Let's understand and make our API requests professional with HTTPInterceptor like a Pro
Tags: angular, typescript, frontend, tutorial
Published: 2024-01-08 13:51:11

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

```typescript
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);
  }
}
```

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:

```bash
ng generate interceptor interceptors/set-domain
```

#### ➾ Importing the HTTPInterceptor file:

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

```typescript
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 { }
```

#### ➾ 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:

```typescript
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);
  }
}

```
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:

```typescript
...

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);
  }
}
```

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 😁😁🤘🤘🤘