Nginx 在响应数据前面加上来自其缓冲区的后请求正文内容?



几天来,我一直在努力解决laravel应用程序中的一个奇怪问题,该应用程序在ubuntu系统上的docker容器中运行,并使用laravel/rebing graphql供应商提供graphql查询响应。

因此,我使用GraphiQL接口将graphql请求发送到我的后端。我收到的请求结果不仅包括有效响应,还包括我在发布请求时发送的参数;

"{"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}]}}}"

此响应没有附带内容类型:application/json,而是作为text/html。请求后的主体似乎是为我的API的响应数据准备的。这导致我的客户端出现JSON解析错误。此处的API数据部分本身似乎是有效的。

这个问题最奇怪的是,它发生在每(!(请求上。因此,我大约50%的请求都收到了一个有效的响应,它是json格式的,没有任何预先准备好的请求后正文。

我试图分析这个问题的根本原因,但我无法在代码中找到一个位置,在那里参数作为附加输出得到响应。

nginx配置是否会导致请求后正文内容的预处理

在我的进一步调查中,我开始替换laravels的公共目录中的index.php文件,并创建了一个自定义的index.php,其中只包含一个exit("test")执行。结果出乎意料。我仍然在每一秒的请求中为输出预先准备了我的后期参数:

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

我使用的是nginx:alpine和php:7.4-fpm-alpine中的docker图像。docker容器打开一个端口,该端口从运行在我的根系统上的apache2服务器获取代理。

这是我的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;
} 
}

有没有人已经经历过这种行为,或者你有没有暗示从哪里开始进行进一步的分析?

提前非常感谢!!

问候Jules

经过一个月的挣扎和使用解决方案,如切换到Apache2等。。。我想我找到了解决办法。

正如我在最初的问题中所描述的,这个问题发生在nginx服务器已经运行了一段时间之后。重新加载nginx服务器后,问题暂时消失。有了apache2,我就没有这个问题了。因此,我将问题隔离到nginx本身。

我现在尝试通过设置来禁用nginx的请求缓存:

proxy_request_buffering off; <===
client_max_body_size 500M;
client_body_buffer_size 500M;

我还提高了测试的缓冲大小,现在它可以工作了。这个问题似乎根本与Laravel、Graphql或PHP无关。对于任何可能偶然发现这个话题的人,我将相应地编辑我最初的问题。我希望这对将来的某个人有所帮助。

如果使用端口9000,则会出现此问题。使用端口8000。

您的问题很可能与PHP的auto_prepend_file指令有关。注意,";none";需要禁用自动预处理。

最新更新