Skip to content

Instantly share code, notes, and snippets.

@cwhsu1984
Last active March 17, 2023 01:59
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cwhsu1984/3419584ad31ce12d2ad5fed6155702e2 to your computer and use it in GitHub Desktop.
Save cwhsu1984/3419584ad31ce12d2ad5fed6155702e2 to your computer and use it in GitHub Desktop.
parse multi-dimensional form-data from PATCH request
<?php
// The code is inspired by the following discussions and post:
// http://stackoverflow.com/questions/5483851/manually-parse-raw-http-data-with-php/5488449#5488449
// http://www.chlab.ch/blog/archives/webdevelopment/manually-parse-raw-http-data-php
/**
* Parse raw HTTP request data
*
* Pass in $a_data as an array. This is done by reference to avoid copying
* the data around too much.
*
* Any files found in the request will be added by their field name to the
* $data['files'] array.
*
* @param array Empty array to fill with data
* @return array Associative array of request data
*/
function parse_raw_http_request($a_data = [])
{
// read incoming data
$input = file_get_contents('php://input');
// grab multipart boundary from content type header
preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
// content type is probably regular form-encoded
if (!count($matches))
{
// we expect regular puts to containt a query string containing data
parse_str(urldecode($input), $a_data);
return $a_data;
}
$boundary = $matches[1];
// split content by boundary and get rid of last -- element
$a_blocks = preg_split("/-+$boundary/", $input);
array_pop($a_blocks);
$keyValueStr = '';
// loop data blocks
foreach ($a_blocks as $id => $block)
{
if (empty($block))
continue;
// you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char
// parse uploaded files
if (strpos($block, 'application/octet-stream') !== FALSE)
{
// match "name", then everything after "stream" (optional) except for prepending newlines
preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches);
$a_data['files'][$matches[1]] = $matches[2];
}
// parse all other fields
else
{
// match "name" and optional value in between newline sequences
preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);
$keyValueStr .= $matches[1]."=".$matches[2]."&";
}
}
$keyValueArr = [];
parse_str($keyValueStr, $keyValueArr);
return array_merge($a_data, $keyValueArr);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment