PSR-7 vs. the Server(Request|Response) RFC

tl;dr: PSR-7 aims to model HTTP messages, whereas the RFC aims to make some non-OO PHP functionality more OO-ish.


I had thought the distinction between the purpose of PSR-7, and the purpose of the server-side request/response object RFC, was obvious from their descriptions. But that is apparently not the case.

I would prefer to discuss the RFC entirely on its own merits, and not dwell on the various strengths and weaknesses of PSR-7. However, to reduce confusion on this topic, I am happy to take some time to expound on the differences.

To understand those differences more clearly, we need to start with a history of PSR-7.

Purpose of PSR-7

PSR-7 was born to answer the question, “How can we model HTTP messages in PHP for sending a request, and getting back a response?” That is, how can we standardize the model of an HTTP request message for sending, and the model of the returned the HTTP response, when using PHP as an HTTP client?

The entrance vote passed in Jan 2014 after about a year of pre-work, with Michael “Guzzle” Dowling as lead: https://groups.google.com/d/topic/php-fig/H1Lr7FYxj94/discussion. You can see the original draft at https://github.com/php-fig/fig-standards/pull/244/files.

What you’ll find in the draft is one pair of request/response interfaces, descended from a message interface, with stream as message body, and no URI specification. These were designed primarily as client interfaces; all the referenced projects in the draft were client-side. (As a side note, they were mutable. Dowling said, “Having mutable and immutable messages would add a significant amount of complexity to a HTTP message PSR and would not reflect what is currently being used by a majority of PHP projects.”)

After 8 months, Dowling stepped down in August 2014, citing a lack of time and motivation. He also said: “I don’t think there’s one way to represent HTTP messages, clients, or servers in PHP.” https://groups.google.com/forum/#!topic/php-fig/XwFcqSmqzGk

Shortly thereafter, in September 2014, with encouragement from many (including myself), MWOP of Zend Framework takes over PSR-7. We learn that he has “Sencha Connect” and middleware on the brain:

The reason I wanted to port Connect is this: an application consists of middleware. Each middleware is a callback that accepts a request, response, and a callback called “next” (which is optional, actually):

function (request, response, next)

I know from Michael Dowling that the original intent for PSR-7 was to define HTTP messages that could then be used in HTTP clients. I am here to argue that they are even more important when considering server-side applications.

At this point, we see that PSR-7 has been expanded to answer a second question: “How can we model HTTP messages for receiving a request, and sending back a response?” This is in addition to the original goal, but idea is the same: building a standard model of HTTP messages.

(For full disclosure, note that I became a sponsor on PSR-7 in December 2014, along with Beau Simensen as the coordinator.)

It is during MWOP’s tenure, before the successful acceptance vote in May 2015, that we see the PSR-7 interfaces expand in number, and become “immutable” (with one intentional exception, and other unintentional exceptions).

So we can see that the purpose of PSR-7 is to model 2 sets of HTTP messages using 7 interfaces: one set for when PHP sends a request and receives a response, and an addition set for when PHP receives a request and sends a response.

The Purpose of the Server(Request|Response) RFC

The proposed RFC starts out by asking a different question. It is not concerned with modeling HTTP messages, whether when sending or receiving them. Instead, it asks: “How can we take the request-related superglobals in PHP, and the various response-related global functions in PHP, and encapsulate them in objects, to make them at least a little more object-oriented?” Becuase the RFC begins with a different question, it leads to a different answer.

You end up with a ServerRequest object that exposes almost only properties, mimicking PHP’s superglobals. The properties are read-only, since they represent user input that should be copied out, not changed-in-place. As a convenience, a lot of common $_SERVER['HTTP_*'] values are parsed into more usable representations. Conceding the needs of application development, there are properties and methods for truly immutable values relating to application-specific parameters, parsed content input, and so on.

You also end up wih a ServerResponse object that exposes only methods, mimicking some of PHP’s global functions. Instead of emitting headers and cookies on each call to the related methods, it buffers and retains the header and cookie values until you decide to send them. As a collection point for those values, and for content, you can inspect the state of the object prior to sending, and modify it as needed. It has some convenience methods, not least of which includes sending content as a download, or as JSON, with the appropriate headers.

Conclusion

I hope this helps to clear up any confusion as to the purpose of the RFC, vs. the purpose of PSR-7. They start with different questions, and have different goals. I think it would be better to see them as orthogonal to each other at worst, and complementary at best.

Are you stuck with a legacy PHP application? You might like my book because it gives you a step-by-step guide to improving your codebase, all while keeping it running the whole time.
Share This!Share on Google+Share on FacebookTweet about this on TwitterShare on RedditShare on LinkedIn

4 thoughts on “PSR-7 vs. the Server(Request|Response) RFC

  1. I am not entirely sure I understand your argument. I guess you are saying you are aiming at a more modest improvement by simply “wrapping current functionality into an OO API”, to make it a more iterative than attempting a bigger more risky step?

    I also seem to read out of our statement that for a more risky bigger step you are not so keen on pushing PSR-7 since you are unhappy with the fact that PSR-7 is not fully immutable.

    Is this a correct summary?

    • My impression is rather than defining the interfaces and leaving it up to various PSR-7 compliant libraries to implement them, the RFC provides PHP-native objects that contain the request/response values that PHP provides by default.

      Eg. PSR-7 doesn’t define what a cookie is, it simply provides getHeader/getHeaders methods, which each implementer is responsible to implementing (with any desired associated behaviour). Thus, one library might be really basic and simply return the cookie value(s). Another may implement logic around what a Cookie is. The RFC would remove this ambiguity and simplify dealing with headers/etc that actually have structure, rather than reinventing the wheel.

      (Aside, a really good example of ambiguity is that multiple values in a header are usually separated by a comma. But some headers also use a space while others are simply duplicated.)

  2. I’d like to see the RFC get up. PSR7 aside, it seems like a glaring omission that PHP doesn’t have a clean wrapper around HTTP operations being that HTTP is it’s ‘thing’…

Leave a Reply

Your email address will not be published. Required fields are marked *