美文网首页
记一次请求头header丢失问题排查实录

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

作者: linyb极客之路 | 来源:发表于2023-11-13 09:39 被阅读0次

    前言

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

    故事延续

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

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

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

    underscores_in_headers on
    

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

    复盘

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

    我们直接贴官网的说明


    b69c7d85fac1cddd9f4f750f59a6a191_b54d6ef1f8a6d5c0651d1aa3076141b3.png

    他的中文大意是当客户端请求头的字段中带有下划线,nginx默认会将该字段标识为无效字段
    既然是无效了,当然token就空了。详细可以看官方链接
    http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers

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

    总结

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

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

    附录

     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'
    

    其中

       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/server-snippet: |
          underscores_in_headers on;
    

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

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

    enable-underscores-in-headers: "true" 
    

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

    示例配置

    apiVersion: v1
    data:
      allow-snippet-annotations: "true"
      enable-underscores-in-headers: "true"
      use-forwarded-headers: "true"
    kind: ConfigMap
    ....省略其他
    

    相关文章

      网友评论

          本文标题:记一次请求头header丢失问题排查实录

          本文链接:https://www.haomeiwen.com/subject/twzrwdtx.html