记一次请求接口出现400响应码的诡异错误实录

前言

最近业务碰到了一个诡异的400接口请求异常,部门用户通过浏览器访问会出现400响应码错误,部分用户又能正常访问。该接口用postman请求访问,都能正常返回数据。后端写客户端请求该接口,也都能返回正常的数据。本文就来记录一下这次问题

整体简化版请求链路

如图

问题排查过程

因为不管是用postman或者是后端自己写客户端请求,都能返回正常的数据。就说明我们请求的参数是没啥问题,问题可能是出现在请求头上,我们就觉得是不是nginx做了啥限制,于是 官网溜一圈,发现如图的参数

它的中文大意是通常客户端请求缓存的大小1K就够了,但是如果请求包含长cookie或者wap客户端,1k这个值可能就不大够,因此我们适当把该大小调高验证,发现没效果。于是我们把目光转向,client_header_buffer_size下方的large_client_header_buffers

该参数的大体作用:设置用于读取大型客户端请求标头的缓冲区的最大数量和大小。请求行如果超过一个缓冲区的大小,就会向客户端返回414(请求URI太大)错误。请求头字段也不能超过一个缓冲区的大小,否则会向客户端返回400(错误请求)错误。缓冲区仅按需分配。默认情况下,缓冲区大小等于8K字节。如果在请求处理结束后,连接转换为保持活动状态,则释放这些缓冲区。

看到这里我们似乎看到曙光,因此我们果断把该参数加上,并调高相应的配置值,本以为可以高枕无忧,结果配上去,那偌大的400错误,感觉就是在嘲讽我们的天真。

思路似乎断了,就问了一下chatGPT,看它有没有什么想法,可能是我提示不够精确,在它一本正经的胡说八道后,我放弃继续追问。于是还是走回传统的提问方式,去搜索引擎排查一番,然后查到这篇文章 www.likecs.com/ask-3802541...

这篇文章告诉我们当我们做了刚才配置后,还会出现400,此时跟我们的nginx大概没啥关系了,应该是跟后端有关系,他建议是如果是springboot项目,通过在项目中适当调高如下的值

yaml 复制代码
server:
  max-http-header-size:

于是我们死马当活马医,神奇的事发生了,没有再出现400的情况

问题原因梳理

出现请求400的原因,确实是请求头过大的原因,但为什么通过postman或者后端请求就不会有问题,而通过浏览器访问就会有问题,原因就是我们在处理跨域的时候,请求头加了一堆乱七八糟的东西,比如

xml 复制代码
        add_header 'Access-Control-Allow-Headers' 'x-app-id,x-tenant-id,x-user-id,Authorization,Accept,Origin,Keep-Alive,User-Agent,access-control-allow-origin,If-Modified-Since,Cache-Control,Content-Type,Range,systemId,Cookie。。。';

其次为什么会出现部分用户访问出现400,部分用户又不会,就是因为我们请求时,请求头会携带用户jwt token,该token的payload存放一堆跟用户相关的东西,比如权限id列表啥的,这样就导致有些用户的token的长度是比较大

总结

此次400响应码错误的问题,除了技术层面上,还有一些是规范上的,比如请求头加了了一堆无用的参数,其次为了方便,在token上搞了一堆业务数据,有些bug真的是无意识产生的,轻描淡写的一篇文章,可知道当时排查了2,3天,希望这篇文章能给其他小伙伴带来一些帮助或者排查思路吧

附录

nginx-ingress配置header头缓冲大小

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |-
      underscores_in_headers on;
      large_client_header_buffers 4 1M;
      client_header_buffer_size 16K;
相关推荐
Ruci ALYS26 分钟前
SpringBoot Maven快速上手
spring boot·后端·maven
rADu REME1 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
你好潘先生1 小时前
Next.js + Spring Boot 实现 AI 多模型并行对话系统(架构设计与关键实现)
spring boot·向量检索·next.js·pgvector·ai对话·多模型对比·sse流式输出
苍煜1 小时前
SpringBoot单体应用到分布式下的数据库锁、事务、Redis事务、分布式锁、分布式事务协调
数据库·spring boot·分布式
Dylan的码园1 小时前
springBoot与Web后端基础
前端·spring boot·后端
skiy2 小时前
SpringBoot项目中读取resource目录下的文件(六种方法)
spring boot·python·pycharm
salipopl2 小时前
Spring Boot 整合 Druid 并开启监控
java·spring boot·后端
geNE GENT2 小时前
Spring Boot 实战篇(四):实现用户登录与注册功能
java·spring boot·后端
HackTorjan12 小时前
深度神经网络的反向传播与梯度优化原理
人工智能·spring boot·神经网络·机器学习·dnn
直奔標竿21 小时前
Java开发者AI转型第二十五课!Spring AI 个人知识库实战(四)——RAG来源追溯落地,拒绝AI幻觉
java·开发语言·人工智能·spring boot·后端·spring