Categories
Angular JavaScript TypeScript

Advanced Usage of the Angular HTTP Client

Spread the love

Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.

In this article, we’ll look at how to make PUT and DELETE requests with the Angular HTTP Client and using HTTP interceptors.

Making a DELETE Request

We can use the delete method to make a DELETE request by passing in the request URL as the first argument and an request options object as the 2nd argument

For example, we can use it as follows:

app.component.ts :

import { Component } from "@angular/core";  
import { HttpClient, HttpHeaders } from "@angular/common/http";

@Component({  
  selector: "app-root",  
  templateUrl: "./app.component.html",  
  styleUrls: ["./app.component.css"]  
})  
export class AppComponent {  
  constructor(private http: HttpClient) { } ngOnInit() {  
    this.getPost();  
  } 

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

    this.http  
      .delete("https://jsonplaceholder.typicode.com/posts/1", httpOptions)  
      .subscribe(res => console.log(res));  
  }  
}

In the code above, we call the delete method with the URL and httpOptions .

Then we call subscribe to initiate the request. The subscribe callback’s parameter has the response content.

Making a PUT Request

A PUT request can be made with the put method. It’s similar to the post method except it makes a PUT request.

The first argument is the URL, the 2nd is the request body, and the 3rd argument is the request options object.

For example, we can write the following:

app.component.ts :

import { Component } from "@angular/core";  
import { HttpClient, HttpHeaders } from "@angular/common/http";  
import { Post } from "./post";

@Component({  
  selector: "app-root",  
  templateUrl: "./app.component.html",  
  styleUrls:["./app.component.css"]  
})  
export class AppComponent {  
  constructor(private http: HttpClient) {}  

  ngOnInit() {  
    this.addPost();  
  } 

  addPost() {  
    const body = {  
      userId: 1,  
      title: "title",  
      body: "body"  
    }; 

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

    this.http  
      .put<Post>(  
        "https://jsonplaceholder.typicode.com/posts/",  
        body,  
        httpOptions  
      )  
      .subscribe(res => console.log(res));  
  }  
}

HTTP Interceptors

We can create and use HTTP interceptors to inspect and transform HTTP requests from our app to the server.

They can also be used to inspect and transform the server’s response on their way back to the app.

Multiple interceptors form a forward and backward chain of request/response handlers.

We can create and use our interceptor as follows:

http-req-interceptor.ts :

import { Injectable } from "@angular/core";  
import {  
  HttpEvent,  
  HttpInterceptor,  
  HttpHandler,  
  HttpRequest  
} from "@angular/common/http";
import { Observable } from "rxjs";

@Injectable()  
export class HttpReqInterceptor implements HttpInterceptor {  
  intercept(  
    req: HttpRequest<any>,  
    next: HttpHandler  
  ): Observable<HttpEvent<any>> {  
    return next.handle(req);  
  }  
}

app.module.ts :

import { BrowserModule } from "@angular/platform-browser";  
import { NgModule } from "@angular/core";  
import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";  
import { AppComponent } from "./app.component";  
import { HttpReqInterceptor } from "./http-req-inteceptor";

@NgModule({  
  declarations: [AppComponent],  
  imports: [BrowserModule, HttpClientModule],  
  providers: [  
    { provide: HTTP_INTERCEPTORS, useClass: HttpReqInterceptor, multi: true }  
  ],  
  bootstrap: [AppComponent]  
})  
export class AppModule {}

In the code above, we created the HttpReqInterceptor class that extends the HttpInterceptor interface.

To implement the interface, we implement the intercept method which returns the observable returned by next.handle .

Then we can use it by adding the following:

{ provide: HTTP_INTERCEPTORS, useClass: HttpReqInterceptor, multi: true }

to the providers array in AppModule .

Interceptor Order

If we have interceptors A, B, and C provided in that order, then if we make an HTTP request, A runs, then B, then C.

When our app receives a response, it’ll run C first, then B, then A.

intercept and handle return HttpEvent<any> instead of HttpResponse<any> .

This is because interceptors examine and modify the response from next.handle .

Immutability

HttpRequest and HttpResponse instance properties are readonly , which makes them immutable.

This is good because requests may be retried several times. We don’t want the retry request to be modified before it’s retried.

Therefore, if we want to change the request, we have to clone it and then return next.handle with the cloned request passed in as follows:

http-req-inteceptor.ts :

import { Injectable } from "@angular/core";  
import {  
  HttpEvent,  
  HttpInterceptor,  
  HttpHandler,  
  HttpRequest  
} from "@angular/common/http";import { Observable } from "rxjs";

@Injectable()  
export class HttpReqInterceptor implements HttpInterceptor {  
  intercept(  
    req: HttpRequest<any>,  
    next: HttpHandler  
  ): Observable<HttpEvent<any>> {  
    const secureReq = req.clone({  
      url: req.url.replace("http://", "https://")  
    });  
    return next.handle(secureReq);  
  }  
}

In the code above, we modified all request URLs that started with http to start with https .

Modifying the Request Body

We can modify the request body as follows before sending it to the server:

http-req-interceptor.ts :

import { Injectable } from "@angular/core";  
import {  
  HttpEvent,  
  HttpInterceptor,  
  HttpHandler,  
  HttpRequest  
} from "@angular/common/http";import { Observable } from "rxjs";

@Injectable()  
export class HttpReqInterceptor implements HttpInterceptor {  
  intercept(  
    req: HttpRequest<any>,  
    next: HttpHandler  
  ): Observable<HttpEvent<any>> {  
    const body = req.body;  
    const newBody = { ...body, title: body.name.trim() };  
    const newReq = req.clone({ body: newBody });  
    return next.handle(newReq);  
  }  
}

In the code above, we copied the request body with:

const body = req.body;  
const newBody = { ...body, title: body.name.trim() };

Then we set the body of the request to the newBody by writing:

const newReq = req.clone({ body: newBody });

In the end, we returned the request observable.

We set the body to an empty object undefined or null to clear the request body in the example above.

Conclusion

We can make PUT and DELETE requests by calling the put and delete methods.

put takes the URL as the first argument, the request body as the 2nd argument, and the request options object as the last argument.

delete takes the URL as the first argument, and the request options object as the last argument.

To transform requests before sending it, we can create and user HTTP interceptors.

They can be chained and called in the same order they’re provided for making requests, and the reverse order when receiving responses.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *