Nginx 通过upstream反向代理报 400 Bad Request

2023-11-19

首先看一下400错误的定义:

400 Bad Request 是一种 HTTP 错误状态码。HTTP/1.1 对 400 Bad Request的定义主要是:

  • 语义有误,当前请求无法被服务器理解
  • 请求参数有误
  • 丢包导致异常

背景一:

开发了一个springboot接口服务(版本:<version>2.0.3.RELEASE</version>),使用nginx的upstream作为反向代理,default.conf配置如下:

upstream infer_worker {
    server 10.86.72.5:8080;
    server 10.86.72.15:8080;
    keepalive 1024;
}
server {
    listen              80 default;
    server_name         localhost;
    location = /infer {
        proxy_pass          http://infer_worker;
        proxy_set_header    Connection "";
        proxy_http_version  1.1;
    }
}

部署好后开始测试,从nginx 的access日志中发现http的status返回400。印象中以前的项目都是这么配置的,为什么会出错呢?google以后发现是由于springboot升级后导致内置tomcat的升级导致的。

https://github.com/spring-projects/spring-boot/issues/13236 从这里可以看出问题的原因是带有下划线的Host的http请求,tomcat认为是有问题。那为什么之前版本的tomcat是正常的呢? 新版本的tomcat对这个头部进行了校验,旧版本没有校验。好了,到这里我们就知道了,其实对于带有下划线的Host,tomcat是遵循的RFC1-1034的规范的,所以tomcat的处理是正确的。

说明:查看springboot中tomcat的包只需要查看maven依赖即可。

解决方法

1)设置proxy_set_header HOST $host

在location块中加上proxy_set_header HOST $host。(注意不能同时加上这两个:proxy_set_header HOST $host;proxy_set_header Host $http_host;)

分析:nginx在没有配置proxy_set_header HOST $host 的时候,在转发http请求的时候会默认把upstream的名称作为Host头部的内容。如果像上面例子中那样,upstream名称后面有下划线,就会被tomcat收到,从而报错。proxy_set_header HOST $host这个配置的主要是在nginx在转发htp请求的时候会加上实际的Host请求头。如http请求是 http://abc.com/hello,那么nginx在转发http请求的时候会原封不动的把host请求头(Host:abc.com)转发给后台服务。

2)upstream后面的名称去掉下划线:

从上面的分析中可知,去掉upstream后面名称中的下划线也可以避免这个问题。

参考:https://googlevip8.com/post/47

背景二:

upstream test_interface {
    server 192.168.12.2 8080;
}

