DEV Community

ezzabuzaid
ezzabuzaid

Posted on • Updated on

Angular Request Augmentation

One of the most important packages that come out of the box with angular is the HTTP package, although it's incredible and easy to use it still has a limitation when it comes to deal with the Interceptors.

Almost in each Angular project, I used interceptors, at least one interceptor to add Authorization header with every request.
A while back I needed to skip adding that header for a specific request, but unfortunately, there's no direct way to tell the Authorization interceptor, don't add the header to this request!
unless you added a specific header or query param to mark this request.
But this was indirect and not good in the long term, so from this point, I decided to figure out a way to make this more declarative and obvious.

I started to play with request headers, a function that will accept a plain object that will be mapped out to HTTP headers that will be removed before sending the request out of the client, but again I didn't like this approach because it doesn't look as I want.
then I had a chance to extend the HttpClient class so I can easily add what I want, I saw a lot of developer doing this approach before releasing the HttpClient to perform some logic before or after sending the request, but this just makes things worst for me.

Thus, I found a way to modify a module interface in order to add specific functionality to it, thanks to Typescript Module Augmentaion
it allows you to patch existing objects by importing and then updating them.

So the final thoughts were to extend the HttpClient, add a custom method to it to pass custom options along with the request, use DI system to provide the CustomHttpClient as HttpClient, and finally using Module augmentation to augment the HttpClient interface with the new custom method.

Let's start ^^
I'll not dig deep in explaining how you gonna do it, instead, I've combined all the work in one package and here's the source code to see how it works in details

  1. Run npm install @ezzabuzaid/ngx-request-options
  2. Define your custom options interface
interface CustomOptions {
    defaultUrl:boolean;
    defaultAuth: boolean;
}
Enter fullscreen mode Exit fullscreen mode
  1. Add RequestOptionsModule to AppModule
import { RequestOptionsModule } from  '@ezzabuzaid/ngx-request-options';

@NgModule({
    imports: [
        HttpClientModule,
        RequestOptionsModule.forRoot<CustomOptions>({
            // Default options to be applied on all requests
            defaultAuth: true;
            defaultUrl: true
        })
    ]
})


// Add those lines as they are
declare module '@angular/common/http/http' {
    // Augment HttpClient with the new `configure` method
    export  interface  HttpClient {
        /**
        * Configure request options.
        */
        configure(options: Partial<CustomOptions>): HttpClient;
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Time to use it
    • Use the new configure before the HTTP method with the options you want to use in the interceptros
@Injectable()
export class MyService {
    constructor(private http: HttpClient) { }
    getData() {
        return this.http
            .configure({ defaultUrl:  false })
            .get('endpoint');
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Inject the RequestOptions in the Interceptor
import { RequestOptions } from '@ezzabuzaid/ngx-request-options';
@Injectable()
export class UrlInterceptor implements HttpInterceptor {
    constructor(private requestOptions: RequestOptions<CustomOptions>) { }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let  url = request.url;
        if (this.requestOptions.get(request, 'defaultUrl')) {
            url = environment.endpointUrl + request.url;
        }
        return  next.handle(this.requestOptions.clone(request, { url }));
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it. with this setup, you can have the request communicate will with any interceptor
for more details please refer to the repo

Some of the use cases of interceptors maybe

  • Add default URL to the outgoing request
  • Dynamic caching for the response
  • Show progress bar while a request on the fly
  • Display a snack bar telling the state of the request
  • Append Authorization header for a request
  • Logging request metadata
  • Error handling
  • Unify Response content type
  • Auto mapping the response body and there's more,

If you have any questions or feedback please comment about them.

Happy coding!

Top comments (1)

Collapse
 
aboudzeineddin profile image
Abdurahman Zeineddin

Thank's Friend , very helpful package