Let's understand and make our API requests professional with HTTPInterceptor like a Pro

Renan Ferro - Jan 8 - - Dev Community

Hey guys, how are you today?!

It's 2024, let's make this year wonderful and do a lot of some cool things!

Today I'd like to share and talk about a something interesting and it can do your application and development time better!

So let's see and learning something cool!

👾 The problem

When we have an application consuming an API we basically have this structure:

In this example we have a Github News Application consuming an API

import {environment} from "../../environments/environment";

....

export class GithubNewsService {

  constructor(
    private _httpClient: HttpClient
  ) { }

  getGithubNews(): Observable<GithubNews[]> {
    return this._httpClient
      .get<GithubNews[]>(`${environment.apiGithubNews}/getNews`);
  }

  saveNewGithubNews(news: GithubNews): Observable<GithubNews[]> {
    return this._httpClient
      .post<GithubNews>(`${environment.apiGithubNews}/saveNews`, news);
  }
}
Enter fullscreen mode Exit fullscreen mode

If you nice, we have a bit of duplication in our code. In the getGithubNews and saveNewGithubNews methods we need to pass the APIU url, which we pass using the environment.apiGithubNews.

But let's imagine this application becomes increasingly large with countless services consuming the same API url. And this way that we are using it in the future could cause us some problems, because imagine that one day it becomes necessary to change the variable that was previously apiGithubNews and now has another name, perhaps something like apiGenericNews we would need changing the name in all files generates work and we could possibly break the application, if we lave somewhere without changing!

And I can say, we can resolve this like a pro and with only a file! Let's see this!


👩‍🎨 The solution

Angular offer for us a lot of really and powerfull things, and one of these is the HTTPInterceptor.

🧩 HTTPInterceptor

In a nutshell, with Interceptors we can transform a flow of events by transforming the request before passing it on, calling next.handle() and applying the logic we want!

So, thinking about our "problem" we can put the API url of the request in our HTTPInterceptor, with this we can remove the environment.apiGithubNews from our GithubNewsService and we'll only have one place to change the environment.apiGithubNews, if this ever happens in the future this will change!

This makes our code a little cleaner and easier to apply future changes.

Now, let's work!

🧩 Structuring the Solution

Let's see and apply the structure for the solution.

➾ Generate the HTTPInterceptor file:

First, let's generate the HTTPInterceptor, with Angular CLI we just need put the generate command to generate the file, like below:

ng generate interceptor interceptors/set-domain
Enter fullscreen mode Exit fullscreen mode

➾ Importing the HTTPInterceptor file:

Let's import the our HTTPInterceptor in our app.module.ts inside the providers, so basically the structure will be:

import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { SetDomainInterceptor } from './interceptors/set-domain.interceptor';
...

@NgModule({
  ....
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: SetDomainInterceptor,
      multi: true,
    },
  ],
  ...
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

➾ Structuring the SetDomainInterceptor:

As we saw above, we need to take the request flow, apply the logic we want and return the update request with next.handle(), so basically the structure will be like below:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';

@Injectable()
export class SetDomainInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(httpRequest: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {

    const requestStructureUpdated: HttpRequest<any> = httpRequest
        .clone({
          url: `${ environment.urlApi }/${ httpRequest.url }`,
          setHeaders: {
            'Content-Type': 'application/json'
          }
        });

    return next.handle(requestStructureUpdated);
  }
}

Enter fullscreen mode Exit fullscreen mode

Basically, we take the request and create a clone of it, passing the API url with environment.apiGithubNews, after that we concatenate the rest of the request URL with ${ httpRequest.url } and we also apply the 'Content-Type': 'application /json'.

Now in our service structure, we can remove the environment.apiGithubNews and have just the API url path, so the new structure will look like this:

...

export class GithubNewsService {

  constructor(
    private _httpClient: HttpClient
  ) { }

  getGithubNews(): Observable<GithubNews[]> {
    return this._httpClient
      .get<GithubNews[]>('getNews');
  }

  saveNewGithubNews(news: GithubNews): Observable<GithubNews[]> {
    return this._httpClient
      .post<GithubNews>('saveNews', news);
  }
}
Enter fullscreen mode Exit fullscreen mode

Really cool and interesting, right?!

Now with this we can apply and passa whatever we want in all requests in our application, having only one place to do this and keeping our code easy to apply future changes.


We have many possibilities and I hope that with this new possibility you learn something and help you!

I hope you enjoyed today's article!

If know of any other way, have any comments or anything else, please leave a comment and let's talk!

See you soon 😁😁🤘🤘🤘

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .