Angular 6 Http Interceptor - with Node.js RestAPIs

https://grokonez.com/frontend/angular/angular-6/angular-6-http-interceptor-with-node-js-restapis

Angular provides HTTP Interception to inspect and transform HTTP requests from your application to the server. In the tutorial, we show how to build an Angular 6 Http Log Interceptor with Node.js RestAPIs.

Related posts:

Technologies

  • Angular 6
  • RxJS 6
  • Bootstrap 4
  • Visual Studio Code – version 1.24.0
  • Nodejs – v8.11.3

Angular HTTP Interception

@angular/common/http has a major feature HTTP Interception that helps inspect and transform HTTP requests.

Example Log Interceptor:


import { HTTP_INTERCEPTORS } from '@angular/common/http';

import { Injectable } from '@angular/core';
import {
  HttpEvent, HttpInterceptor, HttpHandler,
  HttpRequest, HttpResponse
} from '@angular/common/http';

import { finalize, tap } from 'rxjs/operators';
import { LogService } from './log.service';

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  constructor(private log: LogService) {}

  intercept(req: HttpRequest, next: HttpHandler) {
    const started = Date.now();
    let ok: string; 

    // Log - start request
    this.log.add("Start request -> " + `${req.method} ${req.urlWithParams}`);

    return next.handle(req)
      .pipe(
        tap(
          // Success Path
          event => ok = event instanceof HttpResponse ? 'succeeded' : '',
          // Fail Path
          error => ok = 'failed'
        ),
        // Log when response observable either completes or errors
        finalize(() => {
          const elapsed = Date.now() - started;
          const log = `${req.method} ${req.urlWithParams}
             ,  ${ok} in ${elapsed} ms.`;

          // Log - end response
          this.log.add("End request: " + log);
        })
      );
  }
}

