Why we need Interceptors?
Very often we want to enforce or apply behaviour when receiving or sending HTTP requests within our application. We want to perform the tasks like authenticating, logging, updating the request header, error catching etc. for every http request/response. For this we need to do it explicitly for each and every http call which involves lots of energy and time to put.
The reliable and promising solution for this is Interceptor which does all these tasks implicitly.
Interceptors provide a mechanism to intercept and modify the application’s http requests globally before they are sent to the server.
Interceptors can be used to pre and post HTTP requests. Pre-processing happens before requests are executed. This can be used to change request configurations. Post-processing happens once responses have been received. Responses can be transformed via post-processing.
Let’s try to understand the concept with below example.
Create an Interceptor to update the request header to pass the authentication token. If response comes with 401 error, redirect to login page and also log every http request.
This example will cover,
- Packages need to import
- Creating Interceptor
- Updating the request header
- Log every http request.
- Error catching
Let’s create a new interceptors/my.interceptor.ts file with below code where I have created an MyInterceptor class , imported all the packages needed to create an Interceptor and also created an interceptor.
To create an Interceptor, we need to implement the HttpInterceptor interface from @angular/common/http package. Every time our application makes an HTTP request using the HttpClient service, the Interceptor calls the intercept() method.
When the intercept() method is called Angular passes a reference to the httpRequest object. With this request, we can inspect it and modify it as necessary. Once our logic is complete, we call next.handle and return the updated request onto the application.
Interceptor parameters as in above code are
req: HttpRequest – The outgoing request object to be modified
next: HttpHandler – The next interceptor in the chain, or the backend if no interceptors remain in the chain
Observable<HttpEvent<any> – An observable of the event stream.
Now to wire-up our interceptor, let’s provide it in the app module or a feature module using the HTTP_INTERCEPTORS token:
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 . If you import HttpClientModule multiple times across different modules (for example, in lazy loading modules), each import creates a new copy of the HttpClientModule, which overwrites the interceptors provided in the root module.
You can define multiple interceptors by defining it in provider like this:
Angular applies interceptors in the order that you provide them in your module’s providers.
You cannot change the order or remove interceptors later. If you need to enable and disable an interceptor dynamically, you’ll have to build that capability into the interceptor itself.
Now let’s update the interceptor in interceptors/my.interceptor.ts.
Above Interceptor will do the following tasks:
- Write the http request url to console(You can write a code to log it into a log file)
- Add the token to request header
- Navigate to login page if response is 401 error
By calling catchError through a pipe we are able to handle response errors from the server for that request. Therefore, we are allowed to verify its status and do our treatment as required.
Interceptors can be very useful for multiple purposes on all sorts of applications. You just need to understand what you need and how you can achieve it using Interceptor.