Angular Logging Http Interceptor
June 26, 2018
This page will walk through Angular logging Http Interceptor example. Angular provides HttpInterceptor
interface that is used to intercept HttpRequest
and handle them. HttpInterceptor
provides intercept()
method that generally intercepts outgoing request before calling next interceptor. intercept()
method accepts HttpRequest
and HttpHandler
as arguments. To create interceptor, we need to create a service that will implement HttpInterceptor
and define intercept()
method. Here on this page we will create an interceptor for logging. We will log request method, request URL and request completion time with success or failure message.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 6.0.3
2. Angular CLI 6.0.3
3. TypeScript 2.7.2
4. Node.js 10.3.0
5. NPM 6.1.0
6. In-Memory Web API 0.6.0
Project Structure
Find the project structure of our demo application.my-app | |--src | | | |--app | | | | | |--http-interceptors | | | | | | | |--index.ts | | | |--logging-interceptor.ts | | | | | |--book.ts | | |--book.service.ts | | |--book.component.ts | | |--book.component.html | | | | | |--test-data.ts | | | | | |--app.component.ts | | |--app.module.ts | | | |--main.ts | |--index.html | |--styles.css | |--node_modules |--package.json
Create Logging Interceptor
AngularHttpInterceptor
provides intercept()
method to intercept outgoing request. To create a logging interceptor we need to create a service that will implement HttpInterceptor
interface.
logging-interceptor.ts
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http'; import { finalize, tap } from 'rxjs/operators'; @Injectable() export class LoggingInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler) { const startTime = Date.now(); let status: string; return next.handle(req).pipe( tap( event => { status = ''; if (event instanceof HttpResponse) { status = 'succeeded'; } }, error => status = 'failed' ), finalize(() => { const elapsedTime = Date.now() - startTime; const message = req.method + " " + req.urlWithParams +" "+ status + " in " + elapsedTime + "ms"; this.logDetails(message); }) ); } private logDetails(msg: string) { console.log(msg); } }
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.
Find RxJs
Observable
operators used in our example.
pipe(): It runs functional operators into a chain.
tap(): It performs a side effect for every emission on the source
Observable
and returns Observable
identical to the source, if there is no error.
finalize(): It calls specified function when the source terminates on complete or error and returns
Observable
identical to the source.
Configure Interceptor with Provider
Interceptors are configured with provider as following.{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
const
array as following.
export const httpInterceptorProviders = [ { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true } ];
providers
attribute.
@NgModule({ providers: [ httpInterceptorProviders ], ------ }) export class AppModule { }
Complete Example
logging-interceptor.tsimport { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http'; import { finalize, tap } from 'rxjs/operators'; @Injectable() export class LoggingInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler) { const startTime = Date.now(); let status: string; return next.handle(req).pipe( tap( event => { status = ''; if (event instanceof HttpResponse) { status = 'succeeded'; } }, error => status = 'failed' ), finalize(() => { const elapsedTime = Date.now() - startTime; const message = req.method + " " + req.urlWithParams +" "+ status + " in " + elapsedTime + "ms"; this.logDetails(message); }) ); } private logDetails(msg: string) { console.log(msg); } }
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { LoggingInterceptor } from './logging-interceptor'; export const httpInterceptorProviders = [ { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true } ];
export interface Book { id: number; name: string; category: string; year: string; }
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { Book } from './book'; @Injectable() export class BookService { constructor(private http: HttpClient) { } bookUrl = "/api/books"; getBooks(): Observable<Book[]> { return this.http.get<Book[]>(this.bookUrl); } }
import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { BookService } from './book.service'; import { Book } from './book'; @Component({ selector: 'app-book', templateUrl: './book.component.html' }) export class BookComponent implements OnInit { books$: Observable<Book[]> constructor(private bookService: BookService) { } ngOnInit() { this.getBooks(); } getBooks() { this.books$ = this.bookService.getBooks(); } }
<h3>Book Details</h3> <ul> <li *ngFor="let book of books$ | async" > Id: {{book.id}}, Name: {{book.name}}, Category: {{book.category}}, Year: {{book.year}} </li> </ul>
import { InMemoryDbService } from 'angular-in-memory-web-api'; export class TestData implements InMemoryDbService { createDb() { let bookDetails = [ { id: '101', name: 'Angular 2 by Krishna', category: 'Angular', year: '2015' }, { id: '102', name: 'AngularJS by Krishna', category: 'Angular', year: '2015' } ]; return { books: bookDetails }; } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-book></app-book> ` }) export class AppComponent { }
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { BookComponent } from './book.component'; import { BookService } from './book.service'; import { httpInterceptorProviders } from './http-interceptors/index'; //For InMemory testing import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { TestData } from './test-data'; @NgModule({ imports: [ BrowserModule, HttpClientModule, InMemoryWebApiModule.forRoot(TestData) ], declarations: [ AppComponent, BookComponent ], providers: [ BookService, httpInterceptorProviders ], bootstrap: [ AppComponent ] }) export class AppModule { }
Run Application
To run the application, find the steps.1. Install Angular In-Memory Web API.
npm i angular-in-memory-web-api --save
3. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
4. Run ng serve using command prompt.
5. Access the URL http://localhost:4200
Find the output in console.
GET /api/books succeeded in 506ms
References
HttpInterceptorHttpClient