HTTP Interceptors funcionales

Intermedio
Angular
Angular
Actualizado: 24/09/2025

Interceptores funcionales vs class-based

Los interceptores HTTP son una característica fundamental de Angular que permite interceptar y modificar las peticiones HTTP antes de enviarlas al servidor, así como las respuestas antes de que lleguen a los componentes. Tradicionalmente, Angular utilizaba interceptores basados en clases, pero desde Angular 15 se introdujeron los interceptores funcionales como una alternativa más moderna y simple.

Interceptores class-based: el enfoque tradicional

Los interceptores basados en clases utilizan la interfaz HttpInterceptor y requieren implementar el método intercept(). Este enfoque ha sido el estándar desde las primeras versiones de Angular:

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('Request URL:', req.url);
    
    return next.handle(req).pipe(
      tap(event => {
        if (event.type === HttpEventType.Response) {
          console.log('Response received:', event.status);
        }
      })
    );
  }
}

Para registrar este interceptor, era necesario configurarlo en los providers usando un token específico:

// Configuración tradicional
providers: [
  {
    provide: HTTP_INTERCEPTORS,
    useClass: LoggingInterceptor,
    multi: true
  }
]

Interceptores funcionales: la evolución moderna

Los interceptores funcionales simplifican significativamente la implementación. En lugar de clases, utilizamos funciones simples que reciben HttpRequest y HttpHandlerFn:

export const loggingInterceptor: HttpInterceptorFn = (req, next) => {
  console.log('Request URL:', req.url);
  
  return next(req).pipe(
    tap(event => {
      if (event.type === HttpEventType.Response) {
        console.log('Response received:', event.status);
      }
    })
  );
};

La firma de la función es mucho más directa:

  • req: el objeto HttpRequest que contiene todos los datos de la petición
  • next: la función HttpHandlerFn que pasa la petición al siguiente interceptor o al backend

Principales diferencias entre ambos enfoques

Simplicidad de implementación: Los interceptores funcionales eliminan la necesidad de crear clases e implementar interfaces. Una simple función es suficiente para crear un interceptor completamente funcional.

Menos boilerplate: No hay que declarar @Injectable(), implementar HttpInterceptor, ni manejar la inyección de dependencias de forma compleja. El código se reduce considerablemente.

Mejor composabilidad: Las funciones son más fáciles de componer y reutilizar. Puedes crear interceptores más granulares y combinarlos según las necesidades específicas de cada parte de tu aplicación.

Type safety mejorado: Los interceptores funcionales ofrecen mejor inferencia de tipos de TypeScript, reduciendo errores en tiempo de compilación y mejorando la experiencia de desarrollo.

Compatibilidad con inject(): Los interceptores funcionales pueden utilizar la función inject() para obtener dependencias, lo que los hace compatibles con el sistema moderno de inyección de dependencias de Angular:

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const authService = inject(AuthService);
  const token = authService.getToken();
  
  if (token) {
    req = req.clone({
      setHeaders: { Authorization: `Bearer ${token}` }
    });
  }
  
  return next(req);
};

Ventajas del enfoque funcional

La migración hacia interceptores funcionales aporta beneficios tangibles al desarrollo:

Predictibilidad: Las funciones son más predecibles que las clases, facilitando el testing y el debugging de los interceptores.

Reutilización: Los interceptores funcionales se pueden importar y exportar como cualquier función, facilitando su reutilización entre diferentes módulos o aplicaciones.

Menor complejidad: La ausencia de clases y decoradores reduce la complejidad cognitiva, especialmente para desarrolladores nuevos en Angular.

Mejor rendimiento: Los interceptores funcionales tienen una sobrecarga menor en tiempo de ejecución, ya que no requieren instanciación de clases.

Alineación con la filosofía moderna de Angular: Siguen la tendencia hacia un enfoque más funcional que vemos en signals, standalone components y otras características modernas del framework.

Los interceptores funcionales representan la evolución natural del sistema de interceptores de Angular, manteniendo toda la funcionalidad del enfoque anterior mientras simplifican significativamente su implementación y uso.

Configuración con provideHttpClient y withInterceptors

La configuración de interceptores funcionales en Angular moderno se realiza a través de provideHttpClient() y withInterceptors(), introducidos en Angular 15 y estabilizados en versiones posteriores. Este nuevo sistema de configuración elimina la complejidad de la configuración tradicional y proporciona una API más declarativa y type-safe.

Configuración básica con provideHttpClient

