Server-Side Request/Response Objects

php.internals

Paul M Jones

9 years ago
Hi all, tl;dr: Gauging interest in an extension for server-side PHP request and response objects (*not* HTTP messages per se; see below) prior to writing an RFC for them on the wiki. * * * From time to time we've all heard the complaint that PHP has no built-in request object to represent the execution environment. Userland ends up writing these themselves, and those are usually tied to a specific library collection or framework. The same is true for a response object, to handle the output going back to the web client. I've written them myself more than once, as have others here. After doing some library and framework research (linked later) it looks like there is a reasonably common subset of request/response functionality across all the userland implementations. That functionality also appears useful to non-framework users. I wrote up a userland implementation for that limited subset of functionality, and John Boehr then used that as a reference point for the C version. It is PHP 7.x only, and you can see the result at: <https://gitlab.com/pmjones/phprequest> (The userland reference implementation is at <https://gitlab.com/pmjones/phprequest/tree/master/refimpl>, and the research subjects are in <https://gitlab.com/pmjones/phprequest/tree/master/refimpl/notes>.) The extension provides server-side request and response objects for PHP. They are *not* HTTP message objects proper. They are more like wrappers for existing global PHP variables and functions, with some limited additional convenience functionality. There are only two classes: - StdRequest, essentially a read-only struct composed of PHP superglobals and some other commonly-used values - StdResponse, essentially a wrapper around (and buffer for) response-related PHP functions, with some additional convenience methods, and self-sending capability I thought this might best be offered as a PECL extension first, leading (I would hope) to becoming a part of the PHP distribution later if it proves out. However, PECL has not responded in the past few days (perhaps I have not waited long enough). In the mean time, I am bringing it up here to either (1) get PECL's attention, or (2) begin the RFC process if there's enough interest per <https://wiki.php.net/rfc/howto>. I'm happy to answer any questions, and undergo any criticism, that you may have regarding this. Thanks for your time and attention.
-- Paul M. Jones http://paul-m-jones.com

Korvin Szanto

9 years ago
Hi Paul, Thank you for spending the time to actually put this together! I've been dipping my toes in the water asking around about this (sort of) as well and feedback so far has been "That sounds great but I don't think there is enough interest." So I'm very interested to see what kind of response this gets here. Personally I would prefer complete HTTP message objects similar to existing PSR-7 implementations be added perhaps alongside these simple classes you've proposed. Thanks, Korvin On Mon, Sep 26, 2016 at 12:38 PM Paul Jones <pmjones88@gmail.com> wrote:

Paul M Jones

