What is Interceptor in Angular
Angular Interceptor is a powerful feature that can be used in many ways for securing and handling many HTTP related phenomena. Interceptors provide a mechanism to intercept and or mutate outgoing requests or incoming responses.
What is the use of Interceptors in Angular
There is numerous use of interceptors in any Angular application. There are the following
Setting request headers in HTTP Calls using interceptors.
Authenticate HTTP calls by setting security tokens.
Change the response from the HTTP service call before it is used by the code block.
Use it for global error handling in your application.
Showing global spin loader or progress bar for each HTTP call.
Creating HTTP Interceptors in Angular
Now lets learn various HTTP interceptor examples. We are going to learn different use cases of interceptors in an angular app.
To implement an interceptor you will want to create a class that is injectable and that implements HttpInterceptor. The class should define an intercept method to correctly implement HttpInterceptor. The intercept method takes two arguments req and next and returns an observable of type HttpEvent.
req is the request object itself and is of type HttpRequest.
next is the HTTP handler of type HttpHandler. The handler has a handle method that returns our desired HttpEvent observable.
Add Request Header using Interceptors
In this example we will learn how to change the HTTP request header using the interceptor. Lets create a new interceptor customheaderInterceptor class in our project.
Once you create interceptor class import these dependencies in the same class file.
import Injectable from angularcore
import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse from angularcommonhttp
Put Injectable directive on customheaderInterceptor class. Now implement the class with HttpInterceptor.
Here is the code.
import Injectable from angularcore import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse from angularcommonhttp Injectable export class CustomHeaderInterceptor implements HttpInterceptor intercept req HttpRequest any next HttpHandler import rxjs Observable HttpEvent any throw new Error Method not implemented
HttpRequest It is an outgoing HTTP request. It provides getters to fetch request properties such as method urlWithParams etc.
HttpHandler It transforms an HttpRequest into a stream of HttpEvent. HttpHandler provides handle method to dispatch request from first interceptor to second and so on.
HttpResponse It is a full HTTP response. It has getter methods such as body headers status url etc.
Configure HTTP Interceptors in AppModule
To use the same instance of HttpInterceptors for the entire app import the HttpClientModule only in your AppModule and add the interceptors to the root application injector.
Interceptors are configured in AppModule like below.
provide HTTPINTERCEPTORS useClass Your Interceptor multi true
If there are multiple interceptors you can create a constant and configure them in this constant.
export const httpInterceptorProviders provide HTTPINTERCEPTORS useClass Interceptor1 multi true provide HTTPINTERCEPTORS useClass Interceptor2 multi true provide HTTPINTERCEPTORS useClass Interceptor3 multi true
Lets see how to declare HTTP Interceptors in our AppModule file.
import BrowserModule from angularplatform browser import NgModule from angularcore import AppComponent from appcomponent import HTTPINTERCEPTORS from angularcommonhttp import CustomHeaderInterceptor from appcustom header interceptor NgModule declarations AppComponent imports BrowserModule providers provide HTTPINTERCEPTORS useClass CustomHeaderInterceptor multi true bootstrap AppComponent export class AppModule
Now in order to change the HTTP request header we need a mock service.
Lets add a custom header in request via the interceptor.
req req.clone headers req.headers.setcustom header ZeptoBook return next.handle(req)
Here is the complete code of our interceptor for changing the request header.
import Injectable from angularcore import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse from angularcommonhttp Injectable export class CustomHeaderInterceptor implements HttpInterceptor intercept req HttpRequest any next HttpHandler import rxjs Observable HttpEvent any req req.clone headers req.headers.setcustom header ZeptoBook return next.handle(req)
Finally here is our HTTP call to mock service.
import Component OnInit from angularcore import HttpClient from angularcommonhttp Component selector app root templateUrl app.component.html styleUrls app.component.css export class AppComponent implements OnInit title interceptorapp constructorprivate http HttpClient ngOnInit this.http.gethttpww.mocky.iov2 5e4605113300006700025eab.subscribe data console.logdata
Cross Site Request Forgery XSRF or CSRF protection by Interceptors
HTTP interceptors provide security from Cross Site Request Forgery XSRF or CSRF by reading a token from cookie by default XSRF TOKEN and sets it as an HTTP header X XSRF TOKEN.
Cross site request forgery also known as one click attack or session riding and abbreviated as CSRF sometimes pronounced sea surf or XSRF is a type of malicious exploit of a website where unauthorized commands are transmitted from a user that the web application trusts wikipedia
By default an interceptor sends this cookie on all mutating requests ie POST PUT DELETE etc to relative URLs but NOT on GET HEAD requests since they are read only or on requests with an absolute URL since it is a different domain altogether.
To take advantage of this the server needs to set a token in a JS readable session cookie called XSRF TOKEN on either the page load or the first GET request.
On subsequent requests the server can verify that the cookie matches the X XSRF TOKEN HTTP header and thus be sure that only code running on your domain has sent this request.
Global Error Handling using Interceptors
Using the interceptor you can handle global errors that can happen across your application. Interceptors are the centralized system that takes care of your all HTTP requests and responses.
Since every request you are making goes trough this interceptor we can also use this interceptor to catch all requests that return as an instance of HttpErrorResponse.
In the below code I changed my interceptor to catch an HTTP error for the wrong service URL.
import Injectable from angularcore import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse HttpErrorResponse from angularcommonhttp import throwError from rxjs import catchError from rxjsoperators Injectable export class CustomHeaderInterceptor implements HttpInterceptor intercept req HttpRequest any next HttpHandler import rxjs Observable HttpEvent any return next.handle(req).pipecatchErrorerror HttpErrorResponse if error.status 401 alerterror.message return throwErrorerror
It will show an error alert on page load.
Using Angular Interceptors for Logging or Profiling
You can use the Angular interceptor for application logging purposes.
import Injectable from angularcore import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse HttpErrorResponse from angularcommonhttp import throwError from rxjs import catchError tap from rxjsoperators Injectable export class CustomHeaderInterceptor implements HttpInterceptor intercept req HttpRequest any next HttpHandler import rxjs Observable HttpEvent any if req.method GET const time new Date.getTime.toString const dupReq req.clone params req.params.setnocache time return next.handledupReq.pipe(taphttpEvent HttpEvent any this.logResponsehttpEvent )) return next.handle(req).pipe(taphttpEvent HttpEvent any this.logResponsehttpEvent )) private logResponsehttpEvent HttpEvent any void if httpEvent instanceof HttpResponse console.logInterceptor Logging console.loghttpEvent
Mock Backend Using Angular Interceptors
There are times when we have to work fastly but server side backend APIs are not ready to work. So Angular provides you a facility to create your own mock backend service using the interceptor.
import Injectable from angularcore import HttpInterceptor HttpHandler HttpRequest HttpEvent HttpResponse HttpErrorResponse from angularcommonhttp import throwError of from rxjs import catchError tap from rxjsoperators const mockData cars name BMW model 2020 name Audi model 2019 Injectable export class CustomHeaderInterceptor implements HttpInterceptor intercept req HttpRequest any next HttpHandler import rxjs Observable HttpEvent any if req.method GET req.url httplocalhost4200cars return ofnew HttpResponse status 200 body mockData next.handle(req)
Change Url by Interceptors
You cannot directly change HTTPRequest and HTTPResponse instance properties because they are readonly and immutable.
They are immutable for a good reason the app may retry a request several times before it succeeds which means that the interceptor chain may re process the same request multiple times. If an interceptor could modify the original request object the retried operation would start from the modified request rather than the original. Immutability ensures that interceptors see the same request for each try As per Angular Docs
Since these are read only you cannot change url by using any string function like replace.
req.url req.url.replacehttp https
To alter the request clone it first and modify the clone before passing it to nexthandle. You can clone and modify the request in a single step as in this example.
clone request and replace http with https at the same time const httpsReq req.clone url req.url.replacehttp https return nexthandlehttpsReq
Summary
Interceptors were a great addition in Angular 4.3 and had many excellent use cases as we have seen here. As we have seen in these examples interceptors provide a straightforward mechanism to interact with HTTP requests and responses. This makes it easy to add layers of control and provide more functionality throughout an application without duplicating logic.
Further Reading
Understanding Angular Modules and Its Types
How Change Detection Works In Angular
Testing Angular App With Karma And Jasmine
Best Chrome Extensions For Debugging Angular Apps