Search code examples
typescriptangular7angular-httpclientangular-http-interceptorsapi-gateway

HttpRequest getting cancelled when intercepted


Problem

I'm using HttpInterceptor to add the Authorize header to all of my HTTP requests. The requests are sent to AWS API Gateway. But unfortunately all of my requests get cancelled if I'm intercepting them.

If I add the header directly to the request everything works as expected, but as my token is fetched async the first requests will fail, as the token is not yet available. That's why I added the interceptor that looks like the following, where this.getSession() returns an Observable from a Promise:

intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {       
        return this.getSession()
            .mergeMap((session: CognitoUserSession) => {   
                if(session.getIdToken()){
                    request = request.clone({
                        setHeaders: {
                            Authorization: session.getIdToken().getJwtToken()
                        }
                    });  
                }
                return next.handle(request);
         });
    }

The request itself is performed as follows:

getStoreList(): Observable<string[]> {
 let uri = endpoint + 'getStores';
 return this.http.get<string[]>(uri, {headers: httpHeaders}).pipe(
   map((data) => {
     return data;
 }));
}

this.updateHistoryService.getStoreList()
      .subscribe((data: string[]) => {
        this.stores = ["all", ...data];
        this.getData();
});

But this results in: "XHR failed loading: OPTIONS "https://....eu-central-1.amazonaws.com/dev/getStores"" (I'm using CORS, that's why a pre-flight request is sent.)

What I've tried

If I change this line:

return next.handle(request);

to:

return from(next.handle(request).toPromise());

//the following works as well:
return next.handle(request).toPromise();

I can see in the console, that the data is loaded successfully from the server without any requests being cancelled, but my callback is never called that way, so I'm not able to process the data.


Solution

  • I got it working by adding .pipe(takeWhile(() => this.alive)). Looks like this:

    return this.getSession()
       .pipe(takeWhile(() => this.alive))
            .mergeMap((session: CognitoUserSession) => {   
                if(session.getIdToken()){
                    request = request.clone({
                        setHeaders: {
                            Authorization: session.getIdToken().getJwtToken()
                        }
                    });  
                }
                return next.handle(request);
         });