You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 17拦截器出现Http failure response:0 Unknown Error求助

问题

使用Angular 17开发应用,通过HTTP拦截器从sessionStorage获取授权token并添加至请求头。功能运行正常,API响应符合预期,但浏览器控制台持续抛出错误:Error occurred in HTTP request: Http failure response for [API URL]: 0 Unknown Error。此前未添加if (typeof window !== 'undefined')判断时,曾出现“session storage not defined”错误。目前已确认token正确添加至请求头,仍不清楚该错误的产生原因。

拦截器代码

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

export const tokenInterceptor: HttpInterceptorFn = (req, next): any => {
  if (typeof window !== 'undefined') {
    const token = sessionStorage.getItem('token');

    const authReq = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });

    return next(authReq).pipe(
      catchError((error) => {
        console.error('Error occurred in HTTP request:', error);
        return throwError('An error occurred. Please try again.'); 
      })
    );
  }
  return next(req).pipe(
    catchError((error) => {
      console.error('Error occurred in HTTP request:', error);
      return throwError('An error occurred. Please try again.'); 
    })
  );
};

错误详情

Error occurred in HTTP request: HttpErrorResponse {
  headers: _HttpHeaders {
    normalizedNames: Map(0) {},
    lazyUpdate: null,
    headers: Map(0) {}
  },
  status: 0,
  statusText: 'Unknown Error',
  url: 'https://localhost:44302/api/Complaint/recentListComplaint',
  ok: false,
  name: 'HttpErrorResponse',
  message: 'Http failure response for https://localhost:44302/api/Complaint/recentListComplaint: 0 Unknown Error',
  error: ProgressEvent2 {
    type: 'error',
    target: XMLHttpRequest2 {
      onloadstart: null,
      onprogress: null,
      onabort: null,
      onerror: null,
      onload: null,
      ontimeout: null,
      onloadend: null,
      _listeners: [Object],
      onreadystatechange: null,
      _anonymous: undefined,
      readyState: 4,
      response: null,
      responseText: '',
      responseType: 'text',
      responseURL: '',
      status: 0,
      statusText: '',
      timeout: 0,
      upload: [XMLHttpRequestUpload],
      _method: 'GET',
      _url: [Url],
      _sync: false,
      _headers: [Object],
      _loweredHeaders: [Object],
      _mimeOverride: null,
      _request: null,
      _response: null,
      _responseParts: null,
      _responseHeaders: null,
      _aborting: null,
      _error: null,
      _loadedBytes: 0,
      _totalBytes: 0,
      _lengthComputable: false
    },
    currentTarget: XMLHttpRequest2 {
      onloadstart: null,
      onprogress: null,
      onabort: null,
      onerror: null,
      onload: null,
      ontimeout: null,
      onloadend: null,
      _listeners: [Object],
      onreadystatechange: null,
      _anonymous: undefined,
      readyState: 4,
      response: null,
      responseText: '',
      responseType: 'text',
      responseURL: '',
      status: 0,
      statusText: '',
      timeout: 0,
      upload: [XMLHttpRequestUpload],
      _method: 'GET',
      _url: [Url],
      _sync: false,
      _headers: [Object],
      _loweredHeaders: [Object],
      _mimeOverride: null,
      _request: null,
      _response: null,
      _responseParts: null,
      _responseHeaders: null,
      _aborting: null,
      _error: null,
      _loadedBytes: 0,
      _totalBytes: 0,
      _lengthComputable: false
    },
    lengthComputable: false,
    loaded: 0,
    total: 0
  }
}

分析与解决方案

错误原因分析

控制台抛出的status: 0错误,常见于以下场景:

  1. CORS预请求(OPTIONS)失败:浏览器会在跨域请求前发送OPTIONS预请求,检查后端是否允许跨域。如果后端未正确配置CORS,或者拒绝了带Authorization头的OPTIONS请求,就会触发此错误。此时实际业务请求(如GET/POST)可能已成功完成,导致功能正常但控制台报错。
  2. 直接依赖全局window对象:原代码中用typeof window !== 'undefined'判断,在SSR(服务端渲染)场景下仍可能存在兼容性问题,Angular官方推荐通过DOCUMENT注入来访问浏览器全局对象。
  3. 无token时仍添加Authorization头:当sessionStorage中没有token时,请求头会被设置为Authorization: Bearer null,可能触发后端的异常拦截。

具体解决步骤

1. 优化拦截器逻辑

修改拦截器,跳过OPTIONS请求、仅在token存在时添加授权头,并使用Angular规范的方式访问sessionStorage:

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

export const tokenInterceptor: HttpInterceptorFn = (req, next) => {
  // 跳过OPTIONS预请求,无需携带token
  if (req.method === 'OPTIONS') {
    return next(req).pipe(
      catchError(error => {
        console.error('OPTIONS预请求错误:', error);
        return throwError(() => new Error('跨域预请求失败,请检查后端CORS配置'));
      })
    );
  }

  // 通过DOCUMENT注入访问sessionStorage,适配SSR场景
  const document = inject(DOCUMENT);
  const token = document.defaultView?.sessionStorage.getItem('token');

  let authReq = req;
  // 仅当token存在时添加授权头
  if (token) {
    authReq = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });
  }

  return next(authReq).pipe(
    catchError(error => {
      console.error('HTTP请求错误:', error);
      return throwError(() => new Error('请求出错,请稍后重试'));
    })
  );
};

2. 检查后端CORS配置

确保后端满足以下CORS配置要求:

  • 允许前端域名发起跨域请求(Access-Control-Allow-Origin)
  • 在Access-Control-Allow-Headers中包含Authorization,允许自定义授权头
  • 响应OPTIONS请求时返回200或204状态码,无需返回业务数据

3. 排查重复/取消请求

在浏览器开发者工具的网络面板查看请求详情:

  • 确认是否存在OPTIONS请求失败,而业务请求成功的情况
  • 检查是否有重复发起的请求,或请求因组件销毁被中途取消

内容的提问来源于stack exchange,提问作者Clinton Hadrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:20:07