{"id":3050,"date":"2023-12-12T13:28:00","date_gmt":"2023-12-12T12:28:00","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=3050"},"modified":"2023-12-12T13:30:38","modified_gmt":"2023-12-12T12:30:38","slug":"angular-interceptors","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2023\/12\/12\/angular-interceptors\/","title":{"rendered":"Angular Interceptors"},"content":{"rendered":"\n<p>Angular interceptors are middleware-like services that can be used to intercept and modify HTTP requests and responses globally within our application. They are useful for implementing cross-cutting concerns such as authentication, error handling, logging, and caching.<\/p>\n\n\n\n<p>An interceptor is essentially a class that implements the HttpInterceptor interface. By implementing this interface, the class can override certain methods that allow code to be executed before the request or after the response.<\/p>\n\n\n\n<p>There are two main methods an interceptor can provide:<\/p>\n\n\n\n<ol><li><strong>Request Interceptors<\/strong> : These methods are executed before the HTTP request is sent. We can use them to modify the request headers, add authentication tokens, or perform any other necessary pre-processing.<\/li><li><strong>Response Interceptors<\/strong> : These methods are executed after the HTTP response is received but before it is passed to the calling code. They allow us to inspect and modify the response, handle errors, or perform post-processing.<\/li><\/ol>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Common Use Cases for Angular Interceptors<\/h4>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">1. Authentication Interceptor<\/span><\/h4>\n\n\n\n<p>An authentication interceptor is used to add authentication tokens to outgoing requests and handle authentication-related errors. This is essential for securing our application\u2019s API requests.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\n\n@Injectable()\nexport class AuthInterceptor implements HttpInterceptor {\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const authToken = 'your-auth-token';\n    const authRequest = request.clone({\n      headers: request.headers.set('Authorization', `Bearer ${authToken}`),\n    });\n    return next.handle(authRequest);\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">2. Error Handling Interceptor<\/span><\/h4>\n\n\n\n<p>An error handling interceptor can be used to centralize error handling for HTTP requests. It can capture HTTP errors, log them, and perform appropriate actions like displaying error messages.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpErrorResponse,\n} from '@angular\/common\/http';\nimport { catchError } from 'rxjs\/operators';\nimport { throwError } from 'rxjs';\n\n@Injectable()\nexport class ErrorInterceptor implements HttpInterceptor {\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    return next.handle(request).pipe(\n      catchError((error: HttpErrorResponse) =&gt; {\n        \/\/ Handle and log the error here\n        console.error('HTTP Error:', error);\n        \/\/ Optionally rethrow the error to propagate it\n        return throwError(error);\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">3. Logging Interceptor<\/span><\/h4>\n\n\n\n<p>A logging interceptor can be used to log the details of HTTP requests and responses, which is helpful for debugging and monitoring.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpResponse,\n} from '@angular\/common\/http';\nimport { tap } from 'rxjs\/operators';\n\n@Injectable()\nexport class LoggingInterceptor implements HttpInterceptor {\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    return next.handle(request).pipe(\n      tap((event) =&gt; {\n        if (event instanceof HttpResponse) {\n          console.log('HTTP Response:', event);\n        }\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">4. Caching Interceptor<\/span><\/h4>\n\n\n\n<p>A caching interceptor can be used to implement client-side caching for HTTP responses, reducing the number of unnecessary network requests.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpResponse,\n  HttpHeaders,\n} from '@angular\/common\/http';\nimport { tap } from 'rxjs\/operators';\n\n@Injectable()\nexport class CacheInterceptor implements HttpInterceptor {\n  private cache = new Map&lt;string, HttpResponse&lt;any&gt;&gt;();\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    if (request.method !== 'GET') {\n      return next.handle(request);\n    }\n\n    const cachedResponse = this.cache.get(request.url);\n\n    if (cachedResponse) {\n      return of(cachedResponse);\n    }\n\n    return next.handle(request).pipe(\n      tap((event) =&gt; {\n        if (event instanceof HttpResponse) {\n          this.cache.set(request.url, event);\n        }\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">5. Headers Interceptor<\/span><\/h4>\n\n\n\n<p>A headers interceptor can be used to add custom headers to outgoing HTTP requests. This is often used to set headers like \u2018Content-Type\u2019 or include API keys.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\n\n@Injectable()\nexport class HeadersInterceptor implements HttpInterceptor {\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const headers = new HttpHeaders({\n      'Content-Type': 'application\/json',\n      'X-API-Key': 'your-api-key',\n    });\n    const headersRequest = request.clone({ headers });\n    return next.handle(headersRequest);\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">6. Loading Indicator Interceptor<\/span><\/h4>\n\n\n\n<p>A loading indicator interceptor can be used to show and hide loading spinners or progress bars during HTTP requests, providing a better user experience.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\nimport { LoadingService } from '.\/loading.service';\nimport { finalize } from 'rxjs\/operators';\n\n@Injectable()\nexport class LoadingInterceptor implements HttpInterceptor {\n  constructor(private loadingService: LoadingService) {}\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    this.loadingService.showLoading();\n    return next.handle(request).pipe(\n      finalize(() =&gt; {\n        this.loadingService.hideLoading();\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">7. Base URL Interceptor<\/span><\/h4>\n\n\n\n<p>A base URL interceptor can be used to prepend a base URL to all HTTP requests, simplifying the configuration of API endpoints.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\n\n@Injectable()\nexport class BaseUrlInterceptor implements HttpInterceptor {\n  private baseUrl = 'https:\/\/api.example.com';\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const apiRequest = request.clone({\n      url: `${this.baseUrl}${request.url}`,\n    });\n    return next.handle(apiRequest);\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">8. Offline Mode Interceptor<\/span><\/h4>\n\n\n\n<p>An offline mode interceptor can be used to detect when the user\u2019s device is offline and handle HTTP requests accordingly, such as storing them for later or showing a friendly message.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpErrorResponse,\n} from '@angular\/common\/http';\nimport { throwError } from 'rxjs';\nimport { catchError } from 'rxjs\/operators';\n\n@Injectable()\nexport class OfflineModeInterceptor implements HttpInterceptor {\n  constructor() {}\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    \/\/ Check if the device is offline\n    if (!navigator.onLine) {\n      \/\/ Handle offline mode (e.g., store requests for later)\n      console.error('Device is offline. Request not sent:', request.url);\n      return throwError(new HttpErrorResponse({ status: 0, statusText: 'Offline' }));\n    }\n\n    return next.handle(request);\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">9. JWT Refresh Token Interceptor<\/span><\/h4>\n\n\n\n<p>A JWT refresh token interceptor can be used to automatically refresh expired JSON Web Tokens (JWTs) and seamlessly continue making authenticated requests.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n  HttpErrorResponse,\n} from '@angular\/common\/http';\nimport { AuthService } from '.\/auth.service';\nimport { catchError, switchMap } from 'rxjs\/operators';\nimport { throwError } from 'rxjs';\n\n@Injectable()\nexport class JwtRefreshInterceptor implements HttpInterceptor {\n  constructor(private authService: AuthService) {}\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    return next.handle(request).pipe(\n      catchError((error: HttpErrorResponse) =&gt; {\n        if (error.status === 401 &amp;&amp; error.error &amp;&amp; error.error.message === 'Token expired') {\n          \/\/ Token expired; attempt to refresh it\n          return this.authService.refreshToken().pipe(\n            switchMap(() =&gt; {\n              \/\/ Retry the original request with the new token\n              const updatedRequest = request.clone({\n                setHeaders: {\n                  Authorization: `Bearer ${this.authService.getAccessToken()}`,\n                },\n              });\n              return next.handle(updatedRequest);\n            }),\n            catchError(() =&gt; {\n              \/\/ Refresh token failed; log out the user or handle the error\n              \/\/ For example, you can redirect to the login page\n              this.authService.logout();\n              return throwError('Token refresh failed');\n            })\n          );\n        }\n        return throwError(error);\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-cyan-blue-color\">10. Request Timing Interceptor<\/span><\/h4>\n\n\n\n<p>A request timing interceptor can be used to measure and log the time taken for each HTTP request, helping us identify performance bottlenecks.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\nimport { tap } from 'rxjs\/operators';\n\n@Injectable()\nexport class RequestTimingInterceptor implements HttpInterceptor {\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const startTime = Date.now();\n    return next.handle(request).pipe(\n      tap(() =&gt; {\n        const endTime = Date.now();\n        const duration = endTime - startTime;\n        console.log(`Request to ${request.url} took ${duration}ms`);\n      })\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h4>11. Localization Interceptor<\/h4>\n\n\n\n<p>A localization interceptor can be used to automatically include the user\u2019s preferred language or locale in HTTP requests, ensuring that the server sends responses in the appropriate language.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\nimport { LocaleService } from '.\/locale.service';\n\n@Injectable()\nexport class LocalizationInterceptor implements HttpInterceptor {\n  constructor(private localeService: LocaleService) {}\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const userLocale = this.localeService.getUserLocale();\n    const localizedRequest = request.clone({\n      setHeaders: {\n        'Accept-Language': userLocale,\n      },\n    });\n    return next.handle(localizedRequest);\n  }\n}<\/code><\/pre>\n\n\n\n<h4>12. Content Security Policy (CSP) Interceptor<\/h4>\n\n\n\n<p>A CSP interceptor can be used to automatically add Content Security Policy headers to outgoing HTTP requests to improve security.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\nimport {\n  HttpInterceptor,\n  HttpRequest,\n  HttpHandler,\n} from '@angular\/common\/http';\n\n@Injectable()\nexport class CspInterceptor implements HttpInterceptor {\n  constructor() {}\n\n  intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler) {\n    const cspHeader = \"default-src 'self'; script-src 'self' 'unsafe-inline'\";\n    const cspRequest = request.clone({\n      setHeaders: {\n        'Content-Security-Policy': cspHeader,\n      },\n    });\n    return next.handle(cspRequest);\n  }\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Using Interceptors in Angular<\/h4>\n\n\n\n<p>To use interceptors in our Angular application, we need to provide them in our module. Here\u2019s an example of how to do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule } from '@angular\/core';\nimport { HttpClientModule, HTTP_INTERCEPTORS } from '@angular\/common\/http';\n\nimport { AppComponent } from '.\/app.component';\nimport { AuthInterceptor } from '.\/auth.interceptor';\nimport { ErrorInterceptor } from '.\/error.interceptor';\nimport { LoggingInterceptor } from '.\/logging.interceptor';\nimport { HeadersInterceptor } from '.\/headers.interceptor';\nimport { LoadingInterceptor } from '.\/loading.interceptor';\n\nimport { BaseUrlInterceptor } from '.\/base-url.interceptor';\n\n\n@NgModule({\n  declarations: &#91;AppComponent],\n  imports: &#91;BrowserModule, HttpClientModule],\n  providers: &#91;\n    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },\n    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },\n    { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },\n    { provide: HTTP_INTERCEPTORS, useClass: HeadersInterceptor, multi: true },\n    { provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true },\n\n    { provide: HTTP_INTERCEPTORS, useClass: BaseUrlInterceptor, multi: true },\n\n  ],\n  bootstrap: &#91;AppComponent],\n})\nexport class AppModule {}<\/code><\/pre>\n\n\n\n<p>In this example, we\u2019ve provided multiple interceptors using the&nbsp;<code>HTTP_INTERCEPTORS<\/code>&nbsp;token, and Angular will apply them in the order they are provided.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 id=\"51bb\">Conclusion<\/h4>\n\n\n\n<p id=\"6751\">Angular interceptors are a powerful tool for handling common HTTP-related tasks in our application. They allow us to centralize and modularize concerns such as authentication, error handling, logging, and caching. By implementing interceptors, we can improve the maintainability and scalability of our Angular applications while keeping our code clean and organized.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h5>Reference:<\/h5>\n\n\n\n<p><a href=\"https:\/\/blog.stackademic.com\/\">https:\/\/blog.stackademic.com\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Angular interceptors are middleware-like services that can be used to intercept and modify HTTP requests and responses globally within our application. They are useful for implementing cross-cutting concerns such as authentication, error handling, logging, and caching. An interceptor is essentially a class that implements the HttpInterceptor interface. By implementing this interface, the class can override [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3052,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[37],"tags":[385,787,590,783,791,789,528,782,781,785,788,790,786,784],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3050"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=3050"}],"version-history":[{"count":2,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3050\/revisions"}],"predecessor-version":[{"id":3053,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3050\/revisions\/3053"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/3052"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}