Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending/Receiving PUT requests with PHP, having trouble parsing the request body?

Tags:

rest

php

I'm trying to build out a RESTful APi.

I'm sending a PUT request as so: /api/customer/1

$data['name'] = 'test';

$ch = curl_init('myurl/api/'.$name);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$results = json_decode(curl_exec($ch));

I am passing the $data list in the POSTFIELDS, which I assume will be in the request body.

When I go to parse, I am trying:

$params = file_get_contents('php://input');

However, I am not seeing the variable I passed in anywhere.

Any advice would be helpful, thank you.

like image 721
john Avatar asked Jul 13 '11 17:07

john


2 Answers

The value of $params = file_get_contents('php://input'); will be a string you need to use parse_str:

$input = file_get_contents('php://input');
parse_str($input, $params);
print_r($params);

Also note in some cases php://input can only be read once so you might have to store it.

like image 152
Glass Robot Avatar answered Oct 21 '22 12:10

Glass Robot


The accepted answer won't work for multipart/form-data, out of frustration I wrote my own method. This handles file uploads and multidimensional requests.

/**
 * @param string $formData Raw response request of type FormData
 * @param array $header Meta data for each part of the form data (optional)
 * @return array Processed form data
 */
public function parse_form_data($formData, &$header)
{
    $endOfFirstLine = strpos($formData, "\r\n");
    $boundary = substr($formData, 0, $endOfFirstLine);
    // Split form-data into each entry
    $parts = explode($boundary, $formData);
    $return = [];
    $header = [];
    // Remove first and last (null) entries
    array_shift($parts);
    array_pop($parts);
    foreach ($parts as $part) {
        $endOfHead = strpos($part, "\r\n\r\n");
        $startOfBody = $endOfHead + 4;
        $head = substr($part, 2, $endOfHead - 2);
        $body = substr($part, $startOfBody, -2);
        $headerParts = preg_split('#; |\r\n#', $head);
        $key = null;
        $thisHeader = [];
        // Parse the mini headers,
        // obtain the key
        foreach ($headerParts as $headerPart) {
            if (preg_match('#(.*)(=|: )(.*)#', $headerPart, $keyVal)) {
                if ($keyVal[1] == "name") $key = substr($keyVal[3], 1, -1);
                else {
                    if($keyVal[2] == "="){
                        $thisHeader[$keyVal[1]] = substr($keyVal[3], 1, -1);
                    }else{
                        $thisHeader[$keyVal[1]] = $keyVal[3];
                    }
                }
            }
        }
        // If the key is multidimensional,
        // generate multidimentional array
        // based off of the parts
        $nameParts = preg_split('#(?=\[.*\])#', $key);
        if (count($nameParts) > 1) {
            $current = &$return;
            $currentHeader = &$header;
            $l = count($nameParts);
            for ($i = 0; $i < $l; $i++) {
                // Strip array access tokens
                $namePart = preg_replace('#[\[\]]#', "", $nameParts[$i]);

                // If we are at the end of the depth of this entry,
                // add data to array
                if ($i == $l - 1) {
                    if (isset($thisHeader['filename'])) {
                        $filename = tempnam(sys_get_temp_dir(), "php");
                        file_put_contents($filename, $body);
                        $current[$namePart] = [
                            "name" => $thisHeader['filename'],
                            "type" => $thisHeader['Content-Type'],
                            "tmp_name" => $filename,
                            "error" => 0,
                            "size" => count($body)
                        ];
                    } else {
                        $current[$namePart] = $body;
                    }
                    $currentHeader[$namePart] = $thisHeader;
                } else {
                    // Advance into the array
                    if (!isset($current[$namePart])) {
                        $current[$namePart] = [];
                        $currentHeader[$namePart] = [];
                    }
                    $current = &$current[$namePart];
                    $currentHeader = &$currentHeader[$namePart];
                }
            }
        } else {
            if (isset($thisHeader['filename'])) {
                $filename = tempnam(sys_get_temp_dir(), "php");
                file_put_contents($filename, $body);
                $return[$key] = [
                    "name" => $thisHeader['filename'],
                    "type" => $thisHeader['Content-Type'],
                    "tmp_name" => $filename,
                    "error" => 0,
                    "size" => count($body)
                ];
            } else {
                $return[$key] = $body;
            }
            $return[$key] = $body;
            $header[$key] = $thisHeader;
        }

    }
    return $return;
}
like image 33
Isaac Avatar answered Oct 21 '22 11:10

Isaac