Clarify client-side behaviour regarding URIs and Host headers
Opened this issue · 3 comments
Issue by 2beaucoup
Tuesday Jul 21, 2015 at 13:12 GMT
Originally opened as akka/akka#18048
While thinking about #18044 I looked at how we handle things regarding URIs/Host headers on the client side.
IMO this is how things should behave here:
outgoingConnection
/ hostConnectionPool
URI | Host | effective URI | effective Host |
---|---|---|---|
abs | ✕ | uri | uri.host |
rel | ✕ | uri | con.host |
rel | ✓ | uri | host |
abs | ✓ | uri | host |
hostConnectionPool
(proxied)
URI | Host | effective URI | effective Host | Condition |
---|---|---|---|---|
abs | ✕ | uri | proxy.host | |
rel | ✕ | uri.copy(auth = host) | proxy.host | |
rel | ✓ | uri.copy(auth = host) | proxy.host | |
abs | ✓ | uri | proxy.host | host == uri.host |
superPool
/ singleRequest
URI | Host | effective URI | effective Host | Condition |
---|---|---|---|---|
abs | ✕ | uri | uri.host | |
rel | ✕ | always fail | ||
rel | ✓ | uri | host | |
abs | ✓ | uri | host |
superPool
/ singleRequest
(proxied)
URI | Host | effective URI | effective Host | Condition |
---|---|---|---|---|
abs | ✕ | uri | proxy.host | |
rel | ✕ | always fail | ||
rel | ✓ | uri.copy(auth = host) | proxy.host | |
abs | ✓ | uri | proxy.host | host == uri.auth |
Requests with a protocol of HTTP/1.0
should be required to not have a Host
header and therefore only the first two lines of each table and the "effective URI" column apply.
A recommendation for API users could be to never set a Host
header explicitly and use absolute URIs for superPool
/ singleRequest
and relative URIs in outgoingConnection
/ hostConnectionPool
for simple requests. Akka would then add the Host
header where required.
Implementation wise we could remove RequestRenderingContext
and wrap the client APIs with the logic from above. Or the impl currently behaves exactly like described above? Then we have at least this nice summary. ;)
(The proxy cases are just included for completeness as this is currently unimplemented functionality.)
WDYT?
Comment by sirthias
Wednesday Jul 22, 2015 at 21:02 GMT
Thanks, @2Beaucoup, this is indeed a great description which makes it easy to discuss and implement things properly!
I think I agree with all your table cells. (Maybe things in the "proxied" department are a bit more tricky but, from my current POV, I think you are spot on!)
Comment by 2beaucoup
Friday Jul 24, 2015 at 13:07 GMT
My proposal for simplification would be to:
- treat
Host
as an internal header and warn if it's set - expect absolute URIs for
superPool
/singleRequest
,fail if relative and noHost
header - expect relative URIs for
outgoingConnection
/hostConnectionPool
, warn if absolute, fail ifuri.auth != con.host
- submit relative URI if
con.host == uri.auth
- add
Host
header internally if `protocol != HTTP/1.0``
Comment by schmitch
Saturday Aug 06, 2016 at 09:57 GMT
actually what about "virtual hosts" one could set a Host header and send a request to a total different domain.
Something like:
curl -H 'Host: demo.com' www.google.com
So the Host header should definitly not be internal nor give a warning.
Currently I'm working on play-ws and try to get a akka-http backend and actually I use it basically like that:
Http().singleRequest(HttpRequest(uri = "http://localhost:8000", headers = Seq(Host("demo.de")))
And get a request like that:
GET / HTTP/1.1
Host: demo.de
User-Agent: akka-http/2.4.9-RC1
which is basically all I want.