Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a param to HttpInterceptor?

I am using Angular 4.3.1 and HttpClient. There is an HttpInterceptor to set some headers.

In some http get requests I need to set a different header. Is there anyway I can pass some param to this HttpInterceptor for that particular HttpRequest?

@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if(request.custom.param1) // how can i do this 
      request = request.clone({
        setHeaders: {
          'header1': 'xxxxxx'
          }
      });

    else
      request = request.clone({
        setHeaders: {
          'header2': 'yyyyyy'
          }
      });


    return next.handle(request);
  }
}
like image 709
Amitabh Avatar asked Sep 06 '17 12:09

Amitabh


People also ask

How do I use HttpInterceptor?

HTTP Interceptors is a special type of angular service that we can implement. It's used to apply custom logic to the central point between the client-side and server-side outgoing/incoming HTTP request and response. Keep in mind that the interceptor wants only HTTP requests.

Can we have multiple interceptors?

After providing HTTP_INTERCEPTORS we need to inform the class we are going to implement our interceptor into by using useClass. Setting multi to true, makes sure that you can have multiple interceptors in your project.

How do you intercept HTTP response?

HttpInterceptor is an interface that can be implemented by a class and it has only one method that intercepts an outgoing HttpRequest and optionally transform it or the response. That method called intercept. Typically an interceptor will transform the outgoing request before returning next. handle(req) .


3 Answers

Maybe there's a better way to handle this problem, but as a workaround you can create and pass custom HttpParams to request and then check them in the interceptor. For example:

export class CustomHttpParams extends HttpParams {
  constructor(public param1: boolean) {
   super();
  }
}

Using this class in http call:

this.http.get('https://example.com', {
  params: new CustomHttpParams(true)
})

And now in interceptor:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (request.params instanceof CustomHttpParams && request.params.param1) 
    request = request.clone({
      setHeaders: {
        'header1': 'xxxxxx'
      }
    });
  else
    request = request.clone({
      setHeaders: {
        'header2': 'yyyyyy'
      }
    });

  return next.handle(request);
}
like image 197
Aleksey L. Avatar answered Oct 26 '22 05:10

Aleksey L.


I wrote an interceptor for handling Http error responses. I wanted to allow specific Http calls to instruct the interceptor to ignore certain response status codes, while also retaining the ability to pass params to the Http call. Here is the solution I ended up with. (Thanks, Aleksey for the initial idea in your answer).

Extend HttpParams:

import { HttpParams, HttpParamsOptions  } from '@angular/common/http';

// Cause the HttpErrorInterceptor to ignore certain error response status codes like this:
//
//  this.http.get<TypeHere>(`URL_HERE`, {
//    params: new InterceptorHttpParams({ statusCodesToIgnore: [400, 401] }, {
//      complete: 'false',
//      offset: '0',
//      limit: '50'
//    })
//  })

export class InterceptorHttpParams extends HttpParams {
  constructor(
    public interceptorConfig: { statusCodesToIgnore: number[] },
    params?: { [param: string]: string | string[] }
  ) {
    super({ fromObject: params } as HttpParamsOptions);
  }
}

Interceptor:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return next.handle(req).pipe(
    tap({
      error: (error: any) => {
        if (error instanceof HttpErrorResponse) {
          const regEx = /^[4-5][0-9][0-9]$/; // 4XX and 5XX status codes

          if (regEx.test(error.status.toString())) {
              const errorMessage = this.getErrorMessageFromStatus(error.status);

              if (!this._shouldIgnoreError(req, error)) {
                console.log(`ERROR INTERCEPTOR: ${error.status}`);
                this.toastService.alert(errorMessage);
              }
          }
        }
      }
    })
  );
}

// Based on `request.params.interceptorConfig.statusCodesToIgnore`, we can see if we should ignore this error.
_shouldIgnoreError(request: HttpRequest<any>, errorResponse: HttpErrorResponse) {
  if (request.params instanceof InterceptorHttpParams
    && Array.isArray(request.params.interceptorConfig.statusCodesToIgnore)
    && request.params.interceptorConfig.statusCodesToIgnore.includes(errorResponse.status)) {

    return true;
  }

  return false;
}
like image 22
JWess Avatar answered Oct 26 '22 05:10

JWess


In Angular 12+, there's a new attribute HttpRequest.context designed to solve this.

Shared and mutable context that can be used by interceptors https://angular.io/api/common/http/HttpRequest#context

like image 5
btx Avatar answered Oct 26 '22 04:10

btx