Re: RFC: Server-Side Request and Response Objects (v2)
| From: | Paul M. Jones | Date: | Tue, 11 Feb 2020 13:14:35 +0000 |
| Subject: | Re: RFC: Server-Side Request and Response Objects (v2) | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108479@lists.php.net to get a copy of this message | ||
Hi Michał,
Good to hear from you!
(While writing this, I realized I made a couple of mistakes in the RFC examples related to
CONTENT_LENGTH and CONTENT_TYPE that might have caused confusion; I have now fixed them.)
> On Feb 10, 2020, at 10:46, Michał Brzuchalski <michal.brzuchalski@gmail.com> wrote:
>
> Hi Paul,
>
> thanks for bringing it back. Got some questions:
>
> 1. In your RFC $_ENV is bound to $request.
>
> Looking at HttpFoundation can see it's build from $_GET, $_POST, $_FILES, $_COOKIE,
> $_SESSION and then looking at PSR ServerSideRequest it's build from $_COOKIE, $_GET, $_POST,
> $_FILES, $_SERVER but none of them bounds $_ENV.
>
> Server environment variables basically don't change over time when server process runs.
> What is the specific use case that requires them to be coupled with $request instance?
I have no specific use case; I recall that $_ENV showed up in more than a couple of reviewed
implementations, and so included it here. If there is no objection from John Boehr (who did the
majority of heavy lifting C), or from anyone else, then I would be fine with removing the
ENV-related element. I have no strong feelings on $_ENV representation either way.
> 2. In your RFC all headers are mapped to $request properties
>
> This behaviour is unclear and unusual to me, for eg. in summary can see that if server request
> has "Header-Name" it is found in $_SERVER["HTTP_HEADER_NAME"] and that one is
> bound to $request->headers["header-name"], ok but the next line with example for
> "Content-Type" shows that it's bound to $request->contentType - which means
> probably that it can be accessed in $request->headers["content-type"] as well,
> right? seems logic.
I'm not sure if that is a question/comment/criticism, or a statement of "OK so far, but
...". Please bear with me, so I can make sure I'm addressing your question properly.
First: Not *all* headers are mapped to $request properties; the only ones that get special $request
properties are the ones that showed up as frequently getting special treatment in other
implementations.
Next: the $header array is populated by all $_SERVER['HTTP_*'] values, plus
$_SERVER['CONTENT_TYPE'] and $_SERVER['CONTENT_LENGTH']. The latter two do not
follow the 'HTTP_*' pattern because of RFC 3875; they come in as (e.g.)
Content-Type: text/plain, so you might expect $_SERVER['HTTP_CONTENT_TYPE'],
but RFC 3875 dictates otherwise.
Finally: yes, $request->header['content-type'] is available at the same time as
$request->contentType, but they are not quite the same thing. The Content-Type header also allows
you to specify a charset, which value gets populated into $request->contentCharset. So, you can
read these values these ways:
- $request->header['content-type'] => 'text/plain; charset=UTF-8' (the
original header)
- $request->contentType => 'text/plain' (parsed out by ServerRequest)
- $request->contentCharset => 'UTF-8' (parsed out by ServerRequest)
Likewise, PHP puts `Content-Length: 123' into $_SERVER['CONTENT_LENGTH'];
ServerRequest additionally puts it into $request->headers['content-length'] as a
string; and then further tries to represent the value as an integer in $request->contentLength.
So:
- $request->server['CONTENT_LENGTH'] => (string) '123'
- $request->headers['content-length'] => (string) '123'
- $request->contentLength => (int) 123
My apologies if all of that was stuff you already knew and understood. (And if you did not already
know it, maybe that means I should write up a narrative of the logic being applied.)
> Going further, for eg. $_SERVER["PHP_AUTH_PW"] is bound to $request->authPw and
> then what will happen if the request will receive "Auth-Pw" header?
In that example, PHP would populate two $_SERVER elements: 'PHP_AUTH_PW' from the
password, and 'HTTP_AUTH_PW' from the header. ServerRequest only populates PHP_AUTH_PW
into $authPw; the HTTP_AUTH_PW value would (per the above description) go into
$request->headers['auth-pw'].
I hope that made sense; let me know if it did not.
> With those above I would see a set of getters like getContentType() or getAuthPassword() etc.
> instead of ServerRequest instance properties and a single point to retrieve header values just like
> well known ParameterBag's from HttpFoundation to operate on get, post, headers etc.
Does the above explanation help to modify your preferences here? If not, we can continue talking
about it.
--
Paul M. Jones
pmjones@pmjones.io
http://paul-m-jones.com
Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp
Solving the N+1 Problem in PHP
https://leanpub.com/sn1php