conn_manager: allow to remove port from host header#10960
conn_manager: allow to remove port from host header#10960mattklein123 merged 18 commits intoenvoyproxy:masterfrom
Conversation
|
i will fix failed builds/ signoff the diff. for now just waiting for everything else to complete (to make sure that there is nothing else to fix) |
|
Please add test cases for authority headers with IPv4/IPv6 addresses |
zuercher
left a comment
There was a problem hiding this comment.
Thanks. While we wait for review from the API maintainers, I provided a couple of quick comments.
There was a problem hiding this comment.
I think the name of this field should be more specific. Something like strip_host_port. Another thing to consider is how this interacts with auto host rewrite and other host-manipulation features.
There was a problem hiding this comment.
thanks. yeah. naming is hard. i will wait for other comments and will address yours in next iteration.
as for auto host - from my understanding auto host is a part of Route component of the envoy. and this port stripping modifies host header before we hit it (see "RouteShouldUseNormalizedHost" unittest)
There was a problem hiding this comment.
I will be honest that my initial gut on this one is to not strip the port, but to instead add a routing option that would ignore port during route matching. I think the latter would be the most natural way of solving #886. However, I see your point about doing stripping once and then not having to worry about upstream proxies.
I would definitely like to hear from @alyssawilk and @PiotrSikora on this one.
There was a problem hiding this comment.
Also prefer moving to a routing option.
There was a problem hiding this comment.
as Matt mentioned, matching in routing option would solve #866 (which was bonus point in this diff). but wont allow to simplify configuration for multiple layers of proxies and backends behind them (even if envoy on 2nd layer would ignore port matching, backend behind it wont; that would increas complexity of migrating from other proxies (nginx as example) to envoy).
There was a problem hiding this comment.
I thought we already removed the port when it matched the scheme, i.e. an http://foo.com:80 and https://foo.com:443 but apparently I'm misremembering? Anyway I'd prefer this as a routing option. I'm OK with a configuration guarded removal iff the port matches the listening port - if they don't match removing it feels sketchy.
There was a problem hiding this comment.
on matched the scheme. (unless it was change in last few days):
curl -k -v https://localhost/ -H 'Host:localhost'
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 7
< content-type: text/plain
< date: Tue, 28 Apr 2020 19:22:16 GMT
< server: envoy
<
curl -k -v https://localhost/ -H 'Host:localhost:443'
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< date: Tue, 28 Apr 2020 19:23:06 GMT
< server: envoy
< content-length: 0
<
part of envoy's test configuration which we are hitting in this example:
- name: local_service
domains: ["localhost"]
There was a problem hiding this comment.
as for the matching port - i'm not that familiar with this codepath. is it even possible to get listener object (and therefor it's port) from connection manager and/or route object?
There was a problem hiding this comment.
ok, so seems it is possible to get NetworkConnection from ActiveStream, and therefor local port. now the question is - do you want to make it part of the route object? (and therefor force users to match on "xxx:443" in domains (in this case this diff make little sense, and new one should be made), or you are ok w/ it being part of conn manager (but with removing port only if it is equal to the listeners port)?
There was a problem hiding this comment.
In a perfect world I think we should have both options, route matching with port stripping, as well as this option to strip port IFF the port matches the bound port (per @alyssawilk), but it's fine if you only want to do the latter in this PR.
source/common/http/path_utility.h
Outdated
There was a problem hiding this comment.
I don't think this belongs in PathUtil. There's at least one other authority-related method in header_utility.h/cc's HeaderUtility class.
alyssawilk
left a comment
There was a problem hiding this comment.
This is looking great, especially the thorough unit testing in RemovePortsFromHost :-)
There was a problem hiding this comment.
mind changing Host -> host here and below?
I know Host is pretty standard for HTTP/1.1 but Envoy lowercases anyway and I think it's more consistent with other API docs.
There was a problem hiding this comment.
For sure looking at connection it must be a valid pointer as it's returning a pointer to a reference member.
I think it'd be fine to change both of these to asserts - I think if we create an HTTPConnectionManager with non-valid address we've violated earlier invariants.
There was a problem hiding this comment.
Super nitty, but
->
Return local port of the connection.
If you could check the comments below too that'd be awesome.
There was a problem hiding this comment.
At the point we call this, we've either added a default host for HTTP/1.0 or sent a local reply and will not reach this point (HCM 850)
I don't mind you making it resilient to changes in code order, but if you're going to leave this in please make sure it's unit tested.
There was a problem hiding this comment.
optional, maybe something about the matching in the naming? strip_matching_host_port?
alyssawilk
left a comment
There was a problem hiding this comment.
Looking great - just a few more comment nits and you're good to go!
There was a problem hiding this comment.
I think there's still some Host -> host changes to track down :-)
There was a problem hiding this comment.
Port -> The port
and I'd change "connect" to CONNECT again just for consistency.
There was a problem hiding this comment.
really small nit but port -> the port ?
alyssawilk
left a comment
There was a problem hiding this comment.
@mattklein123 up for API sign off?
mattklein123
left a comment
There was a problem hiding this comment.
Nice! Few small comments from a quick skim. Thank you!
/wait
There was a problem hiding this comment.
This needs a release note. Also, do you mind ref linking fields in here where you can? For example domains.
There was a problem hiding this comment.
nit: generally we don't do asserts like this since it will crash in an obvious way on the next line. I would just remove the conn variable.
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
1. renaming remove_port to strip_host_port 2. stripping port only when it is equal to listener's local port Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
changes: 1. renaming strip_host_port to strip_matching_... 2. renaming shouldRemovePort to shouldRemoveMatchingPort 3. do not remove port if method is "connect" 4. removing some unnecessary checks Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
addressing nits/comments on spelling Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
* removed ASSERT from localPort helper * added ref into prot description * added ref to release notes * rebase Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
…p_patch Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
mattklein123
left a comment
There was a problem hiding this comment.
Awesome thank you. Just a small doc nit and let's ship!
/wait
| Can be reverted temporarily by setting runtime feature `envoy.reloadable_features.fix_upgrade_response` to false. | ||
| * http: remove legacy connection pool code and their runtime features: `envoy.reloadable_features.new_http1_connection_pool_behavior` and | ||
| `envoy.reloadable_features.new_http2_connection_pool_behavior`. | ||
| * http connection manager: added :ref:`stripping port from host header <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.strip_matching_host_port>` support. |
There was a problem hiding this comment.
s/http connection manager/http
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
|
forget to format. will do another commit |
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
|
/azp run envoy-presubmit |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run envoy-presubmit |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Sorry looks like you lost the merge race. :( Can you merge master again? /wait |
…p_patch Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Signed-off-by: Nikita V. Shirokov <tehnerd@tehnerd.com>
Commit Message:
add an api option/conn manager feature which would allow to remove port part from Host header (e.g. would transform
example:443toexample. this would simplify domain's matching inside virtual host as well as would not require explicit matching on "domain:port" in upstream proxies.Additional Description:
in production we see a lot of external requests from third party libraries, which are setting port part even for requests toward common port (443). w/o this diff on envoy side workaround was to match both on "example.com" and "example.com:443" in domains configuration. and to do this on every layer of proxies. as well as modifying application, which was running behind last level envoy, to do the same.
this diff would allow to set up remove_port option on first level envoy, and everywhere just to match on "example.com"
as a side effect it should also help to resolve #886
Risk Level:
LOW
Testing:
new unit tests + manual testing
Docs Changes:
inline in proto file