AngularJS 1.4添加自定义请求头致POST请求失败求助
背景
我是AngularJS新手,正在维护团队的老旧AngularJS 1.4项目,需要给后端请求添加三个自定义请求头(Application、Trace-Id、User-Id)用于请求追踪。
原成功请求头
Accept: application/json, text/plain, */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7 Connection: keep-alive Content-Length: 113 Content-Type: application/json;charset=UTF-8 Host: granite161bcmino-app-ctec-dev03.enwd.co.sa.charterlab.com:8281 Origin: https://11.11.11.11 Referer: https://11.11.11.11/ Sec-Ch-Ua: "Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS" Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: cross-site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
添加自定义头后的失败请求头
Accept: application/json, text/plain, */* Application: app Content-Type: application/json;charset=UTF-8 Referer: https://11.11.11.11/ Sec-Ch-Ua: "Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS" Trace-Id: stestidddddddd User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 User-Id: testuseridddd
后端信息
后端是WebLogic上的Java服务,OPTIONS预检返回200 OK,实际POST端点无需请求头。
POST端点代码
@POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Path("/xxxxx") public Response xxxxx(String jsonbody) { return something; }
OPTIONS端点代码
@OPTIONS @PermitAll @Path("/xxxxx") public Response xxxxx() { return Response .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Credentials", "true") .header("Content-Type", "application/json") .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization") .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD").build(); }
尝试过的操作与问题
- 两种方式添加自定义头:直接在
$http.post(url, data, config)中配置、通过拦截器修改配置,均成功添加自定义头,但请求失败。 - 问题现象:添加自定义头后,浏览器不再自动携带
Content-Length和Host头;手动设置这两个头时,报错:angular.js:10458 Refused to set unsafe header "Content-Length" - 项目仅两个拦截器,新增的用于加自定义头,另一个不修改请求头;POSTMAN携带Host和Content-Length请求可成功。
排查思路
修正CORS预检头配置
自定义请求头属于非简单头,OPTIONS响应的Access-Control-Allow-Headers必须包含新增的Application、Trace-Id、User-Id,否则浏览器会拦截实际请求。当前配置里缺少这些头,需要补充进去。
另外,Access-Control-Allow-Origin设为*的同时不能开启Access-Control-Allow-Credentials: true,这是浏览器的安全限制,需要将Access-Control-Allow-Origin改为请求的具体来源(比如https://11.11.11.11)。检查AngularJS头配置逻辑
确认添加自定义头的代码是否意外覆盖了默认头。比如在拦截器中,应该先初始化默认头对象再添加自定义项:// 正确的合并方式 config.headers = config.headers || {}; config.headers['Application'] = 'app'; config.headers['Trace-Id'] = 'stestidddddddd'; config.headers['User-Id'] = 'testuseridddd';避免直接赋值
config.headers = { ... }导致默认头丢失。放弃手动设置安全头
Host和Content-Length属于浏览器自动管理的不安全头,不允许手动设置,无需尝试添加。只要CORS配置正确,浏览器会自动为合法请求携带这些头。验证预检请求完整性
检查浏览器发送的OPTIONS请求是否包含Access-Control-Request-Headers字段,确认其中包含新增的三个自定义头;同时确认后端OPTIONS响应的Access-Control-Allow-Headers与之匹配。排查AngularJS 1.4版本特性
部分AngularJS 1.4版本在处理自定义头时存在合并逻辑问题,可以简化拦截器代码,仅添加自定义头,不修改其他默认配置;也可以尝试升级到AngularJS 1.4的最新小版本,修复已知的$http头处理bug。查看后端服务器日志
检查WebLogic的访问日志,确认是否收到实际的POST请求,以及请求携带的头信息。如果服务器未收到请求,说明浏览器因CORS校验失败直接拦截了请求;如果收到请求但返回错误,再排查后端服务的头校验逻辑。
内容的提问来源于stack exchange,提问作者Harry Zhang

