1

I am trying to implement a request/response intercept mechanism in Angular4 .I am fairly new to observables.

I maintain two interceptor array , one for request and other for response. Interceptors are nothing but functions which accept request/response object and transforms them.

sendRequest(req:Response):Observable<Response>{
    req= this.processRequest(req);

    This.http.request(req)
           .map( (res:Response)=>{
                return this.processResponse(res)
            })
            .catch(this.handleError)
}

handleError(err:Response):Observable<Response>{
    return Observable.throw(err);
}

Basic error handling works fine . Sometimes for a 401 exception , I want to get new Auth token and retry the same request with updated Auth token.

What I am thinking is to introduce array of error interceptor. One of the error interceptor function would check if it is 401 and would issue a new refresh request to server ,invalidating subsequent error interceptor functions . I assume there is a need to switch the observable stream. The observer will eventually get response from latest request made. How to proceed on this?

NewtonCode
  • 1,322
  • 5
  • 14
  • 25
  • Try this: https://stackoverflow.com/questions/36652495/angular2-http-retry-logic – SrAxi Jun 20 '17 at 13:03
  • Possible duplicate of [Angular2 http retry logic](https://stackoverflow.com/questions/36652495/angular2-http-retry-logic) – Pace Jun 26 '17 at 02:43
  • @Pace My doubt is regarding switching the stream from within an interceptor function. Switchmap works if i am at same level as http.request. – NewtonCode Jun 27 '17 at 04:44
  • Have a look at the answer for this question:https://stackoverflow.com/questions/39928183/angular-2-rxjs-observable-retrywhen-filter-retry-on-error-status/41720854#41720854 – Radu Cojocari Jun 30 '17 at 15:22

2 Answers2

2

Try this:

this.http.get('some/url').retry(2)......

Robin Dijkhof
  • 18,665
  • 11
  • 65
  • 116
0

It seems easier to me to do it at the same level as http.request because otherwise you will need to keep track of all the info to reissue the request but maybe that is no trouble in which case...

I'm guessing your interceptors are operating on the request object itself and returning a copy of the request object? For example, something like...

transformResponse(response) {
  for(let interceptor of interceptors) {
    response = interceptor(response);
  }
  return response;
}

Where interceptor has the following prototype:

interface Interceptor<T> {
  (rsp: T): V;
}

Could you change the interceptor prototype to something like

interface Interceptor<T> {
  (rsp: T): T | Promise<T> | Observable<T>;
}

Then you could do...

transformResponse(responseObs: Observable<any>) {
  for(let interceptor of interceptors) {
    responseObs = responseObs.flatMap(interceptor);
  }
  return responseObs;
}

That would allow an interceptor to return an asynchronous transformation on the response (such as reissuing the request).

Pace
  • 41,875
  • 13
  • 113
  • 156