export const httpInterceptorProviders = [
    { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
];

The intercept method transforms a request into an Observable.
interceptors inspect the request on the way in and forward the request to the handle() method of the next object.
handle() method transforms an HTTP request into an Observable of HttpEvents which include the server's response.

What is next object?
-> The next object represents the next interceptor in the chain of interceptors. The final next in the chain is the Angular HttpClient handler.

How to provide the interceptor?
-> Firstly, importing HTTP_INTERCEPTORS, injection token from @angular/common/http,


import { HTTP_INTERCEPTORS } from '@angular/common/http';

...

export const httpInterceptorProviders = [
    { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
];

-> Then add it to the AppModule providers array:


@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    httpInterceptorProviders
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now you define a simple Angular Http Get request as below:


export class CustomerService {
  private customersUrl = 'http://localhost:8080/api/customers';  // URL to web api
  private handleError: HandleError;

  constructor( 
    private http: HttpClient,  
    httpErrorHandler: HttpErrorHandler,
    private logService: LogService
  ) { 
    this.handleError = httpErrorHandler.createHandleError('CustomerService');
  }

  getCustomers (): Observable {
    const message = "Info -> Function:  getCustomers. Url: " + this.customersUrl;
    this.logService.add(message);

    return this.http.get(this.customersUrl)
    .pipe(
      retry(3),
      catchError(this.handleError('getCustomers', []))
    );
  }

-> Logs with successful response:

angular-6-httpclient-log-interceptor-example-with-nodejs-backend + log results when successfully

-> Logs when Server die -> failed response:

angular-6-httpclient-log-interceptor-example-with-nodejs-backend + log results when fail

Practice

We create 2 projects:

  • Angular project:

angular-6-httpclient-log-interceptor-example-with-nodejs-backend + project structure

  • Node.js project:

angular-6-httpclient-log-interceptor-example-with-nodejs-backend + nodejs structure

For both projects {Angular, Node.js}, we re-use sourcecodes of the tutorials ->

Error Handler Angular 6 HttpClient – catchError + retry – with Node.js/Express example

What do we build more in the tutorial?
-> With Angular project, to do list:

  • Create Log Service
  • Create Log Component
  • Implement Log Interceptor
  • Integrate LogService with Customer Service

-> With Node.js RestAPIs, we re-use all the sourcecode in Error Handler Angular 6 HttpClient post.

Create Log Service

/src/app/log.service.ts ->


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class LogService {
  logs: string[] = [];

  add(log: string) {
    this.logs.push(log);
  }

  removeAll() {
    this.logs = [];
  }
}

Create Log Component

  • src/app/log/log.component.ts ->

import { Component, OnInit } from '@angular/core';
import { LogService } from '../log.service';

@Component({
  selector: 'app-log',
  templateUrl: './log.component.html'
})
export class LogComponent{
  constructor(public logService: LogService) {}
}
  • src/app/log/log.component.html ->
<div *ngIf="logService.logs.length">
  <h3>Logs</h3>
  <button type="button" class="btn btn-dark" (click)="logService.removeAll()">clear</button>
  <br>
  <ol>
    <li *ngFor='let log of logService.logs'> {{log}} </li>
  </ol>
</div>

Implement Log Interceptor

  • src/app/log-interceptor.ts ->

import { HTTP_INTERCEPTORS } from '@angular/common/http';

import { Injectable } from '@angular/core';
import {
  HttpEvent, HttpInterceptor, HttpHandler,
  HttpRequest, HttpResponse
} from '@angular/common/http';

import { finalize, tap } from 'rxjs/operators';
import { LogService } from './log.service';

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  constructor(private log: LogService) {}

  intercept(req: HttpRequest, next: HttpHandler) {
    const started = Date.now();
    let ok: string; 

    // Log - start request
    this.log.add("Start request -> " + `${req.method} ${req.urlWithParams}`);

    return next.handle(req)
      .pipe(
        tap(
          // Success Path
          event => ok = event instanceof HttpResponse ? 'succeeded' : '',
          // Fail Path
          error => ok = 'failed'
        ),
        // Log when response observable either completes or errors
        finalize(() => {
          const elapsed = Date.now() - started;
          const log = `${req.method} ${req.urlWithParams}
             ,  ${ok} in ${elapsed} ms.`;

          // Log - end response
          this.log.add("End request: " + log);
        })
      );
  }
}

export const httpInterceptorProviders = [
    { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true }
];
  • Add LogInterceptor to providers array of AppModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { FormsModule }   from '@angular/forms';
import { HttpClientModule }    from '@angular/common/http';

import { AppRoutingModule }     from './app-routing/app-routing.module';

import { AppComponent } from './app.component';
import { CustomerComponent } from './customer/customer.component';
import { CustomerDetailsComponent } from './customer-details/customer-details.component';
import { AddCustomerComponent } from './add-customer/add-customer.component';

import { HttpErrorHandler } from'./http-error-handler.service';
import { httpInterceptorProviders } from './log-interceptor'
import { LogComponent } from './log/log.component';
import {LogService} from './log.service'

@NgModule({
  declarations: [
    AppComponent,
    CustomerComponent,
    CustomerDetailsComponent,
    AddCustomerComponent,
    LogComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [
    HttpErrorHandler, 
    LogService,
    httpInterceptorProviders
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Integrate LogService with Customer Service

src/app/customer.service.ts ->


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

import { Customer } from './customer';

import { HttpErrorHandler, HandleError } from './http-error-handler.service';
import { LogService } from './log.service';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable({
  providedIn: 'root'
})
export class CustomerService {
  private customersUrl = 'http://localhost:8080/api/customers';  // URL to web api
  private handleError: HandleError;

  constructor( 
    private http: HttpClient,  
    httpErrorHandler: HttpErrorHandler,
    private logService: LogService
  ) { 
    this.handleError = httpErrorHandler.createHandleError('CustomerService');
  }

  getCustomers (): Observable {
    const message = "Info -> Function:  getCustomers. Url: " + this.customersUrl;
    this.logService.add(message);

    return this.http.get(this.customersUrl)
    .pipe(
      retry(3),
      catchError(this.handleError('getCustomers', []))
    );
  }

  getCustomer(id: number): Observable {
    const url = `${this.customersUrl}/${id}`;

    const message = "Info -> Function:  getCustomer. Url: " + url;
    this.logService.add(message);

    console.log(message);

    return this.http.get(url)    
      .pipe(
        retry(3),
        catchError(this.handleError('addCustomer', null))
      );
  }

  addCustomer (customer: Customer): Observable {
    const message = "Info -> Function:  addCustomer. Url: " + this.customersUrl;
    this.logService.add(message);

    console.log(message);

    return this.http.post(this.customersUrl, customer, httpOptions)
      .pipe(
        retry(3),
        catchError(this.handleError('addCustomer', customer))
      );
  }

  deleteCustomer (customer: Customer | number): Observable {
    const id = typeof customer === 'number' ? customer : customer.id;
    const url = `${this.customersUrl}/${id}`;

    const message = "Info -> Function:  deleteCustomer. Url: " + url;
    this.logService.add(message);

    console.log(message);

    return this.http.delete(url, httpOptions)      
      .pipe(
        retry(3),
        catchError(this.handleError('deleteCustomer', null))
      );
  }

  updateCustomer (customer: Customer): Observable {
    const message = "Info -> Function:  updateCustomer. Url: " + this.customersUrl;
    this.logService.add(message);

    console.log(message);

    return this.http.put(this.customersUrl, customer, httpOptions)
      .pipe(
        catchError(this.handleError('updateCustomer', null))
      );
  }
}

SourceCode

https://grokonez.com/frontend/angular/angular-6/angular-6-http-interceptor-with-node-js-restapis

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

Male avatar

loveprogramming

545 bài viết.
98 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
Male avatar
1 0
Tutorial Link: (Link) (Ảnh) Django is a Pythonbased free and opensource web framework that follows the modeltemplateview architectural pattern. A...
loveprogramming viết 7 tháng trước
1 0
Male avatar
1 0
https://loizenai.com/angular11nodejspostgresqlcrudexample/ Angular 11 Node.js PostgreSQL Crud Example (Ảnh) Tutorial: “Angular 11 Node.js Postg...
loveprogramming viết 6 tháng trước
1 0
Male avatar
1 0
Angular Spring Boot jwt Authentication Example Github https://loizenai.com/angularspringbootjwt/ (Ảnh) Tutorial: ” Angular Spring Boot jwt Authe...
loveprogramming viết 6 tháng trước
1 0
Bài viết liên quan
Male avatar
1 0
https://loizenai.com/angular11nodejspostgresqlcrudexample/ Angular 11 Node.js PostgreSQL Crud Example (Ảnh) Tutorial: “Angular 11 Node.js Postg...
loveprogramming viết 6 tháng trước
1 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


Male avatar
{{userFollowed ? 'Following' : 'Follow'}}
545 bài viết.
98 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!