Angular HttpClient doesnt send data to controller.
I get a error 500 (because username in controller is null) when i try to execute fun().
test.sevice.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class RestService {
private EndPointUrl = 'http://127.0.0.1:8080/api/test';
constructor(public http: HttpClient){}
fun(){
this.test().subscribe((data)=>console.log(data));
}
test(): Observable<string>{
let params = new URLSearchParams();
params.append("grant_type",'password');
params.append('username', 'Name');
let body = params.toString();
let headers = new HttpHeaders();
headers.set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post<string>(this.EndPointUrl, body);
}
}
package.json
...
"dependencies": {
"#angular/common": "4.3.4",
"#angular/compiler": "4.3.4",
"#angular/compiler-cli": "4.3.4",
"#angular/core": "4.3.4",
"#angular/forms": "4.3.4",
"#angular/http": "4.3.4",
"#angular/common/http": "4.3.4",
"#angular/platform-browser": "4.3.4",
"#angular/platform-browser-dynamic": "4.3.4",
...},
Spring MVC Controller:
#RequestMapping(value="/test",
method = RequestMethod.POST,
produces=MediaType.APPLICATION_JSON_VALUE)
public String[] test(HttpServletRequest request){
Map<String, String[]> parameters = request.getParameterMap();
return parameters.get("username");
}
Request from postMan works, and returns some username.
Does anyone know what I'm doing wrong?
What i can see is you're using HttpClient not correctly ... cause it came in angular 4.3.* and is little bit different from the old Http ..
you don't have to do anymore .json() ..so for example:
return this.http.post<string>(this.EndPointUrl, body) //<-- IT DON'T NEED HEADERS F.. ITKNOWS IT'S A application/x-www-form-urlencoded
.map((resp) => {
return resp; //<-- HERE resp is your resp.json()
})
.catch((err)=>{
console.log(err);
}); }
and then your post:
let dataForm = new URLSearchParams();
dataForm.append('userName', "MyUserName");
let body = dataForm.toString();
return this.http.post<string>(this.EndPointUrl, body) //<-- IT DON'T NEED HEADERS F.. ITKNOWS IT'S A application/x-www-form-urlencoded
.map((resp) => {
return resp; //<-- HERE resp is your resp.json()
})
.catch((err)=>{
console.log(err);
}); }
use Http instead of HttpClient:
import {Http} from '#angular/http';
...
constructor(private http: Http) { }
...
Related
import { HttpRequest, HttpHandler, HTTP_INTERCEPTORS } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { TokenService } from "./token.service";
#Injectable({
providedIn: 'root'
})
export class InterceptorService {
constructor(private tokenService: TokenService) {
intercep(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
let intReq = req;
const token = this.tokenService.getToken();
if (token != null) {
intReq = req.clone({
headers: req.headers.set('Authorization','Bearer'+token)
});
}
return next.handle(intReq);
}
}
export const interceptorProvider =[{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
}];
//No reconoce y marca error en interceptor, req, token, next //todos errores no reconoce ni me dice de importar nada //
I have a hard time passing the right angular request to the header. This is my service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpHeaders }
from '#angular/common/http';
import { Utente } from '../model/Utente ';
import { Prodotto } from '../model/Prodotto ';
import { OktaAuthService } from '#okta/okta-angular';
import { Observable, from } from 'rxjs';
import { Carrello } from '../model/Carrello ';
import { userInfo } from 'node:os';
import { getLocaleCurrencyCode } from '#angular/common';
const headers = new HttpHeaders().set('Accept', 'application/json');
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
constructor(
private httpClient:HttpClient, private oktaAuth:OktaAuthService ) {}
getCarr(){
return this.httpClient.get<Carrello[]>('http://localhost:8080/prodotti/utente/vedicarrelloo', {headers} );
}
}
This is my spring method:
#Transactional(readOnly = true)
public List<Carrello> getCarrello(#AuthenticationPrincipal OidcUser utente){
Utente u= utenteRepository.findByEmail(utente.getEmail());
return carrelloRepository.findByUtente(u);
}
In console I get this error (error 500):
https://i.stack.imgur.com/BiONS.png
this error corresponds in my console to "java.lang.NullPointerException: null.
But if I access localhost: 8080, I can see the answer correctly, so I assume there is a problem in passing the request header in angular, can anyone tell me where am I wrong, please? I specify that I get this error only in the methods where the OidcUser is present, the rest works perfectly. Thank you!
You need to send an access token with your request. Like this:
import { Component, OnInit } from '#angular/core';
import { OktaAuthService } from '#okta/okta-angular';
import { HttpClient } from '#angular/common/http';
import sampleConfig from '../app.config';
interface Message {
date: string;
text: string;
}
#Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
failed: Boolean;
messages: Array<Message> [];
constructor(public oktaAuth: OktaAuthService, private http: HttpClient) {
this.messages = [];
}
async ngOnInit() {
const accessToken = await this.oktaAuth.getAccessToken();
this.http.get(sampleConfig.resourceServer.messagesUrl, {
headers: {
Authorization: 'Bearer ' + accessToken,
}
}).subscribe((data: any) => {
let index = 1;
const messages = data.messages.map((message) => {
const date = new Date(message.date);
const day = date.toLocaleDateString();
const time = date.toLocaleTimeString();
return {
date: `${day} ${time}`,
text: message.text,
index: index++
};
});
[].push.apply(this.messages, messages);
}, (err) => {
console.error(err);
this.failed = true;
});
}
}
On the Spring side, if you want it to accept a JWT, you'll need to change to use Jwt instead of OidcUser. Example here.
#GetMapping("/")
public String index(#AuthenticationPrincipal Jwt jwt) {
return String.format("Hello, %s!", jwt.getSubject());
}
I want to implement file download using this Angular 6 code:
Rest API:
private static final Logger LOG = LoggerFactory.getLogger(DownloadsController.class);
private static final String EXTERNAL_FILE_PATH = "/Users/test/Documents/blacklist_api.pdf";
#GetMapping("export")
public ResponseEntity<FileInputStream> export() throws IOException {
File pdfFile = Paths.get(EXTERNAL_FILE_PATH).toFile();
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity.ok().headers(headers).contentLength(pdfFile.length())
.contentType(MediaType.parseMediaType("application/pdf"))
.body(new FileInputStream(pdfFile));
}
Service:
import {Injectable} from '#angular/core';
import {HttpClient, HttpParams} from "#angular/common/http";
import {Observable} from "rxjs/index";
import {environment} from "../../../environments/environment";
import {HttpUtils} from "../common/http-utils";
import { map } from 'rxjs/operators';
import {Http, ResponseContentType} from '#angular/http';
#Injectable({
providedIn: 'root'
})
export class DownloadService {
constructor(private http: HttpClient) {
}
downloadPDF(): any {
return this.http.get(environment.api.urls.downloads.getPdf, {
responseType: 'blob'
})
.pipe(
map((res: any) => {
return new Blob([res.blob()], {
type: 'application/pdf'
})
})
);
}
}
Component:
import {Component, OnInit} from '#angular/core';
import {DownloadService} from "../service/download.service";
import {ActivatedRoute, Router} from "#angular/router";
import {flatMap} from "rxjs/internal/operators";
import {of} from "rxjs/index";
import { map } from 'rxjs/operators';
#Component({
selector: 'app-download',
templateUrl: './download.component.html',
styleUrls: ['./download.component.scss']
})
export class DownloadComponent implements OnInit {
constructor(private downloadService: DownloadService,
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
}
export() {
this.downloadService.downloadPDF().subscribe(res => {
const fileURL = URL.createObjectURL(res);
window.open(fileURL, '_blank');
});
}
}
The file is present in the directory but when I try to download it I get error:
18:35:25,032 WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (default task-2) Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
Do you know how I can fix this issue?
Do I need to add additional configuration in order to download the file via Angular web UI?
I use spring-boot-starter-parent version 2.1.0.RELEASE
FileSaver npmjs.com/package/ngx-filesaver is the best library for file download in Angular6 but it has various issues in ios devices. We fixed it by writing own methods and conditionally handling it .
Component
download() {
this.downloadService.downloadPDF().subscribe(async (res: Blob) => {
if (this.isIOSMobileDevice) {
const file = new File([res], fileName, { type: 'application/pdf' });
const dataStringURL: any = await this.fileService.readFile(file);
this.hrefLink = this.sanitizer.bypassSecurityTrustUrl(dataStringURL);
} else {
saveFile(res, fileName);
}
});
}
export const saveFile = (blobContent: Blob, fileName) => {
const isIOS = (!!navigator.platform.match(/iPhone|iPod|iPad/)) || (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
const blob = new Blob([blobContent], { type: 'application/pdf' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
document.body.appendChild(link);
link.href = url;
link.target = '_self';
link.download = fileName;
link.click();
document.body.removeChild(link);
}
};
File Service
async readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
HTML code
<a *ngIf="isIOSMobileDevice" [href]="hrefLink"
target="_blank">Download</a>
<a *ngIf="!isIOSMobileDevice" href="javascript:;" (click)="download"
target="_blank">Download</a>
For ios Mobile devices ,download method has to be called in prerequisite so that we get hrefLink.
I'm following the step by step tutorial of NativeScript but I'm facing the following issue:
When I try to make a post request through my Angular service I get the following error:
JS: {"message":"The specified content type was not found.","errorCode":611}
My code looks pretty much the same as the one in the official docs from NativeScript:
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { User } from './user';
import { Config } from '../config';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
constructor(private _http: Http) { }
register(user: User): Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const url = `${Config.apiUrl}/Users`;
const body = JSON.stringify({
Username: user.email,
Email: user.email,
Password: user.password
});
return this._http.post(url, body, { headers })
.catch(this.handleErrors);
}
handleErrors(error: Response) {
console.error(JSON.stringify(error.json()));
return Observable.throw(error);
}
}
Component class:
signUp() {
this._user.register(this.user).subscribe(
() => {
alert('Your account has been successfully created.');
this.toggleDisplay();
},
() => {
// errors here...
alert('Unfortunately we were unable to create your account.');
}
);
}
Tested under Android and IOs, both throws the same error.
Isn't application/json the expected Content-Type in this case?
If I change the type I get another error saying that the type is missing or is invalid.
Can someone please point out what am I missing?
I have a problem to find way to make authentication for my angular 2 app. I have API in laravel, and tried to use laravel passport(via password grant). I tested it on Postman and now I need to connect it with angular. I've started looking for some library to do it, but i find only this https://github.com/manfredsteyer/angular-oauth2-oidc
Do you have any ideas on how to connect this? I can not cope with that.
You can make service like this , don't forget to assign the client id and secret.
userservice.ts
import {Injectable} from '#angular/core';
import {Observable} from 'rxjs/Rx';
import {Http, Headers, Response} from '#angular/http';
import {User} from './user';
#Injectable()
export class UserService {
constructor(private http: Http) {
}
private oauthUrl = "http://server.techalin.com/oauth/token";
private usersUrl = "http://server.techalin.com/api/users";
getAccessToken() {
var headers = new Headers({
"Content-Type": "application/json",
"Accept": "application/json"
});
let postData = {
grant_type: "password",
client_id: 2,
client_secret: "RGNmOzt7WQ8SdNiCcJKKDoYrsFqI2tudopFjOJU3",
username: "albanafmeti#gmail.com",
password: "password",
scope: ""
}
return this.http.post(this.oauthUrl, JSON.stringify(postData), {
headers: headers
})
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
getUsers(accessToken: string): Observable<User[]> {
var headers = new Headers({
"Accept": "application/json",
"Authorization": "Bearer " + accessToken,
});
return this.http.get(this.usersUrl, {
headers: headers
})
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
and use this service to other component like this
import 'UserService' from './user.service';
export class ExampleCompoent{
constructor(private userService: UserService) {
this.userService.getAccessToken()
.subscribe(data => {
this.getUsers(data.access_token)
});
}
getUsers(accessToken: string) {
this.userService.getUsers(accessToken)
.subscribe(
users => {
this.users = users;
console.log(users);
});
}
}
read more on this link