En aplicaciones standalone de Angular 20, la configuración se realiza en el archivo main.ts o en la configuración de la aplicación:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    provideHttpClient(
      withInterceptors([
        loggingInterceptor,
        authInterceptor,
        errorHandlerInterceptor
      ])
    )
  ]
});

La función provideHttpClient() reemplaza completamente la configuración tradicional de HttpClientModule. Ya no es necesario importar módulos ni configurar providers manualmente.

Registro de múltiples interceptores

Los interceptores se registran como un array de funciones en withInterceptors(). El orden en el array determina el orden de ejecución:

// Los interceptores se ejecutan en el orden especificado
provideHttpClient(
  withInterceptors([
    loggingInterceptor,    // Se ejecuta primero
    authInterceptor,       // Se ejecuta segundo  
    retryInterceptor       // Se ejecuta tercero
  ])
)

Para las respuestas, el orden se invierte automáticamente, siguiendo el patrón de stack (LIFO - Last In, First Out). Esto asegura que cada interceptor pueda procesar tanto la request como la response de forma coherente.

Configuración avanzada con múltiples features

provideHttpClient() acepta múltiples features que se pueden combinar según las necesidades de la aplicación:

import { 
  provideHttpClient, 
  withInterceptors, 
  withFetch, 
  withXsrfConfiguration 
} from '@angular/common/http';

bootstrapApplication(AppComponent, {
  providers: [
    provideHttpClient(
      withInterceptors([authInterceptor, loggingInterceptor]),
      withFetch(), // Usar Fetch API en lugar de XMLHttpRequest
      withXsrfConfiguration({
        cookieName: 'XSRF-TOKEN',
        headerName: 'X-XSRF-TOKEN'
      })
    )
  ]
});

Interceptores condicionales y dinámicos

Los interceptores funcionales permiten configuración condicional más elegante. Puedes crear interceptores que se activen solo bajo ciertas condiciones:

const conditionalInterceptor: HttpInterceptorFn = (req, next) => {
  const config = inject(ConfigService);
  
  if (config.isDevelopment()) {
    console.log('Development request:', req.url);
  }
  
  return next(req);
};

// Configuración con interceptor condicional
provideHttpClient(
  withInterceptors([
    conditionalInterceptor,
    authInterceptor
  ])
)

Configuración por environment

Una práctica común es configurar diferentes interceptores según el entorno de ejecución:

// interceptors.config.ts
export const getInterceptorsForEnvironment = () => {
  const baseInterceptors = [authInterceptor];
  
  if (!environment.production) {
    baseInterceptors.push(loggingInterceptor);
  }
  
  return baseInterceptors;
};

// main.ts
provideHttpClient(
  withInterceptors(getInterceptorsForEnvironment())
)

Migración desde configuración class-based

Para migrar desde interceptores basados en clases, simplemente reemplaza la configuración antigua:

// Configuración antigua (NO usar)
providers: [
  {
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true
  }
]

// Configuración nueva (Angular 20)
providers: [
  provideHttpClient(
    withInterceptors([authInterceptor])
  )
]

Interceptores específicos por servicio

Los interceptores funcionales también permiten configuración específica para ciertos servicios mediante inyección de HttpClient configurado:

@Injectable({ providedIn: 'root' })
export class ApiService {
  private httpClient = inject(HttpClient);
  
  constructor() {
    // HttpClient ya viene configurado con los interceptores globales
  }
  
  getData() {
    return this.httpClient.get('/api/data');
  }
}

Testing y configuración de interceptores

Para testing, la configuración con provideHttpClient() simplifica el setup de tests:

TestBed.configureTestingModule({
  providers: [
    provideHttpClient(
      withInterceptors([mockInterceptor])
    )
  ]
});

Esta nueva aproximación de configuración hace que los interceptores funcionales sean más mantenibles y predecibles, eliminando la complejidad asociada con la configuración tradicional de interceptores y alineándose con la filosofía moderna de Angular 20.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Angular es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Angular

Explora más contenido relacionado con Angular y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  • Comprender la diferencia entre interceptores HTTP basados en clases y funcionales en Angular.
  • Aprender a implementar interceptores funcionales con funciones simples y la función inject().
  • Configurar interceptores funcionales usando provideHttpClient y withInterceptors en Angular 20.
  • Conocer las ventajas y mejoras que aportan los interceptores funcionales respecto al enfoque tradicional.
  • Aplicar configuraciones avanzadas, condicionales y específicas por entorno o servicio con interceptores funcionales.