mutlugazete.com

Utilizing HttpContext in Angular for Flexible Interceptors

Written on

Dynamic Interceptors in Angular

In Angular, interceptors are essential for implementing centralized functionality for HTTP requests. They can handle tasks such as adding authorization tokens to API calls, retrying requests upon failure, returning cached responses, or redirecting users to an error page during HTTP errors. However, there are scenarios where we might want to introduce exceptions to this behavior.

Understanding Exceptions in Interceptors

Interceptors function similarly to fixed functions without parameters. For instance:

// Fixed function

function double() {

return 2 * 2;

}

This function is static and consistently returns the same output. In contrast, a more flexible version allows for dynamic input:

// Generic function

function double(x) {

return x * x;

}

Just like the flexible function, we can enhance the rigidity of interceptors. By default, any logic written within an interceptor executes for every API request. However, there may be instances where you want to:

  • Exclude specific API calls from caching.
  • Prevent navigation to the error page for certain failed requests.
  • Omit the addition of an auth token for particular HTTP requests.

Is it possible to make interceptors more dynamic, akin to functions that accept parameters?

Introducing HTTP Context

With the release of Angular version 12, HttpContext was introduced, allowing developers to pass metadata to HTTP interceptors. This feature enables users to send arbitrary data during an HTTP call via the HTTPClient.

The HttpContext operates similarly to a map, using a map internally to store values:

export class HttpContext {

private readonly map = new Map<HttpContextToken<unknown>, unknown>();

// All the map functions

set<T>(token: HttpContextToken<T>, value: T): HttpContext

get<T>(token: HttpContextToken<T>): T

delete(token: HttpContextToken<unknown>): HttpContext

has(token: HttpContextToken<unknown>): boolean

keys(): IterableIterator<HttpContextToken<unknown>>

}

The key to this map is based on a simple class known as an HTTP context token.

HTTP Context Token Example

Using Class Tokens for Enhanced Safety

Employing a class as a key rather than a simple string offers two significant advantages:

  1. It allows the pre-definition of context tokens, thus limiting the context to specific tokens rather than arbitrary keys.
  2. It promotes type safety by specifying the value type while creating the token.

Example: Implementing HTTP Context

Let’s consider an example involving an interceptor that redirects users to an error page for HTTP failures:

@Injectable()

export class ErrorResponseInterceptor implements HttpInterceptor {

intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {

return next.handle(req).pipe(

catchError((err: unknown) => {

this.router.navigateToUrl('/server-error');

return EMPTY;

})

);

}

}

In cases where we don't want to redirect the user during specific API failures, we can utilize HTTP context to communicate that intent.

Creating an HTTP Context

First, we need to establish a context token:

export const BYPASS_ERROR_PAGE = new HttpContextToken<boolean>(() => false);

Here, we define a boolean type with a default value of false. Next, we create our context:

const context = new HttpContext();

context.set(BYPASS_ERROR_PAGE, true);

Finally, we can pass this context during the API call:

getStats(): Observable<StatsResponse> {

return this.http.get<StatsR>(BASE_API/${stats}, { context });

}

Using HTTP Context in Interceptors

We can retrieve the context from the API request by utilizing the context token:

const context = request.context.get(BYPASS_ERROR_PAGE);

This allows us to avoid redirecting the user during an API failure:

@Injectable()

export class ErrorResponseInterceptor implements HttpInterceptor {

intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {

const errorBypass = request.context.get(BYPASS_ERROR_PAGE) === true;

return next.handle(req).pipe(

catchError((err: unknown) => {

if (!errorBypass) {

this.router.navigateToUrl('/server-error');

}

return EMPTY;

})

);

}

}

Conclusion

In many applications, handling HTTP requests under varying conditions is crucial. HttpContext empowers developers to create dynamic interceptors with type safety. By utilizing context tokens, we can pass arbitrary data to interceptors, enhancing their flexibility.

Discover how to effectively use Http Interceptor in Angular 17 by watching this video.

Learn to build your first Angular HTTP Interceptor with this tutorial.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Exploring the Power and Limitations of GPT-3

Discover the capabilities and challenges of GPT-3, the groundbreaking language model from OpenAI, and learn how to utilize it effectively.

India's Rising Influence: The Next Technological Powerhouse

India emerges as a key player in global tech, facing challenges while seizing opportunities amid U.S.-China tensions.

Harvard Business School: The Launchpad for Billionaires

Discover how Harvard Business School has produced more billionaires than its competitors and learn about the remarkable journey of Mark Stevens.