Description
It seems that $_POST
and http_build_query
are not symmetrical. Currently, $_POST
is tried first when reading the original POST request:
} elseif ('POST' == $request_method) {
$request_params = $_POST;
if (empty($request_params)) {
$data = file_get_contents('php://input');
if (!empty($data)) {
$request_params = $data;
}
}
} elseif ('PUT' == $request_method || 'DELETE' == $request_method) {
$request_params = file_get_contents('php://input');
} else {
$request_params = null;
}
And if $_POST
gets some content above, then http_build_query
is used when passing the request to the remote server:
// add data for POST, PUT or DELETE requests
if ('POST' == $request_method) {
$post_data = is_array($request_params) ? http_build_query($request_params) : $request_params;
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
} elseif ('PUT' == $request_method || 'DELETE' == $request_method) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_method);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_params);
}
Note that $_POST
percent decodes if needed, but http_build_query
percent encodes whenever possible.
For example, consider Content-Type: application/x-www-form-urlencoded
with a POST body including an @
that (erroneously) is not percent-encoded:
[email protected]&password=sEcr3t
Here, $_POST['user']
will simply return the original value as decoding is not needed: [email protected]
. However, http_build_query
will encode the @
to read %40
. And the original Content-Length
header will not be increased to make up for the two extra characters. Hence, the remote server may get a truncated body.
I'm not using PHP a lot, but I'd be tempted to avoid any parsing that $_POST
does, and always use php://input
. However:
php://input
is not available withenctype="multipart/form-data"
So maybe something like the following would be better?
} elseif ('POST' == $request_method) {
$data = file_get_contents('php://input');
if (!empty($data)) {
$request_params = $data;
}
else {
$request_params = $_POST;
}
(This works for me, but I have not tested with enctype="multipart/form-data"
.)