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错误,常见于以下场景:
- CORS预请求(OPTIONS)失败:浏览器会在跨域请求前发送OPTIONS预请求,检查后端是否允许跨域。如果后端未正确配置CORS,或者拒绝了带Authorization头的OPTIONS请求,就会触发此错误。此时实际业务请求(如GET/POST)可能已成功完成,导致功能正常但控制台报错。
- 直接依赖全局window对象:原代码中用
typeof window !== 'undefined'判断,在SSR(服务端渲染)场景下仍可能存在兼容性问题,Angular官方推荐通过DOCUMENT注入来访问浏览器全局对象。 - 无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
相关产品推荐
相关产品推荐

