记一次请求头header丢失问题排查实录

前言

前端小王需要调用兄弟部门老张的后端接口,老张提供的接口,需要token鉴权才能调用成功。当小王按约定携带token调用老张的接口时,起先因为跨域问题,导致前端小王没法成功请求老张的接口。于是小王就跟老张说,能不能他那边配置下允许跨域。但小王是一个很有原则的人,他说这个接口是要给N个部门调用的,不可能给这些调用部门都配置允许跨域,不然口子一旦开了,后面就没完没了,他让小王自己想办法解决跨域。后面小王就把事情向上反馈,小王的领导就跟小王说,我们自己搭个反向代理,通过反向代理解决跨域问题。本文的素材就是来源于此次搭建反向代理后,发生的故事

故事延续

因为前端本来就是基于nginx进行代理,因此小王就直接把老张的接口地址,配置在nginx上。配好后小王就找老张再一次联调,这次跨域的问题是解决了,但是接口返回"系统出现异常,请联系管理员",小王就问让老张排查一下是啥情况,老张看了日志说,是token空了,就问小王是不是token没传,小王信誓旦旦说传了,并把传token的截图丢给老张。

到这事情就很诡异了,小王明明按老张的接口要求,传了token,但为啥老张没接收到token,后边小王就说老张的接口有bug,老张的第一反应是,不可能,这个接口已经提供给好几个系统使用了,他们都没问题。小王就说他们使用没问题,不能代表你接口就是没bug,我这边都按你要求的格式传了,你却没收到,那肯定是你那边问题了。

因为小王和老张都觉得自己请求或者调用没问题,就找了在公司很有威望的程序员老黄来评判,老黄毕竟没参与过小王或者老张的业务项目,他就没从业务入口,而是从端到端的请求入手,他先分析一下请求链路,其次看了一下请求参数,其中token的header参数的key,引起了他注意。这个token的header参数key,为auth_token,于是他就让小王在nginx 的http或者server块配置如下参数

javascript 复制代码
underscores_in_headers on

然后再试下。这次接口很丝滑的通了,小王和老子对老黄的敬仰之情又多了一分

复盘

1、为什么加了underscores_in_headers on,接口就好使了?

我们直接贴官网的说明 他的中文大意是当客户端请求头的字段中带有下划线,nginx默认会将该字段标识为无效字段 既然是无效了,当然token就空了。详细可以看官方链接 nginx.org/en/docs/htt...

其实还有另外一种解法就是大家约定好,不要用下划线,比如将auth_token,改为auth-token.。不过如果涉及到多方系统已经使用了下划线的情况,此时要推进改动,可能就要涉及很多沟通成本了

总结

本文虽然说是讲请求头header丢失的问题,但更多是复现一个开发联调时候的场景,很多时候我们都会觉得我们开发出来的东西没问题,会带有一种迷之自信,其次我文章故意将"系统出现异常,请联系管理员"这个返回值抛出来,这个返回值如果面向对象是业务方,大体是问题不大,但如果是面向群体是开发,无形中就增加沟通成本。很多时候我们大部分的联调时间,其实是耗费在沟通上。

最后补充一下附录跨域和允许下划线访问的内容就当做一个彩蛋,本文的真实场景,其实是通过nginx-ingress来做7层转发

附录

yaml 复制代码
 kubectl.kubernetes.io/last-applied-configuration: |-
      if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Max-Age' 1728008;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,PATCH,OPTIONS';
        return 200;
       }
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/cors-allow-credentials: 'true'
    nginx.ingress.kubernetes.io/cors-allow-headers: >-
      DNT,x-app-id,x-tenant-id,x-user-id,Authorization,Accept,Origin,Keep-Alive,User-Agent,access-control-allow-origin,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,systemId,Cookie,x-agent-type,x-noauth,isrefreshtoken,auth_token
    nginx.ingress.kubernetes.io/cors-allow-methods: PUT, GET, POST, OPTIONS
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: 'true'
    nginx.ingress.kubernetes.io/proxy-body-size: 300m
    nginx.ingress.kubernetes.io/server-snippet: |
      underscores_in_headers on;
    nginx.ingress.kubernetes.io/ssl-redirect: 'false'

其中

yaml 复制代码
   kubectl.kubernetes.io/last-applied-configuration: |-
      if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Max-Age' 1728008;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Headers' '*';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,PATCH,OPTIONS';
        return 200;
       }
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/cors-allow-credentials: 'true'
    nginx.ingress.kubernetes.io/cors-allow-headers: >-
      DNT,x-app-id,x-tenant-id,x-user-id,Authorization,Accept,Origin,Keep-Alive,User-Agent,access-control-allow-origin,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,systemId,Cookie,x-agent-type,x-noauth,isrefreshtoken,auth_token
    nginx.ingress.kubernetes.io/cors-allow-methods: PUT, GET, POST, OPTIONS
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: 'true'

是允许跨域请求的部分

其中

yaml 复制代码
 nginx.ingress.kubernetes.io/server-snippet: |
      underscores_in_headers on;

是允许请求头包含下划线的部分

当然还可以通过在ingress-nginx-controller的configmap里添加

yaml 复制代码
enable-underscores-in-headers: "true" 

开启全局配置允许请求头包含下划线

示例配置

yaml 复制代码
apiVersion: v1
data:
  allow-snippet-annotations: "true"
  enable-underscores-in-headers: "true"
  use-forwarded-headers: "true"
kind: ConfigMap
....省略其他
相关推荐
阿标在干嘛20 小时前
Nginx一个配置错误,流量损失30%!这是我们的完整排查记录
运维·nginx
IT菜鸟程2 天前
Ubuntu 下 apt 版 Nginx 升级为源码编译版本完整操作指南(1.24.0 → 1.30.4 实战)
linux·nginx·ubuntu
sbjdhjd2 天前
从 7 字符文件名拼接到二维数组取值:PHP 无参函数限制下的受控靶场复盘 | (7字符绕过)
网络·nginx·安全·网络安全·云计算·php·apache
NGINX开源社区2 天前
NGINX Gateway Fabric 2.6:F5 WAF for NGINX 集成 Gateway API
nginx·gateway·fabric
小白羊丨2 天前
HTTP/2 如何缓解 HTTP/1.1 阻塞;长连接对 Nginx 有什么影响?
网络协议·nginx·http
xixiaoyunya3 天前
Docker 容器化部署实战:从零搭建一套完整的 Nginx + Node.js + MySQL + Redis 项目环境
nginx·docker·node.js
SendTomo3 天前
【技术交流】从0到1构建一个汉字学习平台:汉字吧(hanzi8.com)的技术架构猜想
redis·mysql·nginx·php·个人开发
滨哥GPT4 天前
Codex新增文件上传后为什么小文件正常,大文件总失败?Multipart、Body Limit与Nginx限制排查
nginx·ai编程·文件上传·codex·multipart
come112344 天前
Nginx `location` 配置说明(后端开发版)
运维·nginx
PHP实战开发录5 天前
PHP文件上传成功为什么页面却找不到
开发语言·nginx·php·开发