J'ai un intercepteur qui ajoute un jeton dans les en-têtes. Cependant, si je l'utilise après une demande POST, mon observateur dans l'abonnement n'est pas déclenché.
Intercepteur:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.authService = this.inj.get(AuthService);
if (!this.authService.isLoggedIn()) {
return next.handle(req);
}
const changedReq = req.clone({headers: req.headers.set('Authorization', `Bearer ${this.authService.getToken()}`)});
return next.handle(changedReq);
}
Un service:
saveBeer(beerForm: BeerForm): Observable<Response> {
let body = JSON.stringify(beerForm);
let headers = new HttpHeaders({
'Content-Type': 'application/json'
});
return this.http.post(this.apiUrl, body, {headers: headers});
}
Composant:
onSubmitCreateBeer(): void {
this.beerService.saveBeer(this.beerForm)
.takeUntil(this.ngUnsubscribe)
.subscribe(
(response: Response) => {
// On response
this.router.navigate(['/beers']);
}, error => {
// On error
}, () => {
// On complete
});
}
Mon problème est que la réponse n'est jamais déclenchée, donc mon étape de navigation ne fonctionne pas. Si je désactive l'intercepteur, tout fonctionne.
Des idées?
Je l'ai fait travailler. Le problème était que mon observateur attendait JSON dans sa réponse. Cependant, après avoir obtenu 200 OK, la réponse ne contient plus rien dans le corps. C'est une erreur, la fonction d'erreur a donc été appelée.
La solution 1 consiste à définir responseType: text.
saveBeer(beerForm: BeerForm): Observable<any> {
let body = JSON.stringify(beerForm);
let headers = new HttpHeaders({
'Content-Type': 'application/json'
});
return this.http.post(this.apiUrl, body, {headers: headers, responseType: 'text'});
}
La solution 2 consiste à renvoyer 204 à partir du backend.
Les deux fonctionnent bien pour l'instant. Il y a un rapport de bogue à ce sujet:
Ma solution de contournement est un HttpInterceptor qui intercepte les erreurs lorsque le code d'état est 200 et renvoie une HttpResponse avec un corps nul (à la place de HttpClient avec 204 réponses Non contenu):
@Injectable()
export class EmptyResponseBodyErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.catch((err: HttpErrorResponse) => {
if (err.status == 200) {
const res = new HttpResponse({
body: null,
headers: err.headers,
status: err.status,
statusText: err.statusText,
url: err.url
});
return Observable.of(res);
} else {
return Observable.throw(err);
}
});
}
}