Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nginx prepends post request body with response data #951

Open
faizangulzar opened this issue Dec 9, 2024 · 4 comments
Open

Nginx prepends post request body with response data #951

faizangulzar opened this issue Dec 9, 2024 · 4 comments

Comments

@faizangulzar
Copy link

I have set up my Laravel API with Docker(version: 26.1.1), Nginx(image: nginx:stable-alpine), and PHP(image: php:7.4-fpm-alpine) on Debian vps.

For a few days I'm struggling with a strange problem: The result I receive for my API request does not only include the valid response, but also the parameters that I send along with the post request;

Request:
{ "email": "[email protected]", "password": "xxxxxxx" }

Response:
{ "email": "[email protected]", "password": "xxxxxxx" }{ "token": "xxxxxxxxxxxxxxxxxxxxxxxxxx", "type": "xxxxxxxx" }

This response does not come with a content-type: application/json but as text/html. It seems like the post request body is prepended to the response data of my API. This results in a JSON parse error on my client.
After restarting the nginx server, the problem disappeared temporarily and then started again. I checked in both Nginx and laravel logs, there would be no error.

@oxpa
Copy link
Collaborator

oxpa commented Dec 9, 2024

Log upstream related metrics (at least address, time, status and length ) and compare those with what you have in nginx response.
If the length matches - it's the upstream that behaves for you.
If upstream response length is lower than the length of the response - post your configuration, please.

But overall, this question has nothing to do with docker image of nginx, really.

@faizangulzar
Copy link
Author

As per your instructions, I have logged upstream response length and added information below. Another thing I want to let you know that when I try this whole setup without docker with same versions of nginx and php on another debian vps, it works fine without any issue.

upstream related metrics
[10/Dec/2024:10:24:35 +0000] "POST /url/url/url HTTP/1.1" 200 upstream_response_length=416 upstream_response_time=0.214 upstream_status=200 "-" "PostmanRuntime/7.43.0"

nginx response size in postman

Response Size = 647 B
  Headers = 395 B
  Body = 252 B
  Uncompressed = 393 B

nginx/default.conf

log_format upstream_log '[$time_local] "$request" $status '
                        'upstream_response_length=$upstream_response_length '
                        'upstream_response_time=$upstream_response_time '
                        'upstream_status=$upstream_status '
                        '"$http_referer" "$http_user_agent"';

server {
    listen 80;
    index index.php index.html;
    server_name xx.xxx.com;
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;

    ...

    location ~ \.php$ {
        access_log /var/log/nginx/upstream_access.log upstream_log;
        fastcgi_intercept_errors on;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        include fastcgi.conf;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param  REQUEST_METHOD $request_method;
        fastcgi_param HTTP_MOD_REWRITE on;
    }

    ...

}

docker-compose.yml

version: "3"

services:
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    volumes:
      - ../:/var/www/html
      - ./default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
    network_mode: host

  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    environment:
      DB_HOST: xxxxxxxxx
      DB_PORT: xxxxxxxxx
      DB_DATABASE: xxxxxxxxx
      DB_USERNAME: xxxxxxxxx
      DB_PASSWORD: xxxxxxxxx
      REDIS_HOST: xxxxxxxx
    volumes:
      - ../:/var/www/html
    command: |
      sh -c "chown -R www-data:www-data /var/www/html && php-fpm"
    network_mode: host

  redis:
    build:
      context: ./redis
      dockerfile: Dockerfile
    container_name: redis
	command: sh -c 'chown -R redis:redis /data && redis-server'
    volumes:
      - ../../outside_project_folder/data/redis:/data
    network_mode: host

@oxpa
Copy link
Collaborator

oxpa commented Dec 10, 2024

@faizangulzar first of all, I don't see any matching numbers (body length reported by postman should match something in nginx logs, I suppose). Secondly, I don't know what was the request and response, so it's difficult for me to tell where the problem is.

What i meant is that upstream_response_length is response body length. And you can debug the problem further youself.
Say, if I write a configuration that does "return 200 '123\n';" it returns 4 symbols. And upstream_response_length is 4 for me.
Next, I test it with curl: curl $URL | wc -c this gives me the same "4" as the output.
And this result doesn't depend on compression on anything. And I can see upstream_response_length matches whatever I got from nginx.

Please, try similar approach: you can start a shell in the container with docker exec -it nginx /bin/sh (or similar), install curl with apk add curl.
You can then use postman to get proper curl command as in this SO question https://stackoverflow.com/questions/49432735/converting-a-postman-request-to-curl
And then try the curl | wc -c pointing it at the local nginx. The number from this command should match the number in logs.

If upstream_response_length doesn't match the curl | wc -c then I don't have any good ideas.

@oxpa
Copy link
Collaborator

oxpa commented Dec 10, 2024

It's also worth mentioning that it's not that easy to make nginx prepend request body to a reply. It is possible but requires some fiddling with configuration. So it's probably not an nginx problem, really

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants