Cómo diagnosticar errores CORS en Angular con responseType

diagnostico-cors-fetch-angular

responseType en HttpResponse: diagnóstico programático de CORS y Fetch API en Angular

Tiempo estimado de lectura: 3 min

  • Diagnóstico preciso: responseType expone la clasificación de Fetch (basic, cors, opaque, error, opaqueredirect) para convertir status: 0 en información accionable.
  • Observabilidad: Usar interceptores para registrar fetchType permite distinguir fallos de red, bloqueos CORS y respuestas opacas.
  • Estrategia de reintentos: No aplicar reintentos genéricos; combinar responseType con límites y circuit breakers.
  • Compatibilidad: Habilitar Fetch con provideHttpClient(withFetch()) para acceder a esta propiedad; XHR no la expone.

Introducción

responseType en HttpResponse es la nueva propiedad que Angular expone en HttpResponse y HttpErrorResponse para reflejar el tipo de respuesta de la Fetch API (‘basic’, ‘cors’, ‘opaque’, ‘error’, ‘opaqueredirect’). En las primeras líneas: esto permite diagnosticar programáticamente fallos de red y bloqueos de CORS sin depender de DevTools ni de mensajes genéricos con status: 0.

Resumen rápido (lectores con prisa)

Qué es: una propiedad en HttpResponse/HttpErrorResponse que refleja Response.type de la Fetch API.

Cuándo usarlo: cuando uses Fetch como motor en Angular (provideHttpClient(withFetch())).

Por qué importa: convierte status: 0 en señales accionables (p. ej. distinguir ‘opaque’ de ‘error’).

Cómo funciona: el navegador categoriza la respuesta (basic/cors/opaque/error/opaqueredirect) y Angular la expone en HttpResponse/HttpErrorResponse.

responseType en HttpResponse: qué es y por qué importa

La propiedad es la representación de Response.type de la Fetch API (documentada en MDN). Angular la hace accesible cuando el HttpClient usa Fetch como motor (activar con provideHttpClient(withFetch())). Si tu app sigue con XHR, no tendrás esta clasificación semántica porque XHR no expone esos metadatos.

No confundas esto con la opción de petición responseType que define ‘json’|’blob’|’text’, ni con HttpEventType. Aquí hablamos de cómo el navegador trató la respuesta desde la perspectiva de seguridad/origen.

Fuentes:

Valores y significado práctico

basic

‘basic’ — Same-origin. No hay CORS. Acceso completo a cabeceras y cuerpo.

cors

‘cors’ — Cross-origin aprobado; el servidor ha respondido con las cabeceras CORS correctas.

opaque

‘opaque’ — Petición cross-origin en modo no-cors: el navegador ejecuta la petición pero oculta cuerpo y cabeceras (respuesta inaccesible).

error

‘error’ — Falla de red total: DNS, conexión rechazada o bloqueo de CORS severo que impidió la entrega.

opaqueredirect

‘opaqueredirect’ — Redirección cross-origin en modo manual.

Interpretar correctamente evita reintentos inútiles y mejora observabilidad: un ‘opaque’ no se arregla reintentando; es probable que la petición haya sido enviada en modo incorrecto o que falten cabeceras CORS.

Implementación práctica: interceptor de diagnóstico

Un interceptor global es el lugar natural para enriquecer logs y tomar decisiones automáticas:

import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { catchError, throwError } from 'rxjs';

export const corsDiagnosticInterceptor: HttpInterceptorFn = (req, next) => {
  return next(req).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status === 0) {
        // En versiones antiguas puede requerirse "as any" si no está tipado aún
        const fetchType = (error as any).responseType as string | undefined;

        if (fetchType === 'opaque' || fetchType === 'error') {
          // Log estructurado para observabilidad
          const payload = {
            tag: 'network:cors',
            fetchType,
            url: req.url,
            method: req.method,
            timestamp: new Date().toISOString()
          };
          // Ej: enviar a Sentry/Datadog/YourLogger
          console.error('[Network/CORS]', payload);
        }
      }
      return throwError(() => error);
    })
  );
};

Detalles prácticos: añade contexto (userAgent, entorno, versiones) y evita logs verbosos en clientes con alto tráfico. Etiqueta adecuadamente para filtrar incidentes de red en tu SIEM.

Decisiones automáticas y recomendaciones

Cómo actuar según responseType:

  • ‘error’ + status 0: marcar como fallo de infraestructura; no reintentar automáticamente; alertar al equipo infra.
  • ‘opaque’: auditar la configuración de la petición (¿se envía mode: ‘no-cors’ accidentalmente?), revisar proxies y CDN que puedan transformar la petición.
  • ‘cors’ con payload inválido: tratar como error de backend normal y aplicar reintentos controlados si procede.
  • ‘basic’: investigar conectividad local u origen compartido.

Evita políticas de reintento genérico: una estrategia inteligente combina responseType con límites de reintentos y circuit breakers.

Requisitos, tipado y compatibilidad

  • Habilita Fetch: provideHttpClient(withFetch()). (Ver: Angular HttpClient)
  • Tipado: en versiones intermedias de Angular puede ser necesario castear (error as any). Revisa las notas de versión si la propiedad aún no aparece en .d.ts.
  • Testing: en E2E/Browsers reales verifica valores de Response.type. En unit tests, simula HttpErrorResponse con responseType para validar rutas de logging.

Observabilidad y tiempo de resolución

La granularidad que aporta responseType reduce el time-to-detect y time-to-resolve. En entornos donde integras APIs de terceros, proxies corporativos o autenticación centralizada (OAuth), distinguir entre ‘opaque’ y ‘error’ te ahorra reproducir errores en local y te deja respuestas accionables en dashboards.

Conclusión

responseType en HttpResponse no es solo un campo más; es una palanca para convertir errores opacos en señales operativas. Si manejas integraciones cross-origin en producción, habilitar Fetch y aprovechar esta propiedad en interceptores y pipelines de observabilidad es una mejora tangible en resiliencia y diagnóstico.

FAQ

¿Qué es exactamente responseType en HttpResponse?

Es la representación de Response.type de la Fetch API expuesta por Angular en HttpResponse y HttpErrorResponse cuando HttpClient usa Fetch como motor.

¿Necesito cambiar a Fetch para verlo?

Sí. Habilita Fetch con provideHttpClient(withFetch()). Si tu app sigue con XHR, esa clasificación no estará disponible.

¿Cómo distingue ‘opaque’ de ‘error’?

‘opaque’ indica una petición cross-origin en modo no-cors con cuerpo y cabeceras ocultas; ‘error’ indica una falla de red total (DNS, conexión rechazada o bloqueo severo de CORS).

¿Debo reintentar cuando veo status 0?

No automáticamente. Usa responseType para decidir: por ejemplo, no reintentar en ‘error’ y auditar la configuración en ‘opaque’.

¿Dónde conviene registrar fetchType?

En un interceptor global, con logs estructurados que incluyan contexto (userAgent, entorno, versiones) y etiquetas para filtrar en tu SIEM.

¿Cómo pruebo esto en tests?

En E2E y navegadores reales verifica Response.type. En unit tests simula HttpErrorResponse con responseType para validar rutas de logging y comportamiento del interceptor.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *