4

I am having an HTTP Interceptor. The backend API expects custom headers whose values are stored in indexdb during app initialization and other operations. Hence, I need to get the values and pass it with every request. But so far, failing to do so as the interceptor does not wait for the subscription to finish executing and sends requests without the custom headers.

The intercetpor does get the currently saved or default headers but it is too late as the request goes thru without the headers.

indexdb.service.ts:

@Injectable() export class IndexDBService { /* Handles configuration of the app: reading current configuration saving configuration */ private pouch: any; constructor() { this.pouch = new PouchDB("config", { auto_compaction: true }); } currentConfig(): Observable<any> { /* Return the current configuration saved in the database */ let vm = this; return new Observable(observer => { vm.pouch.get("info", function(err, doc) { if (err) { console.log("config read error ", err); // create a default one configOptions={'header1': '1','header2':2} observer.next(configOptions); } else { observer.next(doc); } }); }); } } 

interceptor.ts

import { Injectable } from "@angular/core"; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from "@angular/common/http"; import { Observable } from "rxjs"; import { IndexDBService } from "../services/indexdb.service"; @Injectable() export class InterceptAPICalls implements HttpInterceptor { constructor(private indexdbService: IndexDBService) {} intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { this.indexdbService.currentConfig().subscribe(configData => { console.log(configData); // ==> does work great. I am getting data right req = req.clone({ headers: new HttpHeaders({ "X-Header1": configData["header1"], "X-Header2": configData["header2"] }) }); return next.handle(req); // want this one to return always }); // below is cos the app won't compile and it returns immediately return next.handle(req); } } 

2 Answers 2

8

The intercept function just needs to return an observable. So you start be making a request to the currentConfig() and then switch to the next interceptor when the config is emitted.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return this.indexdbService .currentConfig() .pipe( first(), mergeMap(configData => { req = req.clone({ headers: new HttpHeaders({ 'X-Header1': configData['header1'], 'X-Header2': configData['header2'] }) }); return next.handle(req); }) ); } 
Sign up to request clarification or add additional context in comments.

Comments

5

you can use mergeMap to create async interceptor

intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { return this.indexdbService.currentConfig().pipe(mergeMap(configData => { console.log(configData); // ==> does work great. I am getting data right req = req.clone({ headers: new HttpHeaders({ "X-Header1": configData["header1"], "X-Header2": configData["header2"] }); }); return next.handle(req); }) ); } 

4 Comments

I think this is the right answer. I was going to say to use switchMap, but I realize that this is in an interceptor and it could cancel a previous interceptor.
@cgTag how come? While I have to check Fateh's answer later, I can't get it to work nor compile with multiple errors while your answer worked. the return next gives me Argument of type '{ headers: HttpHeaders; return: Observable<HttpEvent<any>>; }' is not assignable to parameter of type '{ headers?: HttpHeaders; reportProgress?: boolean; params? etc.... while mergeMap(configData) gives Argument of type '(configData: any) => void' is not assignable to parameter of type '(value: any, index: number) => ObservableInput<any>'. Type 'void' is not assignable to type 'ObservableInput<any>'
@NieSelam there are syntax mistake in the source code example. The req.clone has the return statement inside it's code block. The answer that you should use a mergeMap operator is correct but this example has mistakes in it. Nicely formatted code and working examples are important here on stackoverflow.
it's fixed sorry

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.