server {
    listen       12345;
    server_name  localhost;
    location / {
        proxy_pass http://test-interface;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

现象:返回的http状态吗400.查看日志没有抱错。

原因:Host 为空。

解决方法:设置host值

location / {
        proxy_pass http://test-interface;
        proxy_set_header Host $host; 
        #或者 
        proxy_set_header Host $http_host; 
        proxy_http_version 1.1;
        proxy_set_header Connection "";
}

 搜索该问题时,了解到:如果upstream转发域名时也会遇到这个问题,描述如下:

upstream test-interface {
    server abc.test.cn;
}

server {
    listen       12345;
    server_name  localhost;
    location / {
        proxy_pass http://test-interface;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

 所出现的现象就是,从 192.168.1.10 或者 192.168.1.11 请求 192.168.1.11 的 12345 端口,都会返回 400。

最初给请求头加上了 Host ,比如 proxy_set_header Host $host; 或者 proxy_set_header Host $http_host; ,但还是报错,于是只好抓包进行查看,包括经过 Nginx 12345 端口转发的请求,和直接在 Nginx 服务器上调用外网接口的请求。

在比对了之后发现,能调用成功的请求头中, Host 就是接口的域名地址,而调用失败的请求头中,该字段都是 IP 或者其他什么东西

 解决方法一:设置静态Host

upstream test-interface {
    server abc.test.cn;
}

server {
    listen       12345;
    server_name  localhost;
    location / {
        proxy_pass http://test-interface;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host abc.test.cn;
    }
}

  解决方法二:不实用upstream,直接proxy_pass 域名

server {
    listen       12345;
    server_name  localhost;
    location / {
        proxy_pass http://abc.test.cn;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

参考: 

https://priesttomb.github.io/%E6%8A%80%E6%9C%AF/2020/05/05/nginx-400-error-about-host/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nginx 通过upstream反向代理报 400 Bad Request 的相关文章

  • 如何设置 nginx 以允许在 LAN 上使用 HTTP,并在外部连接上进行重定向和授权

    我正在尝试为我在家庭服务器上运行的一些个人 Web 服务设置 Nginx 网络在服务器和互联网之间设置了路由器 该路由器运行着动态 DNS 服务 以便我可以在不在家时连接到它 我希望 Nginx 能够处理来自本地网络的连接 以便它能够通过以
  • 您是否正在尝试将目录挂载到文件上(或反之亦然)?

    我有一个带有版本的docker17 06 0 ce 当我尝试使用 docker 和命令安装 NGINX 时 docker run p 80 80 p 8080 8080 name nginx v PWD www www v PWD conf
  • 使用 Clapprjs 在网页上流式传输 .m3u8

    我使用 nginx rtmp 将 rtmp 转换为 hls 并使用 Clappr 在网页中进行流式传输 但 Clappr 采用旧的 ts 段 导致 404 错误 因为它在服务器上被删除 如何解决这个问题 抱歉 这是我第一次使用 nginx
  • nginx 服务器中不允许方法 405 错误

    我们的反应应用程序在我们的本地机器上正常工作 但我们将其延迟到更高的环境中 它不起作用 它发送405 Method not allowed error 页面正在加载 每当我们要求时submit form这个问题来了 下面是我的nginx c
  • Docker-compose Predis 不通过 PHP 连接

    我正在尝试使用 docker compose 将 PHP 与 redis 连接 docker compose yml version 2 services redis image redis 3 2 2 php image company
  • 使用 nginx 代理时在 RStudio 中运行闪亮的应用程序

    我正在尝试使用通过 nginx 代理的 RStudio 服务器来开发一个闪亮的应用程序 当我使用 RStudio 而不是服务器 来运行闪亮的应用程序时 一切正常 但是 当我通过代理 RStudio 运行时 该应用程序出现在 查看器 窗格中
  • 为从 nginx 反向代理转发的请求添加唯一 id

    我们运行 nginx 作为反向代理 将请求转发到运行 Compojure 的 Clojure 应用程序 Compojure 是一个封装 Jetty 的库 为我们的应用程序提供服务 Web 请求的能力 目前 我们捕获 nginx 和 Cloj
  • 使用 client_body_in_file_only 进行 nginx 文件上传

    晚上好 我需要将静态内容上传到 nginx 服务器 1 9 因此上传模块不适用于此版本 我读过这篇文章 Nginx 直接文件上传 无需通过后端传递 https coderwall com p swgfvw nginx direct file
  • Node + Express + Nginx 未设置 Cookie

    我有一个使用 Express 的 Node 应用程序 我尝试为我的客户端设置 cookie 它在本地环境 http 上运行良好 但是一旦我投入生产 https 我就很好地收到了cookie 我可以在响应中看到它 但它没有设置 任何想法 Ng
  • 当请求太大时,Nginx(我认为)会以错误的权限保存文件

    所以 我对托管和 Linux 等都是完全陌生的 所以如果我说错了 请原谅我 我还在学习 我正在使用 Django 创建一个小型个人网站 我想把它放到网上看看是否一切正常 我从 linode 买了一台便宜的服务器 并使用 Digital Oc
  • NGinx 域名重定向

    假设我有一个名为 xyz co 的网站 我还有其他具有相同前缀的域名 例如 xyz com xyz it xyz co it 现在 nginx 与端口 80 的 nginx conf 中的 server name xyz co 配合得很好
  • kubernetes 集群中 django 应用程序的 Nginx 配置

    我在为部署在 kubernetes 中的 django 应用程序创建 nginx 配置文件时遇到困难 Nginx 和 app 是同一集群中的两个独立容器 据我了解 容器可以通过 127 0 0 1 XX 和主机名相互通信 我为此使用 min
  • Nginx 中 uwsgi_pass 和 proxy_pass 的区别?

    我在 Nginx 后面运行 uWSGI 并一直在使用proxy pass让 Nginx 访问 uWSGI 切换到有什么好处吗uwsgi pass 如果是这样 那是什么 uwsgi pass使用一个uwsgi协议 proxy pass使用普通
  • Docker:Nginx 和 php5-fpm docker 不说话

    我想进行完全 Docker 化的 Drupal 安装 我的第一步是让容器与 Nginx 和 php5 fpm 一起运行 两者都基于 Debian 我在 CoreOS alpha 频道 使用 Digital Ocean 我的 Dockerfi
  • 如何在位置中使用 Nginx Regexp

    Web 项目将静态内容放入 some content img 文件夹中 url规则为 img some md5 但文件夹中的位置 content img 前两位数字 Example url example com img fe5afe048
  • WebSockets 监听 UNIX 域套接字?

    是否可以在 nginx 服务器后面设置一个 WebSockets 服务器来处理 UNIX 域套接字上的连接 我目前在同一台计算机上有多个 WebSocket 服务器实例 并且存在端口共享问题 所有实例都必须分配一个唯一的端口 我想避免这种情
  • 错误:从上游读取响应标头时上游过早关闭连接 [uWSGI/Django/NGINX]

    我目前在用户正在进行的查询中总是得到 502 它通常返回 872 行 在 MySQL 中运行需要 2 07 然而 它返回了大量信息 每一行包含很多东西 有任何想法吗 运行 Django tastypie Rest API Nginx 和 u
  • 如何正确链接 php-fpm 和 Nginx Docker 容器?

    我正在尝试链接 2 个单独的容器 nginx 最新 https registry hub docker com nginx php fpm https registry hub docker com php 问题是 php 脚本不起作用 也
  • nginx 匹配位置中的特定单词

    我在匹配 nginx request body 变量中的特定单词时遇到问题 如果正文请求中有特殊单词 我想代理传递 所以我的方法是这样的 location php if request body proxy pass http test p
  • 为什么 opcache 没有刷新?

    我用guzzlehttp guzzle封装在拉拉维尔 8 升级到后PHP 8 I get Symfony Component ErrorHandler Error FatalError Invalid opcode 117 2 0 in f

随机推荐

  • Matlab 超前滞后相关,自相关xcorr

    Matlab提供了计算互相关和自相关的函数xcorr函数 1 使用方法 c xcorr x y c xcorr x c xcorr x y option c xcorr x option c xcorr x y maxlag
  • linux函数库之htons(), ntohl(), ntohs(),htons() 函数

    linux疑难问题排查实战 分享了作为公司专家 在项目开发过程中内存优化 堆 栈 代码段 数据段 性能优化 死机 栈越界 堆越界 死锁等疑难问题排查的案例 使用的工具 perf asan strace memleak等 工作经验 大家可以点
  • Linux中的firewall-cmd

    2023年8月4日 周五上午 目录 打开端口 关闭端口 查看某个端口是否打开 查看当前防火墙设置 firewall cmd中的服务 在防火墙中什么是服务 为什么会有服务 打开或关闭服务 查看某个服务是否打开 firewall cmd中的 z
  • Unity MRTK使用详解(Htc vive+LeapMotion)

    MRTK Unity是一个由Microsoft驱动的开源项目 提供了多种组件和功能 用于加速Unity中的跨平台MR应用程序开发 以下是其一些功能 提供跨平台输入系统和用于空间交互和UI组件 启用快速原型通过在编辑器中的模拟 让你马上看到变
  • 在vscode内运行php代码文件

    一 下载php 下载php链接 下载后解压缩文件 我新建了一个php文件夹在解压缩到这里 二 下载Xdebug 下载Xdebug链接 下载后复制粘贴到php文件夹下的ext文件夹 三 修改 在php文件夹下找到这两个文件夹 复制第一个文件夹
  • Hudi原理

    1 摘要 Apache Hudi提供了不同的表类型供根据不同的需求进行选择 提供了两种类型的表 Copy On Write COW Merge On Read MOR 2 术语介绍 在深入研究 COW 和 MOR 之前 让我们先了解一下 H
  • checking for module ‘sqlite3‘ package ‘sqlite3‘ not found

    checking for module sqlite3 package sqlite3 gt 某个版本号 not found 在编译安装其他源码包的时候遇到缺少sqlite3库的问题 这里字面上的意思是没有安装sqlite3 但是造成这个问
  • (python)常见面试题

    1 一行代码实现1 100之和 2 如何在一个函数内部修改全局变量 3 列出5个python标准库 os 提供了不少与操作系统相关联的函数 sys 通常用于命令行参数 re 正则匹配 math 数学运算 datetime 处理日期时间 4
  • Redis数据实战之“万金油”的String,为什么不好用了?

    Redis数据实战之 万金油 的String 为什么不好用了 引言 为什么 String 类型内存开销大 用什么数据结构可以节省内存 如何用集合类型保存单值的键值对 引言 以一个项目需要为例 需要开发一个图片存储系统 要求这个系统能快速地记
  • DNS使用TCP与UDP

    DNS同时占用UDP和TCP端口53是公认的 这种单个应用协议同时使用两种传输协议的情况在TCP IP栈也算是个另类 但很少有人知道DNS分别在什么情况下使用这两种协议 先简单介绍下TCP与UDP TCP是一种面向连接的协议 提供可靠的数据
  • tensorflow-ssd 实现纸张缺陷检测

    环境 win10 tensorflow1 10 python3 6 9 下载https github com balancap SSD Tensorflow到本地 1 解压并测试demo 打开Anaconda prompt 切换到SSD T
  • 我又把HTMLTestRunner改了一下,支持Python3,添加echarts统计饼图

    之前用Bootstrap把HTMLTestRunner改的美观了一点 同时改成了中文的报告 但那个是基于Python2的 见这篇博文 selenium之 输出报告 对HTMLTestRunner进行样式调整后的示例 这次呢 博主又给它改成了
  • mac编译安装Nginx

    一 安装wget 使用homebrew安装wget brew install wget 安装wget时报错 tar Error opening archive Failed to open Users xxx Library Caches
  • 【数据库】如何创建一个非常便宜的无服务器数据库

    云对象存储可以用作功能强大且非常便宜的数据库 您是否相信您可以使用完全托管 可大规模扩展 高度可用且价格低廉的无服务器数据库 每月只需 5 美元 您就可以存储数亿条记录并读写数十亿条记录 如果您的数据库需求可以通过非常简单的键值存储来满足
  • 近期deep learning做图像质量评价(image quality assessment)的论文4

    1 2017会议论文ICME An accurate deepconvolutional neural networks model for no reference image quality assessment 复旦大学 1 1用了部
  • Python开发环境Wing IDE如何查看调试数据

    Wing IDE具有一个十分有用的特性 就是处理复杂bug的时候可以以各种各样的方式查看调试数据值 这个功能具体是由Watch工具实现的 查看数据值 在PrintAsHTML中发生异常时 右键单击Stack Data工具中的本地数值 这将显
  • 【STM32学习笔记】(13)——外部中断详解

    EXTI 简介 EXTI External interrupt event controller 外部中断 事件控制器 管理了控制器的 20 个中断 事件线 每个输入线可以独立地配置输入类型 脉冲 或挂起 和对应的触发事件 上升沿或下降沿或
  • unity本地分数排行榜简单解决方案(Json)

    具体效果 大体方法 创建一个分数类Score和一个分数类的容器List
  • TLSv1.2抓包解密分析过程之ECDHE_RSA_WITH_AES_128_CBC_SHA256

    ECDHE RSA WITH AES 128 CBC SHA256模式下 RSA只用于身份验证 不用于加密 加密密钥是通过有限域的椭圆曲线算法交换的 需要拿到ECDH的私钥才能解密 本文的demo样本使用了特殊方法来获取这些参数 椭圆曲线加
  • Nginx 通过upstream反向代理报 400 Bad Request

    首先看一下400错误的定义 400 Bad Request 是一种 HTTP 错误状态码 HTTP 1 1 对 400 Bad Request的定义主要是 语义有误 当前请求无法被服务器理解 请求参数有误 丢包导致异常 背景一 开发了一个s