Ever had your app ask for something from the server, and it's met with a big, "nope" in the form of an error? Frustrating, right?
I found myself in this very situation while working on the development of the frontend in Angular and came across HTTP error 400. In the realm of HTTP/1.1 standards, this error, known as the "Bad Request" response, surfaces when the server is unable or unwilling to process a request due to malformed client input, invalid parameters, or other issues.
The legacy code was only handling the response; since this request did not return a response, the request failed. So, what would be the best way to handle this? Angular interceptors!
Angular interceptors are more than just handling errors. They can also be used to inject authorization tokens in HTTP requests. This gave me the idea to write my first blog on Hashnode. So here I am, with a quick guide to Angular interceptors.
Introduction
Interceptors in Angular are services that can be used to intercept HTTP requests and responses. They provide a way to modify or handle requests and responses globally before they reach the server or the application.
Create an Interceptor:
// Import necessary modules and classes
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
// Decorate the class as an injectable service
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
// Implement the intercept method required by the HttpInterceptor interface
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Hardcoded authentication token for demonstration purposes
const authToken = 'your-auth-token';
// Clone the original request and add the authorization header
const authReq = req.clone({
setHeaders: {
Authorization: `Bearer ${authToken}`
}
});
// Pass the cloned request to the next handler in the chain
return next.handle(authReq).pipe(
// Map the response to itself (optional step)
map((response) => response),
// Catch and handle any errors
catchError(this.handleError)
);
}
// Optional: Define a private method to handle errors
private handleError = (error) => {
// Implement error handling logic here
console.error('Error:', error);
// Optionally, throw the error again or handle it gracefully
throw error;
}
}
Explanation:
AuthInterceptor
is a class that implements theHttpInterceptor
interface. This interface allows you to intercept and transform HTTP requests or responses.The
intercept
method is the core of the interceptor. It takes the originalHttpRequest
and aHttpHandler
. TheHttpHandler
is responsible for passing the request along the chain of interceptors and ultimately to the server.In this interceptor, a token (
authToken
) is hardcoded for demonstration purposes. In a real-world scenario, you would retrieve the token dynamically, perhaps from a service or another source.The
req.clone()
method is used to create a new request based on the original request (req
). This new request includes an additional header (Authorization
) with the token.The cloned request (
authReq
) is then passed to the next handler in the chain usingreturn next.handle(authReq);
. Thepipe
operator allows you to chain RxJS operators. In this case,map
is used to map the response to itself (which is optional in this context).catchError
is used to catch and handle any errors that might occur during the request.The interceptor includes an optional private method (
handleError
) to handle errors. This method is called within thecatchError
operator.
Register the Interceptor
// app.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';
@NgModule({
declarations: [/* your components */],
imports: [HttpClientModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
],
bootstrap: [/* your root component */]
})
export class AppModule { }
Explanation:
In your
app.module.ts
file, you import the necessary modules and theAuthInterceptor
class.The
HTTP_INTERCEPTORS
token is used to provide a list of interceptors. In this case, you provide theAuthInterceptor
using theuseClass
property.The
multi: true
option indicates that you're providing multiple interceptors.
In conclusion, Angular interceptors serve as essential tools in optimizing your application's interaction with the server. As you navigate your Angular projects, consider interceptors as reliable companions, adept at simplifying common challenges.