asp net core 3 在发布后获取带有正文内容的 POST 操作的 BadRequest 响应

Posted

技术标签:

【中文标题】asp net core 3 在发布后获取带有正文内容的 POST 操作的 BadRequest 响应【英文标题】:asp net core 3 Getting BadRequest response on POST action with body content after publish 【发布时间】:2020-04-01 17:23:06 【问题描述】:

我正在使用 asp.net core 3 构建一个网站,我将其托管在 Debian 9 服务器上,并使用 nginx 作为反向代理。我遇到了这个问题,当我在 Visual Studio 中本地运行应用程序时,我的 POST 请求确实有效,但是当我发布应用程序并将其上传到我的服务器时,它们突然不再工作了。

这是我用于测试的控制器:

public class TestController : Controller

    [HttpPost]
    public IActionResult Ping()
    
        return Ok();
    

    [HttpPost]
    public IActionResult Echo(string message)
    
        return Ok(message);
    

    [HttpPost]
    public IActionResult FormEcho([FromForm]string message)
    
        return Ok(message);
    

我正在使用邮递员来测试这些端点。

Ping

使用不带任何参数的发布请求会在本地和服务器上按预期给出 200。 使用带有 x-www-form-urlencoded 内容的 post 请求在本地提供 200,但在服务器上提供 400。

Echo:

带有查询字符串参数的发布请求在本地和服务器上都返回代码为 200 的消息。 将消息作为 x-www-form-urlencoded 内容的发布请求在本地返回带有代码 200 的消息,但在服务器上给出 400。

FormEcho:

将消息作为 x-www-form-urlencoded 内容的发布请求在本地返回带有代码 200 的消息,但在服务器上给出 400。

从这个测试中,我认为在我的服务器上以某种方式拒绝了带有正文内容的发布请求。我还从日志中注意到,对于在服务器上返回 400 的请求,日志中没有任何内容,就好像该请求甚至没有到达我的应用程序一样。

为什么我的应用程序拒绝带有正文内容的帖子请求?


编辑: 这是我在 nginx 中的配置:

server 
    listen        443 ssl;
    listen        [::]:443 ssl;

    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    server_name   51.38.35.10;

    error_log /var/log/nginx/error.log info;

    location / 
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection 'upgrade';
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    


server 
    listen        80;
    listen        [::]:80;

    server_name   51.38.35.10;

    return 302 https://$server_name$request_uri;

【问题讨论】:

“日志中没有任何内容,好像请求甚至没有到达我的应用程序” – 那么也许没有?检查 nginx 的日志以查看是否发生了任何事情。您也可以尝试直接在服务器上运行应用程序(不使用 nginx),看看它是否可以这样工作。还可以尝试提高日志级别,以便您可以看到调试消息。 如果您的 ASP 服务器上没有关于请求的日志,但 nginx 服务器中有日志,则问题出在您那里的配置。您应该发布配置,以及来自 nginx 的任何错误日志。此外,nginx 可以在调试模式下启动,它会生成更多有用的日志。 @SebastianRedl 谢谢你的建议。我在问题中包含了我的 nginx 配置。我检查了日志,没有关于 400 错误的消息。我将日志级别设置为信息,因为我读到信息级别记录了 400 个错误,但没有消息。只有关于我的自签名证书的警告。我看看能不能在调试模式下启动nginx。 @poke 谢谢,我会尝试在没有 nginx 的情况下运行应用程序,看看会发生什么。 不知道这是否与此问题有关,但我只看到 Connection 'upgrade' 仅使用 websocket 配置。请改用proxy_set_header Connection keep-alive 【参考方案1】:

如果 ASP.NET Core 应用程序甚至不记录传入请求(而其他应用程序工作),那么它似乎实际上并没有收到任何传入请求。在这种情况下,可能是您的反向代理配置没有让这些请求通过您的应用。

我通常通过 nginx 对 ASP.NET Core 应用使用如下配置:

location / 
    proxy_pass         http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection keep-alive;
    proxy_set_header   Host $host;
    proxy_cache_bypass $http_upgrade;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;

那也是recommendation from the official ASP.NET Core docs。

设置不同的Connection 标头值,尤其是Upgrade,似乎有点问题。我个人刚刚看到Upgrade 值与 WebSockets 的 HTTP Upgrade 标头一起使用。

所以调整 nginx 配置应该可以解决你的问题。

注意Connection keep-alive

【讨论】:

以上是关于asp net core 3 在发布后获取带有正文内容的 POST 操作的 BadRequest 响应的主要内容,如果未能解决你的问题,请参考以下文章

登录 ASP.NET Core 3.1 后如何获取用户信息

由于请求正文过大,大文件上传到 ASP.NET Core 3.0 Web API 失败

如何在 ASP.NET CORE 3.0 中配置路由以使用带有 [FromQuery] 参数的重载 [HttpGet] 方法?

在 cookie 中存储 JWT 令牌后,如何在 ASP.NET Core 3.1 中破坏该 cookie 并获取信息

ASP.NET Core 在 json 发布请求正文中传递 antiforgerytoken

如何在 ASP.NET Core 中间件中直接将响应正文设置为文件流?