REST request data can't be read in 'put' method
Solution 1
The parse_str
is used to parse a query string(in form arg1=xyz&arg2=abc) and not JSON. You need to use json_decode
to parse JSON strings.
$data = json_decode(file_get_contents("php://input"), true);
Here is the code that works:
$method = strtolower($_SERVER['REQUEST_METHOD']);
$data = array();
switch ($method) {
case 'get':
$data = $_GET;
break;
case 'post':
$data = $_POST;
break;
case 'put':
$data = json_decode(file_get_contents("php://input"), true);
break;
}
var_dump($data);
Curl command:
curl -i -X PUT -d '{"name":"a","data":"data1"}' http://my-server/my.php
Response:
array(2) {
["name"]=>
string(1) "a"
["data"]=>
string(5) "data1"
}
Solution 2
Could it be that there's something wrong with the web server?
Actually yes. After banging my head on this for a few hours, I found that the culprit for the missing data was this:
Note: Prior to PHP 5.6, a stream opened with php://input could only be read once
Another piece of code was accessing the php://input before my code, and on servers with php < 5.6, this caused the input to be lost.
Only on PUT requests that is.
Igor
Updated on June 27, 2022Comments
-
Igor almost 2 years
I'm trying to develop a RESTful API with PHP without using frameworks. While processing the request, the client data cannot be read using this:
parse_str(file_get_contents("php://input"), $put_vars);
Here's the full code:
public static function processRequest() { //get the verb $method = strtolower($_SERVER['REQUEST_METHOD']); $request = new Request(); $data = array(); $put_vars = array(); switch ($method) { case 'get': $data = $_GET; break; case 'post': $data = $_POST; break; case 'put': parse_str(file_get_contents("php://input"), $put_vars); $data = $put_vars; echo $data; break; } $request->setMethod($method); $request->setRequestVars($data); if (isset($data['data'])) { $request->setData(json_decode($data)); echo 'data exists'; } return $request; }
I'm using cURL to rest the API and when I type this command:
curl -i -X PUT -d '{"name":"a","data":"data1"}' http://localhost/my-rest-api/api/
I only get this back:Array""
Why isn't the proper data returned?
EDIT
I also tested another piece of code that is supposed to be an API and
file_get_contents('php://input', true)
still returns null. Could it be that there's something wrong with the web server?-
Shimon Rachlenko over 10 yearsdon't use
echo $data
for testing, use eithervar_dump($data)
orprint_r($data)
-
Shimon Rachlenko over 10 yearsI recreated your code on my server and was able to run it using your curl command and it produces required result.
-
-
Igor over 10 years@ShimoRachlenko I Just edited the code and still get the same results
-
Shimon Rachlenko over 10 yearsCan you confirm that
file_get_contents("php://input")
give you the data you send? And another thing - how do you output the result? -
Igor over 10 yearsHow can it be confirmed? So far the output is printed using 'echo', as shown above.
-
Shimon Rachlenko over 10 yearsDo
echo file_get_contents("php://input")
, and also doprint_r($data)
after you json_decode it. -
Igor over 10 yearsI also noticed that if I send data using 'POST', $_POST is empty.
-
Shimon Rachlenko over 10 years@Igor answer updated. The main point is to use
var_dump
instead ofecho
for debug. -
Igor over 10 yearsCan you add the cURL command and response also? I get 'null' using the same code
-
Mike Brant over 10 years@Igor If you are sending JSON data via POST, it will also not be parsed into $_POST. What you need to do is set you HTTP Content header for the request to be
application/json
, such that PHP will not try to parse the data as a query string, and then you need tojson_decode
the raw input data as suggested here. This applies to any cases where you are sending data via JSON. -
Igor over 10 years@MikeBrant Can I set the Content Header in cURL while making requests? I hope that's what you meant.
-
Igor over 10 years@ShimonRachlenko Thanks for the edit, but I still get different response with your code. Here's what I get:
<pre class='xdebug-var-dump' dir='ltr'><font color='#3465a4'>null</font></pre>
Do you have any idea why? -
Igor over 10 years@MikeBrant Did you also try this code to see if it's working?
-
Mike Brant over 10 years@Igor How would I do that? I have no access to your code or servers. It seems that you are doing some sort of var_dump via xdebug based on the returned content. Looks like you need to do some debugging.
-
Igor over 10 years@MikeBrant The code I use is the one from this answer. I created an index.php file with this code in it, placed it on a server, used cURL to test the PUT method and despite Shimon's claim, get_file_contents('php://input') returns null. I don't see what I'm doing wrong.
-
Vijay Kumar over 6 yearsThis was very helpful. Thank you for sharing.