HobojoeBr
HobojoeBr

Reputation: 619

Angular 5 - Response HttpInterceptor - retry on timeout (504)

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):

enter image description here

Devtools shows error 504: enter image description here

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

Answers (1)

Max Koretskyi
Max Koretskyi

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

Related Questions