3

My problem seems similar with $_POST is empty. Nginx OSx , $_POST is empty in nginx and $_GET filled but $_REQUEST is empty, however I cannot find a solution to work for me there.

Long story short, I cannot get my POST request through to a file named server.php on my server.

Let's assume that my server.php contains only something like:

<?php var_dump($_REQUEST);

and my sites-available/domain.tld file contains the following:

server {

    root /var/www/domain.tld/current/dist;
    index index.html index.htm;

    server_name domain.tld;


    location / {
        try_files $uri $uri/ index.php?$query_string =404;
    }

    location ~ \.php$ {
            #limit_except POST {
            #    allow 127.0.0.1;
            #    deny  all;
            #}

            #if ( $request_method !~ ^POST$ ) {
            #    return 405;
            #}

            include snippets/fastcgi-php.conf;

            fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
            #fastcgi_param REQUEST_METHOD $request_method;
            fastcgi_param  REQUEST_METHOD     $echo_request_method;
            fastcgi_param CONTENT_TYPE $content_type;
            fastcgi_param CONTENT_LENGTH $content_length;
            fastcgi_param REQUEST_BODY $request_body;
            fastcgi_param QUERY_STRING $query_string;

    }

    location ~ /\.ht {
            deny all;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    server_name www.domain.tld;
    return 301 $scheme://domain.tld$request_uri;
}

server {
    if ($host = domain.tld) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;

        server_name domain.tld;
    return 404; # managed by Certbot

}

Whatever 'POST' request I am making on the server.php will just not send any parameters through.

Output of server.php would be array(0) {}

Some other info:

  • Request is made on Request URL: https://domain.tld/server.php

  • Request Method: POST

  • Status Code: 200 OK

A GET request sent like https://domain.tld/server.php?foo=bar will show me the correct foo variable sent over with a value of bar

If needed I can provide details on the request itself. (using axios in a vue app).

Please advise...

Angelin Calu
  • 1,905
  • 8
  • 24
  • 44
  • 3
    What's your request `Content-Type` header? I'd like to rule this out as a possibility, but if that header's value is `application/json`, then you'll need to either modify your request or retrieve that data from the `php://input` stream. PHP expects data to be of the `Content-Type` `application/x-www-form-urlencoded` when storing in request superglobals. – B. Fleming Aug 23 '19 at 20:12
  • 2
    Also `multipart/form-data` works. – Barmar Aug 23 '19 at 20:40
  • my `Content-Type` is indeed `application/json;charset=UTF-8`, I'll tackle that in a minute. – Angelin Calu Aug 23 '19 at 20:43
  • 1
    `$echo_request_method` is non-documented variable – Deadooshka Aug 24 '19 at 00:15

1 Answers1

6

This answer may be a bit late, but for the sake of anyone else encountering this same problem:

The issue turned out to be that the Content-Type header had the value application/json. When PHP parses data to place into the $_POST super global, it expects this header to have the value application/x-www-form-urlencoded or multipart/form-data, the web standard content types. When receiving application/json content type data, you must access it from the php://input stream.

A solution will end up looking something like this:

$json_string_data = file_get_contents('php://input');
$decoded_data = json_decode($json_string_data, true);

If your application expects the data to be available in the $_POST super global, then the following (admittedly hacky) solution can be used:

$json_string_data = file_get_contents('php://input');
$decoded_data = json_decode($json_string_data, true);
$_POST = $decoded_data;

Or, for brevity's sake:

$_POST = json_decode(file_get_contents('php://input'), true);
B. Fleming
  • 7,170
  • 1
  • 18
  • 36