Re: RFC1867 (multipart/form-data) PUT requests
| From: | Larry Garfield | Date: | Wed, 28 Jun 2023 00:45:17 +0000 |
| Subject: | Re: RFC1867 (multipart/form-data) PUT requests | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-120705@lists.php.net to get a copy of this message | ||
On Tue, Jun 27, 2023, at 3:26 PM, Stephen Reay wrote:
>> On 28 Jun 2023, at 02:53, Ben Ramsey <ben@benramsey.com> wrote:
>>
>>> On Jun 27, 2023, at 04:01, Ilija Tovilo <tovilo.ilija@gmail.com> wrote:
>>>
>>> Hi Ben, Hi Rowan
>>>
>>> On Mon, Jun 26, 2023 at 8:55 PM Ben Ramsey <ben@benramsey.com> wrote:
>>>>
>>>>> On Jun 20, 2023, at 06:06, Rowan Tommins <rowan.collins@gmail.com> wrote:
>>>>>
>>>>> On Tue, 20 Jun 2023 at 10:25, Ilija Tovilo <tovilo.ilija@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Introduce a new function (currently named populate_post_data()) to
>>>>>> read the input stream and populate the $_POST and $_FILES
>>>>>> superglobals.
>>>>>
>>>>> How about "request_form_populate_globals"?
>>>
>>> The word "form" seems a bit out of place (even though it appears in
>>> both multipart/form-data and application/x-www-form-urlencoded),
>>> because this function is mainly targeted at PUT/PATCH requests for
>>> REST APIs. Maybe request_body_populate_globals?
>>>
>>>> Another option for the name:
>>>>
populate_multipart_form_data().
>>>
>>> I avoided the term "multipart" because the function technically also
>>> works for application/x-www-form-urlencoded requests. It's less
>>> necessary for the reasons outlined in my previous email, but it would
>>> allow for consistent handling of such requests for all HTTP methods.
>>>
>>> Some people on GitHub voiced that they would prefer an INI setting.
>>> Therefore I will create an RFC accordingly.
>>
>>
>> I know this issue comes up enough because it’s confusing to developers that there’s not
>> a $_PUT, etc., but I’m not a fan of introducing something new that
>> populates globals.
>>
>> While I’ve never used application/x-www-form-urlencoded
>> data for PUT requests (because I don’t think it’s a proper
>> content-type for the semantics of PUT), I do see how this
>> content-type could be used with PATCH, and I also don’t want to
>> rule-out use cases of it for PUT or any other HTTP method.
>>
>> In the past, I’ve used something like the following to solve this:
>>
>> parse_str(file_get_contents('php://input'), $data);
>>
>> I haven’t looked up how any of the frameworks solve this, but I would be willing to bet
>> they also do something similar.
>>
>> Rather than implementing functionality to populate globals, would you be interested in
>> introducing some new HTTP request functions. Something like:
>>
>> http_request_body(): string
>> http_parse_query(string $queryString): array
>>
>> http_request_body() would return the raw body and would be
>> the equivalent of calling
>> file_get_contents('php://input'). Of special note is that
>> it should _always_ return the raw body, even if $_POST is populated,
>> for the sake of consistency and reducing confusion.
>>
>> http_parse_query() would be the opposite of
>> http_build_query() and would return a value instead of requiring a
>> reference parameter, like parse_str().
>>
>> While these don’t address the confusion users face by not having a
>> $_PUT superglobal, I’d prefer not to overload the superglobals.
>> Maybe we can update the documentation to encourage use of these new functions instead of the
>> superglobals?
>>
>> We also might want to introduce something like http_query_string():
>> string that always returns the raw query string, instead of requiring use of the
>> superglobal $_SERVER['QUERY_STRING'].
>>
>> Cheers,
>> Ben
>
>
> As a userland/library developer I *much* prefer this approach, but
> *please* also include http_uploads() (name/signature TBD),
> returning
> an array of file uploads using a structure akin to what $_POST (or
> http_parse_query) gives, based on the field name, rather than the
> current scenario where the presence of square brackets radically
> changes the structure of the $_FILES array.
>
> My initial thought was that perhaps the leaf entities in said array
> could be a subclass of SplFileInfo referencing the uploaded temporary
> file, with additional read-only properties for the extra upload-related
> attributes - but really the important thing is just having a sane,
> consistent structure. Having an object rather than an array with
> constant keys would be a nice addition, but is much less important.
>
>
>
> Cheers
>
> Stephen
I also like Ben's suggestion. It avoids adding more magic globals, but also is still simple
and straightforward to use in an easily composable fashion. Based on the Content-Type header of the
request, it would allow for:
$formData = http_parse_query(http_request_body());
$jsonData = json_decode(http_request_body());
... Whatever other body parsers.
While you should probably not call it exactly like that, it means "take body string, pass to
mime-appropriate body parser" is an easy pattern, and one that can also be easily mocked for
testing.
--Larry Garfield