Re: [PHP-DEV] RFC: Server-Side Request and Response Objects (v2)

This is only part of a thread. view whole thread
  108628
February 17, 2020 00:45 mike@newclarity.net (Mike Schinkel)
> On Feb 16, 2020, at 6:34 PM, Rowan Tommins collins@gmail.com> wrote: > > On 13/02/2020 20:31, Mike Schinkel wrote: >> If I had a vote I would vote I would enthusiastically vote for the RFC if it includes filter_input() functionality. But I would vote against this RFC if it omits filter_input() functionality because it would mean another subsystem in core that does not actually address day-to-day concerns. > > I think you are over-estimating how central the filter API is to most people's workflow with requests. I think that's partly because designing a good validation API is hard, but also because filter_input in particular is a combination of three different concerns:
I think your latter points are orthogonal to this. And that you are taking my advocacy for adding filtering to apply too literally to only the specific implementations in filter_input(). I can see addressing your comments below *and* having a filtering method built into these objects. Possibly even with applicable method names as opposed to a 2nd type parameter, like: $request->getInt('db_id'); $request->getJson('package'); $request->getUrl('return_url');
> 1) Fetching the raw information about the incoming HTTP request from the web server (the "SAPI") > 2) Parsing that raw information into individual fields > 3) Validating those fields against expected type constraints > > The superglobals already combine concerns 1 and 2, and the filter API adds concern 3; but to do so they all assume that the user is basically writing a CGI wrapper for some HTML forms. > > The modern reality is rather different, and step 2 in particular is much more variable: > > - Rather than query string parameters, it might involve extracting parameters from an SEO URL like "/products/123-acme-thingummy" or a RESTish URL like "/products/123/description/en-GB" > - Rather than submitted form data, it might involve parsing JSON from an AJAX request or API call > > > I would love to see new APIs that take a step back from the legacy, and tackle each of these concerns separately, based on modern requirements. > > For concern 1, getting data out of the web server, I'd love to see: > > - A more intuitive way to get the raw request body than file_get_contents('php://input') > - A more reliable way to get the URL the user requested than checking 5 different variables in $_SERVER to handle different deployment methods (see e.g. [1] and [2] for the lengths libraries go to for this) > - A proper distinction between HTTP headers, server status variables, and environment variables, because CGI name-mangling is legacy cruft that users shouldn't need to learn > > For concern 2, parsing that data, I'd love to see: > > - A better API than parse_str for parsing arbitrary strings in application/x-www-form-urlencoded format > - A way to parse data in multipart/form-data format decoupled from the current HTTP request > - Tools for working with Content-Type strings, such as a function for correctly parsing things like "text/html;charset=UTF-8", and constants for common MIME types > > Concern 3, filtering / sanitising / validating, I think is a really hard problem space, and I don't think there will ever be one implementation that suits all cases. > > A similar "shopping list" could probably be made for responses, but if we decoupled the pieces, we wouldn't have to perfect them all at once; instead, we could provide building blocks that make userland implementations easier.
Decoupling is a valid approach. But given how much work it is get to an RFC over the line, it feels like decoupling would end up with a lot more work, lengthen the timeline to achieve base level functionality, and add uncertainty to whether it will even happen whereas handling the 20% now that we need 80% of the time would mean the API would be mostly fully usable out of the gate. -Mike
  108635
February 17, 2020 07:51 rowan.collins@gmail.com (Rowan Tommins)
On 17 February 2020 00:45:26 GMT+00:00, Mike Schinkel <mike@newclarity.net> wrote:
>I think your latter points are orthogonal to this. And that you are >taking my advocacy for adding filtering to apply too literally to only >the specific implementations in filter_input().
Firstly, I deliberately didn't say "the filter API isn't well designed", I said "designing a good validation API is hard". In particular, finding the balance between flexibility and simplicity is key. Including a single blessed validation API in something as fundamental as a request object should take a lot of careful design, not be an afterthought to something like the current RFC. I also talked specifically about moving away from the old assumptions of CGI. What does it mean to "filter" a JSON body? We could check it's valid JSON, but parsing it will reveal that anyway. We could automatically parse it in the request object, and have "filters" apply to individual elements; but where would the user supply parser options, and how would you specify nested elements? Or we could keep it as a dumb string, and leave the validation to other systems, like a JSON Schema validator. Even with a plain HTML form, you might be using a form builder and want to associate your validation with the form definition rather than having it baked into the request object.
>But given how much work it is get to an RFC over the line, it feels >like decoupling would end up with a lot more work, lengthen the >timeline to achieve base level functionality, and add uncertainty to >whether it will even happen whereas handling the 20% now that we need >80% of the time would mean the API would be mostly fully usable out of >the gate.
Funny, I see the exact opposite: trying to build a single set of classes which include a system for getting global state AND a system for parsing it in different ways AND an in-built validation API seems like a mammoth task. And if you keep it monolithic, any feature you miss or make a mistake on is much harder to fix later. Regards, -- Rowan Tommins [IMSoP]