如何通过Angular拦截器获取所有HTTP请求头
问题背景
我们需要读取、检查应用发出的所有请求头。当前项目已经使用Angular拦截器处理请求逻辑,现在需要扩展拦截器的功能,最初考虑直接读取request.header.keys()是否可以实现需求。
当前使用的拦截器代码如下:
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http"; import { Injectable } from "@angular/core"; import * as HttpStatusCode from "http-status-codes"; import { throwError } from "rxjs"; import { Observable } from "rxjs/Observable"; import { catchError, tap } from "rxjs/operators"; import { SharedService } from "src/app/core/services/shared.service"; import { LastActiveService } from 'src/app/core/services/last-active.service'; @Injectable() export class InactiveSessionInterceptor implements HttpInterceptor { constructor( private readonly shared: SharedService, private readonly lastActiveServie: LastActiveService) {} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req).pipe( tap((event) => { this.lastActiveServie.lastActive = Date.now(); console.log(event); console.log(`req.url ==> ${req.url}`); console.log('REQUEST HEADERS: ', req.headers.keys()); }), catchError(this.handleInactiveSession), ); } private readonly handleInactiveSession = (response: HttpErrorResponse): Observable<never> => { if ( response.error != undefined && response.error.Message != undefined && (response.status === HttpStatusCode.BAD_REQUEST || response.status === HttpStatusCode.UNAUTHORIZED) && response.error.Message.includes("Session") && response.error.Message.includes("Expired") ) { this.shared.logout(); } return throwError(response); }; }
实际测试时发现问题:以search接口为例,Chrome开发者工具Network面板中可以看到该请求携带了大量请求头,但上述拦截器代码打印出来的头信息只有极少部分。
代码打印的请求头效果:
Network面板中实际展示的全量请求头:
原因说明
出现这个现象不是代码写法错误,是两层机制决定的:
- Angular拦截器的执行时机早于浏览器底层请求发送逻辑:
req.headers对象仅会存储Angular应用层面(业务代码、其他拦截器)手动添加到请求上的自定义头。当Angular把请求交给浏览器的XHR/fetch接口后,浏览器会自动追加一批默认头,比如User-Agent、Host、Connection、Accept-Encoding、Sec-Fetch-*系列头、Cookie自动携带的相关头、CORS校验相关头等,这部分头的追加动作发生在Angular拦截器执行完成之后,拦截器自然拿不到。 - 浏览器安全策略限制:W3C规范明确将浏览器自动生成的这批头列为禁止前端脚本访问/篡改的头列表,哪怕请求已经发送完成,普通页面上下文的JS也没有权限读取这部分头信息,不存在特殊写法可以绕过这个限制。
可行处理方案
根据实际诉求选择对应方案即可:
- 如果需要校验的是业务侧主动添加的自定义请求头(比如自行封装的
Authorization令牌、链路追踪ID、业务标识头等),当前写的req.headers.keys()(注意是复数headers,不要误写为单数header)逻辑完全可以正常工作,这部分头本来就完整存储在Angular的HttpRequest实例中。 - 如果是调试阶段需要查看最终发出的全量请求头,直接使用Chrome DevTools的Network面板查看即可,不需要在业务代码中打印。
- 如果生产环境确实需要获取包含浏览器自动追加头的全量请求信息,普通前端页面代码无法实现,只能通过浏览器扩展的
webRequestAPI获取,该API仅对扩展程序开放权限。
内容的提问来源于stack exchange,提问作者bob.mazzo
相关产品推荐
相关产品推荐

