I would like error responses, in the response body, from my API server to flow all the way to my component for certain error codes, for example 400 or 422. It works well without an HttpInterceptor in the following implementation.
function handleHttpError() {
return (response: any) => {
let newResponse;
if (response.status === 0) {
// Error connecting to the server
newResponse = { error: 'Error connecting to the server!' }
} else {
// Server returns a response in response.error
newResponse = response.error;
}
return of(newResponse);
};
}
export class MyService {
...
saveTransaction(trans: Transaction): Observable<APIResponseBody> {
return this.http.post<APIResponseBody>(this.transUrl, trans)
.pipe(catchError(handleHttpError()));
}
...
}
export class MyComponent {
...
onSubmit() {
this.myService.saveTransaction(this.data) {
.subscribe((res: APIResponseBody) => {
if (res.error) {
this.toastService.showError(`${res.error}: ${JSON.stringify(res.attributes)}`);
} else if (res.trans) {
this.trans = res.trans;
}
})
}
}
...
}
It does not, however, work when I move the error handling to HttpInterceptor. All non-2xx http errors seem to be filtered by the interceptor in the following implementation:
export class HttpInterceptorService implements HttpInterceptor {
constructor() { }
intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
catchError((response: any) => {
let newResponse;
if (response.status === 0) {
// Error connecting to the server
newResponse = { error: 'Error connecting to the server!' }
} else {
// Server returns a response in response.error
newResponse = response.error;
}
return of(newResponse);
})
);
}
}
}
export class MyService {
...
saveTransaction(trans: Transaction): Observable<APIResponseBody> {
return this.http.post<APIResponseBody>(this.transUrl, trans);
}
...
}
What am I missing in my interceptor implementation?
The interceptor needs to return an Observable<HttpEvent>
, in your case an Observable<HttpResponse>
So instead of returning the newResponse
object directly you just need create a new HttpResponse
and set your response as the body of the response.
export class HttpInterceptorService implements HttpInterceptor {
constructor() { }
intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
catchError((response: any) => {
...
return of(new HttpResponse({ body: newResponse }));
})
);
}
}
cheers