HttpProxyHandler generates invalid CONNECT url and Host header when address is resolved#7784
Conversation
|
@slandelle this produced multiple test errors... please check |
|
Yes, I'll have a look. But I think those tests are broken. |
|
@slandelle then fix the broken tests ;) |
There was a problem hiding this comment.
@slandelle should we make this a utility method in the http package ? Like in HttpUtils ? I think this is something that is useful in general.
There was a problem hiding this comment.
Can do, sure. But does it make sense to introduce this now while work on Netty 5 targeting Java 8 is about to start?
There was a problem hiding this comment.
@slandelle I think it still does as netty 5 is most likely still be 1 year away
There was a problem hiding this comment.
This utility would be better suited for NetUtil than HttpUtil, don't you think?
There was a problem hiding this comment.
Not sure... isnt it kind of related how you format stuff for the http header ?
There was a problem hiding this comment.
Ah, ok, I thought you were only talking about the first line above your comment, not the whole block. Will do.
|
@normanmaurer @trustin Note that tests passes, but I didn't fix the logic in ProxyHandlerTest that looks broken to me. That would be a separate issue. |
|
@slandelle sounds good... if you have time we love PRs as you know ;) |
|
@slandelle @normanmaurer I have a question regarding
RFC 7230 and older RFC2616 on
Which might be applied to 80 and 443 if we still honor 2616, but not exclusively to 443. |
|
@kachayev From my experience with AHC), there are some servers that really expect with port. And that's how browsers compute Host headers too. |
There was a problem hiding this comment.
Why did you make this change?
|
@slandelle With the latest changes |
|
@kachayev You wouldn't use this handler for http-only proxy, the mechanism is different and doesn't use a CONNECT request (directly connect to proxy and send absolute url instead of relative). I have to check for WebSockets then. |
|
@slandelle "wouldn't use" doesn't mean it's not allowed. RFC7231 I mentioned above does not specify tunnel to be used only with a secure connection. CURL, for example, does not establish tunnel when connecting to HTTP proxy by default but you still can force this: $ curl -vvv -o /dev/null -x http://localhost:8888 --proxytunnel http://www.google.com
* Rebuilt URL to: http://www.google.com/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
* Establish HTTP proxy tunnel to www.google.com:80
> CONNECT www.google.com:80 HTTP/1.1
> Host: www.google.com:80
> User-Agent: curl/7.54.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* Proxy replied OK to CONNECT request
> GET / HTTP/1.1
> Host: www.google.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK |
|
@kachayev Which proxy do you use? Then, what do you suggest? Ignore 80 and 443? It's not possible to guess the actual scheme and current API doesn't let you specify. |
|
@slandelle Charles for Mac, but that's irrelevant because a lot of proxies do support CONNECT over plain HTTP. My suggestion is not to ignore even default ports (neither 443 nor 80) as it might break functionality in some cases (at least we cannot guarantee that it would not). |
From my experience, it's the other way around: things broke when the default port was there. And that's what AHC and browser does. I'm fine with not ignoring by default, but I'll introduce an option to override. |
|
@normanmaurer PTAL again |
There was a problem hiding this comment.
@slandelle you need to revert all the removals of throws... as its a breaking change. People who may have override the method and have throws on it will be in trouble.
|
@normanmaurer fixed |
|
cc: @zpencer |
|
@carl-mastrangelo @ejona86 @trustin any of you can verify this one ? |
|
I can take a look |
|
FWIW, the getHostString changes all look good. It's the |
There was a problem hiding this comment.
Let's add a test for this case.
There was a problem hiding this comment.
I'm not convinced it would make sense to test this single line of code.
Then, url and Host header computations are entangled so I can save allocations.
I can't test HttpProxyHandler#newInitialMessage because I would need to override destinationAddress() which is final.
I'm going to extract CONNECT request creation in a static method.
There was a problem hiding this comment.
Actually, it should be fine. Stay tuned.
|
@normanmaurer @zpencer Host header tests added, PTAL again. |
|
@trustin any concerns ? |
|
Sorry! Will take a look tomorrow.
2018년 3월 22일 (목) 오후 10:40, Norman Maurer <notifications@github.com>님이 작성:
… @trustin <https://github.com/trustin> any concerns ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7784 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAKnXhyQ5NRLXdsIT21nlNMK5kckjDa5ks5tg6nlgaJpZM4SsUfR>
.
|
normanmaurer
left a comment
There was a problem hiding this comment.
A few nits... otherwise LGTM
There was a problem hiding this comment.
nit: you can remove the else as you return anyway.
|
@normanmaurer done |
There was a problem hiding this comment.
I guess a user of this method may think the return value will contain the port number. How about adding a boolean parameter withPort, so that this method adds :<port> when it's true?
There was a problem hiding this comment.
What about trying to find a better name instead? Maybe formatHostnameForHttp?
I'm not fond of expanding an API beyond what's being used internally so it can serve for whatever other purpose we're not aware of.
WDYT?
…ddress is resolved Motivation: HttpProxyHandler uses `NetUtil#toSocketAddressString` to compute CONNECT url and Host header. The url is correct when the address is unresolved, as `NetUtil#toSocketAddressString` will then use `getHoststring`/`getHostname`. If the address is already resolved, the url will be based on the IP instead of the hostname. There’s an additional minor issue with the Host header: default port 443 should be omitted. Modifications: * Introduce NetUtil#getHostname * Introduce HttpUtil#formatHostnameForHttp to format an InetSocketAddress to HTTP format * Change url computation to favor hostname instead of IP * Introduce HttpProxyHandler ignoreDefaultPortsInConnectHostHeader parameter to ignore 80 and 443 ports in Host header Result: HttpProxyHandler performs properly when connecting to a resolved address
|
@slandelle thanks! |
|
@normanmaurer Thanks for merging |
Motivation:
HttpProxyHandler uses
NetUtil#toSocketAddressStringto computeCONNECT url and Host header.
The url is correct when the address is unresolved, as
NetUtil#toSocketAddressStringwill then usegetHoststring/getHostname. If the address is already resolved, theurl will be based on the IP instead of the hostname.
There’s an additional minor issue with the Host header: default port
443 should be omitted.
Modifications:
use
getHostnameotherwiseResult:
HttpProxyHandler performs properly when connecting to a resolved address