9 years ago
Hi all, First, I want to reiterate that my initial desire was to submit this to PECL, to give the project some exercise before bringing it to internals. If someone here can nudge the PECL folks about my account request, that'd be appreciated. Otherwise, I'm happy to continue the discussion here. Now, on to the questions and criticisms. * * *
> On Sep 26, 2016, at 16:10, Korvin Szanto <korvinszanto@gmail.com> wrote: > > Personally I would prefer complete HTTP message objects similar to existing PSR-7 implementations be added perhaps alongside these simple classes you've proposed.
Mike Wallner notes his pecl_http work, which I think is good for complete HTTP messages. * * *
> On Sep 26, 2016, at 16:32, Rowan Collins <rowan.collins@gmail.com> wrote: > > This sounds like an interesting project, but I have a few questions. > > First, the obvious one: why does this need to be an extension and/or built into core? Are there reasons such as performance for implementing this in C rather than PHP? Does it provide functionality that is hard to implement in a userland library?
The part that's hard to do in userland is public read-only properties that cannot be subverted by child classes. As to building it into core, I think it'd probably be better in PECL first, but my application there has been ignored so far (though maybe I've not waited long enough).
> You mention that it is not just an HTTP wrapper, but although you mention researching other frameworks, I can't see any reference to PSR-7 [http://www.php-fig.org/psr/psr-7/]. What do you see as the relationship between your proposal and that standardisation effort?
I did use it as a research subject, but I failed to include it in my notes; I will add it. I was a sponsor on PSR-7, and I've worked with implementations since before the PSR was finalized. I put together the Relay middleware dispatcher, and some middleware pieces, and some applications, all using PSR-7, so I'm relatively familiar with its ins and outs. However, I have come to think of it as "not having lived up to its promise." That's not to denigrate MWOP, its lead author, whom I encouraged throughout the PSR process. But the PSR-7 claim of "immutability" turns out to be only partly true; instead, it is quasi-immutable, and so it has the problems that come with both mutability and immutability. There are some other problems, which if you press me on I'll go into, but not eagerly and only with trepidation. This work steps back a little bit, to survey the actual implementations of server-side requests and responses in userland, and bring together their similarities (with a very little bit of refinement), instead of building an entirely new and not-thoroughly-examined way of doing things.
> Regarding the design of the objects themselves, why is stdRequest property-only, but stdResponse method-only? The asymmetry feels awkward to me.
Yeah, I get that. They use PHP itself as the example, where the superglobals carry all the request-related information, and global functions handle all the response-related activity. Part of the idea is to make using StdRequest and StdResponse "feel" a bit more like using the superglobals and global functions, while still corralling the related information into its own space inside an object. * * *
> > On Sep 26, 2016, at 16:45, Michael Wallner <mike@php.net> wrote: > > Did you include pecl/http in your research?
I did, but I failed to note it. I will do so.
> It looks like it covers most of that already, if not all. > I know you said *not* HTTP messages per se, but I don’t see a lot of a difference.
One difference regarding StdRequest is that everything is exposed as read-only public properties. All of the frameworks/libraries I looked at had equivalents of this: $value = $request->getPost($key, $default_value); That's to provide a default value if a particular $_POST key is not available. However, under PHP 7, the ?? operator makes that kind of method unnecessary: $value = $request->post[$key] ?? $default_value; Further, StdRequest includes things that are not part of HTTP messages (e.g. all $_ENV values, and some $_SERVER values). The main difference regarding StdResponse is that instead of attempting to mimic an HTTP Message model, it mimics PHP functionality, except buffering the calls instead of sending them right away. (There are some added convenience methods as well, drawn from the research subjects.) * * *
> On Sep 26, 2016, at 16:52, Davey Shafik <davey@php.net> wrote: > > Additionally to this, we need to start thinking about what it means to move > away from simple request/response architectures. In the age of WebSockets > and HTTP/2 multiplexing w/Server Push, the likelihood of multiple responses > for one request, or even responses with no associated request, are possible.
I've spoken with Davey, and the summary seems to be that server-push is possible, though in an impoverished way, via Link headers. Those can be added with header(), which means they can be added with StdResponse::setHeader(). As far as the rest, they are the subject of future work from Davey, which I look forward to, and will be happy to incorporate as it becomes available. (Davey, please correct me if I got that wrong.)
> I'd rather look at this as the target for this kind of exploration and > implementation.
To be clear, the StdRequest/StdResponse classes are not intended as exploration; they are "summaries" of existing work in the field.
-- Paul M. Jones http://paul-m-jones.com

Rowan Collins

9 years ago
On 26/09/2016 20:37, Paul Jones wrote:
> tl;dr: Gauging interest in an extension for server-side PHP request and response objects (*not* HTTP messages per se; see below) prior to writing an RFC for them on the wiki.
This sounds like an interesting project, but I have a few questions. First, the obvious one: why does this need to be an extension and/or built into core? Are there reasons such as performance for implementing this in C rather than PHP? Does it provide functionality that is hard to implement in a userland library? You mention that it is not just an HTTP wrapper, but although you mention researching other frameworks, I can't see any reference to PSR-7 [http://www.php-fig.org/psr/psr-7/]. What do you see as the relationship between your proposal and that standardisation effort? Regarding the design of the objects themselves, why is stdRequest property-only, but stdResponse method-only? The asymmetry feels awkward to me. I think the most interesting parts are those that attempt to rationalise $_SERVER, and I think a library (or built-in functionality) devoted to those could be very useful. Some of that overlaps with PSR-7, but that standard doesn't go into depth on things like Accept headers, Authentication, etc. Like I say, it's an interesting idea, but I'm not sure how it fits in with the wider ecosystem. Regards,
-- Rowan Collins [IMSoP]

Davey

9 years ago
On Mon, Sep 26, 2016 at 2:32 PM, Rowan Collins <rowan.collins@gmail.com> wrote:
> On 26/09/2016 20:37, Paul Jones wrote: > >> tl;dr: Gauging interest in an extension for server-side PHP request and >> response objects (*not* HTTP messages per se; see below) prior to writing >> an RFC for them on the wiki. >> > > This sounds like an interesting project, but I have a few questions. > > First, the obvious one: why does this need to be an extension and/or built > into core? Are there reasons such as performance for implementing this in C > rather than PHP? Does it provide functionality that is hard to implement in > a userland library? > > You mention that it is not just an HTTP wrapper, but although you mention > researching other frameworks, I can't see any reference to PSR-7 [ > http://www.php-fig.org/psr/psr-7/]. What do you see as the relationship > between your proposal and that standardisation effort? > > Regarding the design of the objects themselves, why is stdRequest > property-only, but stdResponse method-only? The asymmetry feels awkward to > me. > > I think the most interesting parts are those that attempt to rationalise > $_SERVER, and I think a library (or built-in functionality) devoted to > those could be very useful. Some of that overlaps with PSR-7, but that > standard doesn't go into depth on things like Accept headers, > Authentication, etc. > > Like I say, it's an interesting idea, but I'm not sure how it fits in with > the wider ecosystem.
Additionally to this, we need to start thinking about what it means to move away from simple request/response architectures. In the age of WebSockets and HTTP/2 multiplexing w/Server Push, the likelihood of multiple responses for one request, or even responses with no associated request, are possible. I'd rather look at this as the target for this kind of exploration and implementation. - Davey

Larry Garfield

9 years ago
On 09/26/2016 10:52 PM, Davey Shafik wrote:
> On Mon, Sep 26, 2016 at 2:32 PM, Rowan Collins <rowan.collins@gmail.com> > wrote: > >> On 26/09/2016 20:37, Paul Jones wrote: >> >>> tl;dr: Gauging interest in an extension for server-side PHP request and >>> response objects (*not* HTTP messages per se; see below) prior to writing >>> an RFC for them on the wiki. >>> >> This sounds like an interesting project, but I have a few questions. >> >> First, the obvious one: why does this need to be an extension and/or built >> into core? Are there reasons such as performance for implementing this in C >> rather than PHP? Does it provide functionality that is hard to implement in >> a userland library? >> >> You mention that it is not just an HTTP wrapper, but although you mention >> researching other frameworks, I can't see any reference to PSR-7 [ >> http://www.php-fig.org/psr/psr-7/]. What do you see as the relationship >> between your proposal and that standardisation effort? >> >> Regarding the design of the objects themselves, why is stdRequest >> property-only, but stdResponse method-only? The asymmetry feels awkward to >> me. >> >> I think the most interesting parts are those that attempt to rationalise >> $_SERVER, and I think a library (or built-in functionality) devoted to >> those could be very useful. Some of that overlaps with PSR-7, but that >> standard doesn't go into depth on things like Accept headers, >> Authentication, etc. >> >> Like I say, it's an interesting idea, but I'm not sure how it fits in with >> the wider ecosystem. > > Additionally to this, we need to start thinking about what it means to move > away from simple request/response architectures. In the age of WebSockets > and HTTP/2 multiplexing w/Server Push, the likelihood of multiple responses > for one request, or even responses with no associated request, are possible. > > I'd rather look at this as the target for this kind of exploration and > implementation. > > - Davey
A point others have made in the past, and I have been convinced of, is that userspace is perfectly fine for this sort of work. It doesn't need to be native for any reason other than standardization, which PSR-7 already has covered. What *would* be helpful is to expose the "parse stream to struct" logic that PHP uses to build the superglobals to user space. Basically, make it possible to replace Request::createFromSuperGlobals() with Request::createFromStream('php://stdin') (or something along those lines), for performance as that's the only expensive part of the process. Parsing whatever that provides into a PSR7 object, an HttpFoundation object, or something else is then safe to do in userspace and evolve in user-space as needed. It would also make it possible to parse an arbitrary stream (or maybe string?), not just php://stdin, which would help with long-running processes, HTTP2, etc. etc. Perhaps there could even be an ini option (*ducks*) to disable the superglobals entirely and save that processing time. I agree that Yet Another Request Struct(tm) offers little value at this point. --Larry Garfield

Michael Wallner

9 years ago
On 26 09 2016, at 21:37, Paul Jones <pmjones88@gmail.com> wrote:
> > Hi all, > > tl;dr: Gauging interest in an extension for server-side PHP request and response objects (*not* HTTP messages per se; see below) prior to writing an RFC for them on the wiki. >
Did you include pecl/http in your research? It looks like it covers most of that already, if not all. I know you said *not* HTTP messages per se, but I don’t see a lot of a difference. Regards, Mike