Cómo agregar headers HTTP a peticiones con interceptores funcionales en Angular

Cuando trabajamos con peticiones a una API externa en Angular, a veces necesitamos agregar o enviar headers. La idea de repetir el mismo código en cada petición no es algo de lo que debamos sentirnos orgullosos.
Por ejemplo, al trabajar con la ball don't lie API, es necesario enviar el header Authorization con la API key. Una solución rápida es crear un objeto con mis headers:
private _ballDontLieAuthHeader = {
Authorization: `MY_AMAZING_TOKEN`,
}Luego, agregamos el header _ballDontLieAuthHeader a cada petición. El código se ve así:
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { delay, map } from 'rxjs';
import { Player } from '../entities/player';
@Injectable({ providedIn: 'root' })
export class PlayersService {
private _http = inject(HttpClient);
private _ballDontLieAuthHeader = {
Authorization: `MY_AMAZING_TOKEN`,
}
public getPlayers() {
return this._http
.get<{ data: Array<Player> }>(`/players`, {
headers: this._ballDontLieAuthHeader,
})
.pipe(
map((response) => response.data),
delay(5000),
);
}
public getPlayerById(id: string) {
....
}
public deletePlayer(id: string) {
...
}
}Puede que funcione, pero ¿qué pasa si necesitamos esos headers en otros servicios? Tendría que importar _ballDontLieAuthHeader en todas partes, y cada método de petición tendría que agregarlos 😿.
Una mejor alternativa es usar interceptores para esto. Veamos cómo hacerlo.
Los interceptores
Los interceptores funcionales son funciones que se ejecutan en cada petición. Nos ayudan a agregar headers, reintentar peticiones fallidas, almacenar respuestas en caché y hacer mucho más.
Crear un interceptor es simple: es solo una función que recibe HttpRequest como parámetro y next para procesar el siguiente paso en la cadena de interceptores.
export function monitorInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> {
console.log(`🐒 hi!`);
return next(req);
}Los interceptores deben registrarse en provideHttpClient(), por ejemplo, en app.config o en bootstrapApplication.
bootstrapApplication(AppComponent, {providers: [
provideHttpClient(
withInterceptors([monitorInterceptor,myotherInterceptor]),
)
]});Ahora que sabemos lo sencillo que es crear un interceptor, vamos a actualizar nuestro código moviendo la URL de la API y la clave a un archivo de entorno. Después, crearemos y registraremos el interceptor.
Configurar los entornos
Primero, a partir de Angular 15 o 16, los archivos de entorno ya no se incluyen por defecto. Sin embargo, podemos generarlos fácilmente con el Angular CLI. Ejecuta el comando ng g environments en la terminal, lo que creará los archivos environment.ts y environment.development.ts.
ng g environments
CREATE src/environments/environment.ts (31 bytes)
CREATE src/environments/environment.development.ts (31 bytes)Abre environment.ts y agrega la URL de la API y el token:
export const environment = {
production: true,
apiUrl: 'https://api.github.com/repos',
token: 'your-api-key'
};¡El entorno está listo! Ahora vamos a crear y registrar nuestro interceptor.
Crear y registrar el interceptor
Usando el Angular CLI, creamos un interceptor ejecutando el comando ng g interceptor interceptors/authorization.
ng g interceptor interceptors/authorization
CREATE src/app/interceptors/authorization.interceptor.spec.ts (512 bytes)
CREATE src/app/interceptors/authorization.interceptor.ts (158 bytes)Abre el archivo authorization.interceptor.ts. En la función authorizationInterceptor, recibimos los parámetros req y next.
export const authorizationInterceptor: HttpInterceptorFn = (req, next) => {
return next(req);
};Clonamos la petición usando el método .clone() y definimos las propiedades a modificar en la nueva instancia dentro de HttpHeaders. Usamos req.headers.set('Authorization', ${environment.token}) para agregar el header de autorización a la petición, y usamos next para enviar el cambio en la petición.
El código final se ve así:
import { HttpInterceptorFn } from '@angular/common/http';
import {environment} from "../../environments/environment";
export const authorizationInterceptor: HttpInterceptorFn = (req, next) => {
const requestWithAuthorization = req.clone({
headers: req.headers.set('Authorization', `${environment.token}`),
});
return next(requestWithAuthorization);
};Por último, abre el archivo app.config e importa provideHttpClient. Luego, registra authorizationInterceptor usando la función withInterceptors:
import { provideHttpClient, withInterceptors } from '@angular/common/http';
export const appConfig = {
providers: [
provideHttpClient(withInterceptors([authorizationInterceptor])),
]
}¡Guarda los cambios y listo! Ahora cada petición incluye el header de autorización con el token 🎉.
Modern frontend development — Angular, React, TypeScript, accessibility, and performance.
Preguntas Frecuentes
¿Qué es un interceptor funcional en Angular y en qué se diferencia de uno basado en clases?
Un interceptor funcional en Angular es una función simple que recibe una petición HttpRequest y una función next para manejar el flujo, en lugar de una clase que implementa la interfaz HttpInterceptor. Se introdujeron como una alternativa más sencilla que encaja con el enfoque standalone y la función inject, eliminando la necesidad de crear una clase de servicio completa y registrarla en el arreglo providers.
¿Cómo agrego un header Authorization a cada petición HTTP en Angular?
La forma más limpia de agregar un header Authorization a cada petición es crear un interceptor HTTP. Dentro del interceptor, clonas la petición entrante usando request.clone y le pasas un nuevo objeto de headers con la clave Authorization y el valor de tu token. Luego llamas a next con la petición clonada para enviar la versión modificada al servidor.
¿Cómo registro un interceptor funcional en Angular?
Para registrar un interceptor funcional, pásalo en el arreglo withInterceptors dentro de la llamada provideHttpClient en la configuración de tu aplicación. Esto reemplaza el enfoque anterior basado en clases de agregar HTTP_INTERCEPTORS al arreglo providers. Puedes registrar varios interceptores en el mismo arreglo withInterceptors y se ejecutarán en orden.
¿Por qué debería usar un interceptor en lugar de agregar headers manualmente en cada método del servicio?
Agregar headers manualmente en cada método de servicio duplica código, dificulta actualizar el token en un solo lugar y aumenta el riesgo de olvidar un header en un endpoint nuevo. Un interceptor centraliza la lógica para que cada petición saliente se gestione de forma consistente sin tocar cada método individualmente.
Artículos Relacionados
Compartir este artículo
Si esta guía te resultó útil, compártela con tu equipo o con otros desarrolladores.
Software real. Lecciones reales.
Comparto las lecciones que aprendí por las malas, para que puedas evitarlas o estar preparado cuando ocurran.
Únete a 13,800+ desarrolladores y lectores.
Cero spam. Cancela tu suscripción en cualquier momento.