Originally posted on my blog
Dealing with API based token is sometimes cumbersome. Due to the fact that, on every request, we have to send a token as parameter to be able to reach out the server.
In Angular, it becomes easier with the help of HttpClient interceptors. In this tutorial, I will lead on how to set up a token once and use it on every request with interceptors.
Prerequisite
Set up a new angular app
ng new my-app
Then add a service file that will handle the logic of sending the request.
ng generate service data
After successfully generated the service add the following lines to send the request to the server.
import { Injectable } from "@angular/core";
import { HttpClient, HttpParams } from "@angular/common/http";
@Injectable({
providedIn: "root"
})
export class DataService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get("https://example.com/api/data", {
params: new HttpParams().set(
"auth-token",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
)
});
}
getUsers() {
return this.http.get("https://example.com/api/users", {
params: new HttpParams().set(
"auth-token",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
)
});
}
}
And in your app.component.ts
call the service we've created to achieve the request.
import { Component } from "@angular/core";
import { DataService } from "./data.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent {
constructor(private dataService: DataService) {}
showData() {
this.dataService.getData().subscribe(response => {
// Write your logic here to handle the data
console.log(response);
});
}
showUsers() {
this.dataService.getUsers().subscribe(response => {
// Write your logic here to handle the data
console.log(response);
});
}
}
As you can see in the data.sevice.ts
file, we use the same params
for both getData() and getUsers() methods to send the token.
Now it's time to optimize it with interceptors.
Interceptors
Http Interceptors were introduced with version 4.3 of Angular. They help a lot with handling request with the same parameters or headers.
To implement it, we need to create a new file auth.interceptor.ts
. You can name it whatever you like, but it's a convention to add .interceptor to be clear about what's inside the class file. Next, add this following code block to the file.
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent
} from "@angular/common/http";
import { Observable } from "rxjs";
export class AuthInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const cloneReq = req.clone({
params: req.params.set(
"auth-token",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
)
});
return next.handle(cloneReq);
}
}
First, we need to import HttpInterceptor
and implement it to our class to be able to access to the intercept()
method. Then, we pass two arguments req and next to that method. The first is the request of type HttpRequest
and can have any type of data, and the second next
will handle the request and let it continue its journey.
The intercept() method is of type Observable
and can receive any type of events.
The Http request is by default immutable, we can't edit it. Therefore, we need to create a copy by cloning the request with req.clone()
. Now with this method, we can configure our params directly and return the cloneReq
request and let it continue its way to the server.
Now, our interceptor will add the token as a parameter on every request before letting it reach out the server. We can even simplify our data.service.ts
file by removing everything related to params.
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
@Injectable({
providedIn: "root"
})
export class DataService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get("https://example.com/api/data");
}
getUsers() {
return this.http.get("https://example.com/api/users");
}
}
Conclusion
Http interceptors are useful on every matter. It's kind like middleware in back-end development. We can use it to modify our requests and also our responses.