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:
user=me@example.com&password=sEcr3t
Here, $_POST['user'] will simply return the original value as decoding is not needed: me@example.com. 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 with enctype="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".)
It seems that
$_POSTandhttp_build_queryare not symmetrical. Currently,$_POSTis tried first when reading the original POST request:And if
$_POSTgets some content above, thenhttp_build_queryis used when passing the request to the remote server:Note that
$_POSTpercent decodes if needed, buthttp_build_querypercent encodes whenever possible.For example, consider
Content-Type: application/x-www-form-urlencodedwith a POST body including an@that (erroneously) is not percent-encoded:Here,
$_POST['user']will simply return the original value as decoding is not needed:me@example.com. However,http_build_querywill encode the@to read%40. And the originalContent-Lengthheader 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
$_POSTdoes, and always usephp://input. However:So maybe something like the following would be better?
(This works for me, but I have not tested with
enctype="multipart/form-data".)