Briebug Blog

Sharing our thoughts with the community

3 ways to use Angular HTTP Interceptors

3 ways to use Angular HTTP Interceptors


Angular HTTP Interceptors provide a flexible mechanism to control your application when dealing with network-related resources. They’re similar to middle-ware in other frameworks and allow network logic to be abstracted and reused.


Resources To Follow

? Demo App / ? Github



Why use HTTP Interceptors

Interceptors provide a convenient location to apply functionality across all or some network requests and responses. As an application grows, re-implementing the same logic can become tedious, error-prone, and potentially leads to inconsistent functionality.


For example, setting up an Authorization Header across multiple network requests can quickly lead to duplicate code at the service or component level. By utilizing an interceptor it can be configured once and applied on all existing and future HTTP requests. By abstracting global network logic to a single responsibility class, we make it easier to test and build reliable applications quickly.




Intercepting HTTP Requests

Requests can be controlled with the HttpHandler that is passed to interceptor methods. In its simplest usage, if you don’t want to modify the request, you return the handle method. Typically used like this:



This is where you can modify Auth headers or anything else related to the request.



Intercepting Responses

To interact with the response, you’ll pipe off the handle method. From there you can interact with other services such as adding to a cache like you’ll see below or modifying the response in the XML to JSON example.


Be aware that there may be other events besides the response so it’s a good idea to check for an HttpResponse before acting on the response event.




HTTP Interceptor Examples

Caching

Caching, specifically cache invalidation, can be quite difficult so this article will skip the specifics on that. Instead, we’ll look at a simple example that returns something from the cache or allows the request to go through. For a given endpoint you can cache the results in a number of ways and return the cache based on time, existence, or another factor.


The following example checks for the existence in the cache and returns it:



If the request is not in the cache, make the request as normal with sendRequest.



Here we pipe off the handle method to interact with the response and set it in the cache. Now if the same request is made it will be returned immediately.




XML to JSON

Often developers don’t have complete control over how they get data. For example, if you have one API that returns XML but the rest of your app works with JSON it might make sense to convert the XML response to JSON for consistency. With an interceptor, the XML conditional logic can be abstracted from consumers and applied to all network requests.



In order to handle the response, this logic is pipe’ed off of the handle method. Then if the response is valid XML, we return the cloned response event and parse the XML into JSON.




Redirect based on scopes

When an application needs to restrict access to certain routes, an interceptor can provide that functionality in one place across many routes. Since interceptors are run for every request you can organize your route guard logic in one place. Assuming you’ve set up what routes are guarded and can access the user’s available scopes, the interceptor can determine whether to allow the request or redirect.



In this example, if the route isn’t protected we don’t take any action. If it is the request is allowed if the user is an admin otherwise we redirect and cancel the request.




Immutability

It may not be obvious but the HttpRequest and HttpResponse instances are immutable. From the Angular docs

Interceptors are capable of mutating requests and responses, the HttpRequest and HttpResponse instance properties are read-only, rendering them largely immutable.

This is done because the app may retry a request several times and if the interceptor could modify the original request then each subsequent request could be different.


What this means for developers is that you must clone the request and modify that instance:




Interceptor order

Interceptors pass requests through in the order that they’re provided [A,B,C]. The following “barrel” example gathers interceptors to later be provided in their declared order.

Requests will flow in A->B->C and responses will flow out C->B->A.



Then in app.module.ts:




Summary

As we’ve 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.


Helpful links





Originally published at kevinschuchard.com on May 8, 2019.

Thanks to Jon Rista.


Author: Kevin Schuchard, Sr. Enterprise Software Engineer

View Details
- +
Sold Out