How to get body of a POST in php?

363,650

Solution 1

To access the entity body of a POST or PUT request (or any other HTTP method):

$entityBody = file_get_contents('php://input');

Also, the STDIN constant is an already-open stream to php://input, so you can alternatively do:

$entityBody = stream_get_contents(STDIN);

From the PHP manual entry on I/O streamsdocs:

php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".

Specifically you'll want to note that the php://input stream, regardless of how you access it in a web SAPI, is not seekable. This means that it can only be read once. If you're working in an environment where large HTTP entity bodies are routinely uploaded you may wish to maintain the input in its stream form (rather than buffering it like the first example above).

To maintain the stream resource something like this can be helpful:

<?php

function detectRequestBody() {
    $rawInput = fopen('php://input', 'r');
    $tempStream = fopen('php://temp', 'r+');
    stream_copy_to_stream($rawInput, $tempStream);
    rewind($tempStream);

    return $tempStream;
}

php://temp allows you to manage memory consumption because it will transparently switch to filesystem storage after a certain amount of data is stored (2M by default). This size can be manipulated in the php.ini file or by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes.

Of course, unless you have a really good reason for seeking on the input stream, you shouldn't need this functionality in a web application. Reading the HTTP request entity body once is usually enough -- don't keep clients waiting all day while your app figures out what to do.

Note that php://input is not available for requests specifying a Content-Type: multipart/form-data header (enctype="multipart/form-data" in HTML forms). This results from PHP already having parsed the form data into the $_POST superglobal.

Solution 2

return value in array

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

Solution 3

A possible reason for an empty $_POST is that the request is not POST, or not POST anymore... It may have started out as post, but encountered a 301 or 302 redirect somewhere, which is switched to GET!

Inspect $_SERVER['REQUEST_METHOD'] to check if this is the case.

See https://stackoverflow.com/a/19422232/109787 for a good discussion of why this should not happen but still does.

Solution 4

function getPost()
{
    if(!empty($_POST))
    {
        // when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
        // NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
        return $_POST;
    }

    // when using application/json as the HTTP Content-Type in the request 
    $post = json_decode(file_get_contents('php://input'), true);
    if(json_last_error() == JSON_ERROR_NONE)
    {
        return $post;
    }

    return [];
}

print_r(getPost());

Solution 5

This is an exemple of how to create a php api with file_get_contents("php://input") and used in javascript using ajax with XMLHttpRequest.

var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
    console.log("done");
            }
        }
    };
    xhttp.open("POST", "http://127.0.0.1:8000/api.php", true);
    xhttp.send(JSON.stringify({
        username: $(this).val(),
        email:email,
        password:password
    }));

$data = json_decode(file_get_contents("php://input"));
$username  =  $data->username;
$email  =   $data->email;
$password  =   $data->password;
Share:
363,650
Itay Moav -Malimovka
Author by

Itay Moav -Malimovka

SOreadytohelp Below are some of the open source projects I work on. A PHP Library the wrappes SurveyMonkey's API https://github.com/itay-moav/TheKofClient A tool to Schema Check, manage Stored Procedures, Triggers, Views and get autocompletion: https://github.com/itay-moav/rahl_commander A fun way to point users at the right direction in your site ;-) https://github.com/itay-moav/babahandofgod An old version of WMD which I converted to Mootools, 8 years ago... http://moowmd.awardspace.info Feel free to contact me through linkedin http://www.linkedin.com/in/itaymoav

Updated on July 08, 2022

Comments

  • Itay Moav -Malimovka
    Itay Moav -Malimovka almost 2 years

    I submit as POST to a php page the following:

    {a:1}
    

    This is the body of the request (a POST request).
    In php, what do I have to do to extract that value?

    var_dump($_POST); 
    

    is not the solution, not working.

  • scy
    scy over 10 years
    Please note that afaics, the STDIN stream is not available on systems running PHP using CGI, i.e. via mod_fcgid or mod_fastcgi etc.
  • nullability
    nullability over 10 years
    The preferred method for accessing the raw POST data is php://input. $HTTP_RAW_POST_DATA is not available with enctype="multipart/form-data".
  • Anvar Pk
    Anvar Pk over 8 years
    but, i am passing variable(as form-data) with the request , how can i access specified value, i am passing grant_type=password&username=user&password=pass as form-data body with the request, how will i get grant_type from " $entityBody"
  • Charles
    Charles over 8 years
    This feature was DEPRECATED in PHP 5.6.0, and REMOVED as of PHP 7.0.0.
  • Itay Moav -Malimovka
    Itay Moav -Malimovka over 8 years
    This question was asked in the context of developing a REST api platform.
  • Legolas
    Legolas over 8 years
    I'm not sure what you mean? A REST api might just as well find redirects in it's path, that's the issue I had.
  • Itay Moav -Malimovka
    Itay Moav -Malimovka over 8 years
    I meant when I asked the question, I was not trying to resolve a bug, but rather trying to figure out how to develop it.
  • DesertEagle
    DesertEagle over 7 years
    this hint saved my day. the receiving server has been reconfigured to redirect to https whoch broke some API clients.
  • YakovL
    YakovL over 6 years
    according to my test, this php://input is empty for application/x-www-form-urlencoded content-type as well (besides multipart/form-data)
  • Itay Moav -Malimovka
    Itay Moav -Malimovka over 5 years
    (PECL pecl_http >= 0.10.0)
  • zackygaurav
    zackygaurav over 5 years
    Actually my request was POST but after inspecting it was showing that it was GET. Once I added a / at the end of my URL, it started showing POST. Weird!
  • Legolas
    Legolas over 5 years
    @zackygaurav maybe it was being redirected from the url without / to the one with / ?
  • Sinus the Tentacular
    Sinus the Tentacular over 5 years
    To expand on @scy's response: STDIN is not available, but php://input is. So while on (Fast)CGI configurations stream_get_contents(STDIN) won't work, file_get_contents("php://input") will.
  • Rick
    Rick almost 5 years
    function doesn't exist.
  • Anthony Rutledge
    Anthony Rutledge over 4 years
    What this bit of logic is missing is a test of the value found in the Content-Type header. It does not follow that just because $_POST is empty that JSON must have been submitted, or that if json_last_error() == JSON_ERROR_NONE is false, that an empty array should be returned. What if someone has submitted XML or YAML? Add a test for the Content-Type and go from there.
  • Anthony Rutledge
    Anthony Rutledge over 4 years
    In this scenario, you now have to loop through the $data associative array to check if each value is encoded the way you desire. The "stream-to-datatype" way of looking at things may be simplistic, but it may not be as efficient as dealing with encoding in the "stream form" using a stream filter. If you are not handling encoding issues and simply sanitizing and validating, you are missing a step.
  • Anthony Rutledge
    Anthony Rutledge over 4 years
    Also, the HTTP request method can factor in determining if you want to accept input data. See the $_SERVER superglobal for useful values to check.
  • T.Todua
    T.Todua over 3 years
    the answers dont have so many upvotes as above comment :)
  • Azade
    Azade about 3 years
    it is a very good way to post data from body in php mvc.