Reputation: 619
I tried implementing an HttpInterceptor to retry requests that timeout. I implemented the following code, but err does not contain the status code, hence it doesn't work.
@Injectable()
export class RetryInterceptor implements HttpInterceptor {
constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.retryWhen(error => {
return error
.flatMap((err) => {
if (err instanceof HttpErrorResponse && err.status === 504) { // timeout
return Observable.of(err.status).delay(5000);
}
return Observable.throw({ error: 'No retry' });
})
.take(1)
.concat(Observable.throw({ error: 'Sorry, there was an error (after 5 retries)' }));
});
}
}
The err object has the following object (notice that status is 0):
Can anyone help me?
Thanks in advance!
---- UPDATE ---- After a deeper analysis I found out that the problem is that I have another interceptor that adds the Auth header to my requests. I created a stackblitz sample to show this problem: https://stackblitz.com/edit/angular-interceptors-azhwak In the above example you can check that the error code is always 0 (zero), even though the error is 504. If you comment out the other interceptor (I2) the code works as expected.
Not sure if I am doing something wrong or if I shouldn't have multiple interceptors (some updating the request, and some the response)?
UPDATE 2
User @AngularInDepth.com was right, the problema was that CORS wasn't being provided. Managed to get it working using a different service. But now I am facing a different issue, I'd like to only call the second Interceptor (I2) after the first retry. Is there a way to do it?
See the updated example: https://stackblitz.com/edit/angular-interceptors-ckbvsb
Thanks
Upvotes: 2
Views: 3120
Reputation: 105547
The problem is with the service https://httpstat.us/504
itself. It doesn't handle CORS correctly when you add a custom header to the request and hence the XHR request errors instead of making a request. When the XHR errors, you get a status of 0
because no request was made. Here is the plunker that demonstrates that and the code:
request() {
const url = 'https://httpstat.us/504';
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
// when commented out `onload` handler is executed, otherwise `onerror`
// xhr.setRequestHeader('any', 'any');
xhr.onload = () => {console.log('loaded')};
xhr.onerror = () => {console.log('errror')};
xhr.send();
}
Upvotes: 2