I have built an HttpInterceptor
that closely follows the one in the Angular Documentation.
However, I needed to make an asynchronous call as part of my interceptor. I created a StackBlitz with a simplified version of the code (but identical in semantics).
The interceptor looks like:
export class AuthInterceptor implements HttpInterceptor {
constructor(private session: SessionService, private config: ConfigurationService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const apiRoot = this.config.apiUrl;
if (apiRoot && req.url.startsWith(apiRoot)) {
return this.addAuth(req).pipe(switchMap(x => next.handle(x)));
} else {
return next.handle(req);
}
}
private addAuth(original: HttpRequest<any>): Observable<HttpRequest<any>> {
return from(this.session.getToken()).pipe(
map(token => {
const req = original.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return req;
})
);
}
}
It's fairly simple:
- check if the URL we are calling requires our token (
req.url.startsWith()
) - if yes, then fetch our token and add it as a header
- if not, simply continue the pipeline
The ConfigurationService
has a simple string
property named apiUrl
.
The SessionService
has an almost equally simple method named getToken()
which returns a Promise<string>
.
However, I am having a hard time testing this...
My actual test is very simple:
it('should add authorization header for API call', () => {
http.get('bar').subscribe();
httpMock.expectOne(req => req.headers.has('Authorization'));
});
I have mocked the getToken()
and apiUrl
properly so that apiUrl='bar'
and getToken()
returns Promise.resolve('foobar')
.
The problem seems to be only when going through the addAuth()
path. If I test for the counter-case, it works:
it('should NOT add authorization header for non-API call', () => {
http.get('baz').subscribe();
httpMock.expectOne(req => !req.headers.has('Authorization'));
});