对 nginx 反向代理背后的应用程序进行故障排除,因为 POST/PUT 请求回复错误 400(错误请求)
troubleshooting application behind nginx reverse proxy, as POST/PUT requests are replied with Error 400 (Bad Request)
我第一次尝试在 linux 上托管我的 Angular/ASP.net core 3.1 应用程序。
Nginx 站在端口 80 上并提供静态文件并充当 api 部分的反向代理,该部分将传递给 .NET/kestrel 服务器。
问题是我在任何包含正文的网络 API 请求上系统地收到 400 状态代码错误(错误请求),例如 POST & PUT,但是 GET 没问题。
我通过一个中间件添加了一些日志,就是为了看看能不能得到请求。基本上是这样的:
app.Use(async (context, next) => {
context.Request.EnableBuffering();
string reqBody;
using (var reader = new StreamReader(context.Request.Body))
{
reqBody = await reader.ReadToEndAsync();
context.Request.Body.Seek(0, SeekOrigin.Begin);
ms_oLogger.Debug($"Incoming request: METHOD={context.Request.Method} PATH={context.Request.Path} BODY=\"{reqBody}\"");
}
await next();
});
这只是记录 GET 请求的内容,但没有显示有问题的 PUT/POST 请求...我可以断定这只是一个 nginx 问题吗?
我还在 nginx 上为给定的“/api”位置启用了日志,但我不知道发生了什么...我怎么知道哪个层生成了 400状态码?
EDIT1:我开始了一个空白的新项目,只有一个糟糕的 Web API 项目包含一个 GET 和一个 POST 方法只是为了检查我的应用程序是否有问题,但我仍然得到问题。
所以我设置了一个新的 ubuntu 服务器(这次是 ubuntu 服务器而不是桌面版),现在它可以工作了!!!
我比较了配置等......但无法弄清楚出了什么问题!....
但我最初的问题仍然有效:如何解决问题的根源?
EDIT2:这是我的 default.conf:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location /fusion {
root /opt/fichet/WebUI/NgApp;
}
location /fusion/api {
proxy_pass http://localhost:5000/api;
error_log /var/log/nginx/fusion_error_logs.log debug;
access_log /var/log/nginx/fusion_access.log;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
好像没有开启防火墙("sudo ufw status verbose"告诉我们是"inactive")
从您的 nginx 配置中删除这些行。
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
这些 headers 用于 WebSocket 连接,不应出现在 non-websocket 请求中。我的猜测是您的上游服务器不介意 GET 请求,但出于某种原因 POST/PUT。
如果您不使用 websockets,您可以将其删除。
如果你使用的是websockets,你需要nginx根据请求是否是websockets添加或不添加这些headers。这样的事情应该有效:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /fusion/api {
proxy_pass ...
...
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
有关详细信息,请参阅 here。
我第一次尝试在 linux 上托管我的 Angular/ASP.net core 3.1 应用程序。
Nginx 站在端口 80 上并提供静态文件并充当 api 部分的反向代理,该部分将传递给 .NET/kestrel 服务器。
问题是我在任何包含正文的网络 API 请求上系统地收到 400 状态代码错误(错误请求),例如 POST & PUT,但是 GET 没问题。
我通过一个中间件添加了一些日志,就是为了看看能不能得到请求。基本上是这样的:
app.Use(async (context, next) => {
context.Request.EnableBuffering();
string reqBody;
using (var reader = new StreamReader(context.Request.Body))
{
reqBody = await reader.ReadToEndAsync();
context.Request.Body.Seek(0, SeekOrigin.Begin);
ms_oLogger.Debug($"Incoming request: METHOD={context.Request.Method} PATH={context.Request.Path} BODY=\"{reqBody}\"");
}
await next();
});
这只是记录 GET 请求的内容,但没有显示有问题的 PUT/POST 请求...我可以断定这只是一个 nginx 问题吗?
我还在 nginx 上为给定的“/api”位置启用了日志,但我不知道发生了什么...我怎么知道哪个层生成了 400状态码?
EDIT1:我开始了一个空白的新项目,只有一个糟糕的 Web API 项目包含一个 GET 和一个 POST 方法只是为了检查我的应用程序是否有问题,但我仍然得到问题。 所以我设置了一个新的 ubuntu 服务器(这次是 ubuntu 服务器而不是桌面版),现在它可以工作了!!! 我比较了配置等......但无法弄清楚出了什么问题!.... 但我最初的问题仍然有效:如何解决问题的根源?
EDIT2:这是我的 default.conf:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location /fusion {
root /opt/fichet/WebUI/NgApp;
}
location /fusion/api {
proxy_pass http://localhost:5000/api;
error_log /var/log/nginx/fusion_error_logs.log debug;
access_log /var/log/nginx/fusion_access.log;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
好像没有开启防火墙("sudo ufw status verbose"告诉我们是"inactive")
从您的 nginx 配置中删除这些行。
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
这些 headers 用于 WebSocket 连接,不应出现在 non-websocket 请求中。我的猜测是您的上游服务器不介意 GET 请求,但出于某种原因 POST/PUT。
如果您不使用 websockets,您可以将其删除。
如果你使用的是websockets,你需要nginx根据请求是否是websockets添加或不添加这些headers。这样的事情应该有效:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
location /fusion/api {
proxy_pass ...
...
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
有关详细信息,请参阅 here。