On Thu, Feb 26, 2015 at 4:38 PM, Evert Pot <
ever...@gmail.com> wrote:
> Michael Dowling raised an issue about the Host header yesterday, and we
> decided that this should be addressed in PSR-7.
>
> His main point was, if the user changes the URI with withUri, does this
> affect the result of:
>
> $request->getHeader('Host')
>
> and if so, how?
>
> Just like the "request target" the Host header and the result of
> ->getUri()->getHost() are two fundamentally different things.
>
> The former describes:
>
> 1. Part of the URI we are retrieving
> 2. The contents of the Host header
>
> While the latter describes the actual host we are connecting to to
> request the resource.
>
> It gets even a bit more complicated, because the request target may also
> have a host, which give us three distinct places to put a host.
Much as I love the HTTP specification for its simplicity, this is yet
another one of those areas where it introduces some really, really
awful ambiguity. :)
> We've found that the request object in Go actually handles this in a
> different way.
>
>
https://golang.org/src/net/http/request.go
>
> In Go, their request object has an equivalent 'req.Host'. They actually
> provide separate accessors to everything in the "Request Target".
>
> Their req.Host therefore refers both to request targets in the 'absolute
> form', as well as the contents of the "Host:" header. Only one of these
> should ever appear in HTTP after all.
SHOULD, but the spec allows for it. :)
> (note that GO also has a separate req.URL.getHost() just like we do).
>
> I actually think that the GO approach models the HTTP request even more
> perfectly than we do, but taking their approach would mean a larger
> departure of the existing api... which is perhaps a bad idea at this
> stage in the game.
>
> So, lacking a larger change, the workaround that we both felt was 'good
> enough' was to treat the Host header identical to the RequestTarget.
>
> So that means that the Host header should be special cased, specifically:
>
> * If we don't have a Host header and getHeader('Host') is called, it
> will return the value of getUri()->getHost()
> * If the user explicitly sets the 'Host' header, that will always take
> precendence.
I like this approach; it's consistent with how the RequestTarget is
modeled in the interfaces (which you also note separately below).
> * Other methods that returns headers also need to behave this way for
> the host.
I'm not sure what you mean here...
> This addresses the two main use-cases:
>
> 1. Most users will just want to set setUri() and you don't want to ask
> them to explicitly also have to set the Host header every time.
> 2. Some users may care about the distinction between the Host header
> and setUri().
>
> It also makes the behavior identical to getRequestTarget() that can be
> overridden, but normally uses the information from getUri().
>
> But there is one thing that this solution does not address. A user may
> want to make a HTTP/1.0 request without a Host header at all. I think
> this is an edge-case that we don't have to care about, but should be
> documented.
I think that could be an implementation detail of an HTTP client, TBH.
Also, since HTTP/1.0 DOES allow sending the Host header, I think it's
definitely a very, very slim edge case, and it would have to be
something the consumer of the client opts into specifically (and the
client would essentially need to check to see if the URI host and the
Host header match before deciding to omit it).
> # Is this a radical change?
>
> I don't think this is. This proposal keeps the interface the same, but
> just changes some docblocks. This change makes something extremely
> explicit what would otherwise likely have been implementation-specific,
> causing potential interoperability problems.
The language here would be SHOULD, as in optional but recommended
behavior. For instance, a server-side specific implementation of PSR-7
might not need to implement this behavior.
This is the PR I've created according to your post:
-
https://github.com/php-fig/fig-standards/pull/446
and the related commit for http-message:
-
https://github.com/php-fig/http-message/pull/26
As you'll see, the change posed a bit of a problem: where to document
the behavior. Since headers are defined in MessageInterface, but the
Host header and changes suggested are specific to the
RequestInterface, the only viable approach was to have
RequestInterface override the getHeader() method. Literally, the only
change was overriding the docblock to add the verbiage and some @see
annotations.
Let me know if this makes sense, and/or if you have any suggested
changes. This should be merged before we enter voting phase, but I
don't think it warrants a new or extended Review phase.
--
Matthew Weier O'Phinney
mweiero...@gmail.com
https://mwop.net/