简体   繁体   English

Nginx 在响应数据之前添加来自其缓冲区的发布请求正文内容?

[英]Nginx prepends response data with post request body content from its' buffer?

For a few days i'm struggling with a strange problem in a laravel application that runs in a docker container on an ubuntu system and uses laravel/rebing-graphql vendor to serve graphql query responses.几天来,我在一个在ubuntu系统上的 docker 容器中运行并使用laravel/rebing-graphql供应商提供graphql查询响应的laravel应用程序中遇到了一个奇怪的问题。

So i'm using the GraphiQL interface to send graphql requests to my backend.所以我使用GraphiQL接口将 graphql 请求发送到我的后端。 The result i receive for my request does not only include the valid response, but also the parameters i send along with the post request;我收到的请求结果不仅包括有效响应,还包括我与发布请求一起发送的参数;

"{\"query\":\"query Users {\\n  users(pagination: {offset: 0, limit: 1}) {\\n    items {\\n      id\\n    }\\n  }\\n}\",\"variables\":null,\"operationName\":\"Users\"}{\"data\":{\"users\":{\"items\":[{\"id\":53}]}}}"

This response does not come with a content-type: application/json but as text/html .此响应不带有 content-type: application/json而是text/html It seems like the post request body is prepended to the response data of my API.似乎 post 请求正文已添加到我的 API 的响应数据中。 This results in a JSON parse error on my client.这会导致我的客户端出现 JSON 解析错误。 The API data part here itself seems valid.这里的 API 数据部分本身似乎是有效的。

The most strange thing of this issue is, that it occurs on every second (!) request.这个问题最奇怪的是,它发生在每一(!)请求上。 So about 50% of my requests are receiving a valid response which does come as json and without any prepended post request body.因此,我大约 50% 的请求都收到了一个有效的响应,该响应确实以 json 格式出现,并且没有任何前置的 post 请求正文。

I tried to analyse the root cause of this issue and i was not able to find a place in the code where the parameters are echoed as an additional output.我试图分析此问题的根本原因,但我无法在代码中找到将参数作为附加输出回显的位置。

Does an nginx configuration cause a prepending of post request body contents? nginx 配置是否会导致发布请求正文内容的前置?

During my further investigation, i started to replace the index.php file inside laravels' public directory and created a custom index.php which contains nothing but an exit("test") ;在我进一步调查期间,我开始替换 laravel 的公共目录中的index.php文件并创建了一个自定义index.php ,其中只包含一个exit("test") execution .执行 The result was unexpected.结果出乎意料。 I still got my post parameters prepended to the output on every second request:我仍然在每个第二个请求的输出中附加了我的 post 参数:

"{\"query\":\"query Users {\\n  users(pagination: {offset: 0, limit: 1}) {\\n    items {\\n      id\\n    }\\n  }\\n}\",\"variables\":null,\"operationName\":\"Users\"}test"

I'm using a docker image from nginx:alpine and php:7.4-fpm-alpine.我正在使用来自 nginx:alpine 和 php:7.4-fpm-alpine 的 docker 映像。 The docker container opens a port which gets a proxy from an apache2 server which runs on my root system. docker 容器打开一个端口,该端口从运行在我的根系统上的 apache2 服务器获取代理。

This is my nginx default config:这是我的 nginx 默认配置:

server {
listen 80;

server_name my-domain.com;
error_log  /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;

root /var/www/html/public;

index index.php index.html;

location / {
    client_max_body_size 100M;

    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Max-Age 1728000;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE, HEAD";
        add_header Content-Length 0;
        add_header Content-Type "text/plain; charset=UTF-8";
        add_header Access-Control-Allow-Headers "Origin,X-Requested-With,Content-Type,Accept,X-CSRF-Token,X-XSRF-TOKEN,Authorization";
        return 204;
    }

    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}

location ~ \.php$ {
    client_max_body_size 100M;

    if ($http_origin ~* "^(blob:)?http(s)?://www.my-domain.com(:[0-9]{2,4})?$") {
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
        add_header Access-Control-Allow-Headers "Origin,X-Requested-With,Content-Type,Accept,X-CSRF-Token,X-XSRF-TOKEN,Authorization";
    }

    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass epapistagephp:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
} 
}

Is there anyone who already experienced this kind of behaviour or do you have a hint on where to start with a further analysation?是否有人已经经历过这种行为,或者您是否暗示从哪里开始进一步分析?

Thank you so much in advance!!非常感谢你!

Greets Jules问候朱尔斯

After month of struggling and using work arounds like switching to Apache2 etc... I guess i found a solution.经过一个月的努力和使用变通办法,如切换到 Apache2 等......我想我找到了一个解决方案。

As described in my original Question, the problem occured after a the nginx server was running for a while already.如我的原始问题所述,问题发生在 nginx 服务器已经运行了一段时间之后。 After a reload of the nginx server the problem disappeared temporarily.重新加载 nginx 服务器后,问题暂时消失了。 With apache2 i did not have this problem.使用 apache2 我没有这个问题。 So that way i kind of isolated the issue to nginx itself.这样我就可以将问题与 nginx 本身隔离开来。

I now tried to disable the request caching of nginx by setting:我现在尝试通过设置禁用 nginx 的请求缓存:

proxy_request_buffering off; <===

client_max_body_size 500M;
client_body_buffer_size 500M;

I also raised the buffering size for testing and it works right now.我还提高了测试的缓冲大小,现在可以正常工作了。 This issue did not seem to be related to Laravel, Graphql or PHP at all.这个问题似乎与 Laravel、Graphql 或 PHP 完全无关。 For anyone who may stumble across this topic, i'm going to edit my original question accordingly.对于可能偶然发现此主题的任何人,我将相应地编辑我的原始问题。 I hope this may help someone in the future.我希望这可以在将来对某人有所帮助。

If you use port 9000, you will have this problem.如果使用9000端口,就会出现这个问题。 Use port 8000.使用端口 8000。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM