I can't seem to find a real answer to this problem so here I go:
How do you parse raw HTTP request data in multipart/form-data
format in PHP? I know that raw POST is automatically parsed if formatted correctly, but the data I'm referring to is coming from a PUT request, which is not being parsed automatically by PHP. The data is multipart and looks something like:
------------------------------b2449e94a11c
Content-Disposition: form-data; name="user_id"
3
------------------------------b2449e94a11c
Content-Disposition: form-data; name="post_id"
5
------------------------------b2449e94a11c
Content-Disposition: form-data; name="image"; filename="/tmp/current_file"
Content-Type: application/octet-stream
�����JFIF���������... a bunch of binary data
I'm sending the data with libcurl like so (pseudo code):
curl_setopt_array(
CURLOPT_POSTFIELDS => array(
'user_id' => 3,
'post_id' => 5,
'image' => '@/tmp/current_file'),
CURLOPT_CUSTOMREQUEST => 'PUT'
);
If I drop the CURLOPT_CUSTOMREQUEST bit, the request is handled as a POST on the server and everything is parsed just fine.
Is there a way to manually invoke PHPs HTTP data parser or some other nice way of doing this? And yes, I have to send the request as PUT :)
I'm surprised no one mentioned
parse_str
ormb_parse_str
:http://php.net/manual/en/function.mb-parse-str.php
I haven't dealt with http headers much, but found this bit of code that might help
From http://php.net/manual/en/function.http-parse-headers.php
Edit - please read first: this answer is still getting regular hits 7 years later. I have never used this code since then and do not know if there is a better way to do it these days. Please view the comments below and know that there are many scenarios where this code will not work. Use at your own risk.
--
Ok, so with Dave and Everts suggestions I decided to parse the raw request data manually. I didn't find any other way to do this after searching around for about a day.
I got some help from this thread. I didn't have any luck tampering with the raw data like they do in the referenced thread, as that will break the files being uploaded. So it's all regex. This wasnt't tested very well, but seems to be working for my work case. Without further ado and in the hope that this may help someone else someday:
Usage by reference (in order not to copy around the data too much):
Have you looked at
fopen("php://input")
for parsing the content?Headers can also be found as
$_SERVER['HTTP_*']
, names are always uppercased and dashes become underscores, eg$_SERVER['HTTP_ACCEPT_LANGUAGE']
.I would suspect the best way to go about it is 'doing it yourself', although you might find inspiration in multipart email parsers that use a similar (if not the exact same) format.
Grab the boundary from the Content-Type HTTP header, and use that to explode the various parts of the request. If the request is very large, keep in mind that you might store the entire request in memory, possibly even multiple times.
The related RFC is RFC2388, which fortunately is pretty short.
I used Chris's example function and added some needed functionality, such as R Porter's need for array's of $_FILES. Hope it helps some people.
Here is the class & example usage