Why isn't CURLOPT_POSTFIELDs accepting an array? Using PHP 8.2.15
I have two files:
// temp.php
exit(file_get_contents('php://input'));
// test.php
$fields = ['foo' => 'bar'];
$config = [
\CURLOPT_RETURNTRANSFER => true,
\CURLOPT_ENCODING => '',
\CURLOPT_MAXREDIRS => 10,
\CURLOPT_TIMEOUT => 10,
\CURLOPT_FOLLOWLOCATION => true,
\CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
];
$with_array_handle = \curl_init('http://localhost/temp.php');
\curl_setopt_array($with_array_handle, $config + [\CURLOPT_POSTFIELDS => $fields]);
$with_string_handle = \curl_init('http://localhost/temp.php');
\curl_setopt_array($with_string_handle, $config + [\CURLOPT_POSTFIELDS => http_build_query($fields)]);
echo '<pre>' . curl_exec($with_array_handle) . '</pre>';
echo '<pre>' . curl_exec($with_string_handle) . '</pre>';
temp.php
echos back the request body. test.php
requests temp.php
twice and echoes both responses so test.php
should be outputting the bodies of both requests to temp.php
.
but what I'm actually getting is
foo=bar
The first request's body is empty if I use CURLOPT_POSTFIELDS
. Why?
The PHP documentation specifically says CURLOPT_POSTFIELDS
accepts an array as input but that doesn't match the behavior I'm observing.
This parameter can either be passed as a urlencoded string like
para1=val1¶2=val2&...
or as an array with the field name as key and field data as value.
When you give it an array, the request is sent with Content-type: multipart/form-data
. Apparently this causes the PHP processor to read the body itself, and it's not available to php://input
. I suspect this is because this format is usually used for file uploads, so it needs to read the uploaded files into their temporary files, and built the $_FILES
array; it would be difficult to keep it available for the input stream to re-read.
In either case, the parameters are available in the $_POST
array.