http: add HTTP/1.1 case preservation#15619
Conversation
1) Add new stateful header formatter extension point 2) Add preserve case formatter extension Fixes #14363 Signed-off-by: Matt Klein <mklein@lyft.com>
|
@asraa @alyssawilk @jmarantz @snowp PTAL. I'm pretty happy with how this turned out. It's quite clean and the perf overhead when not in use should be negligible. |
jmarantz
left a comment
There was a problem hiding this comment.
Epic! Looks great overall. A few minor comments so far.
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Outdated
Show resolved
Hide resolved
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Outdated
Show resolved
Hide resolved
Signed-off-by: Matt Klein <mklein@lyft.com>
Signed-off-by: Matt Klein <mklein@lyft.com>
Signed-off-by: Matt Klein <mklein@lyft.com>
snowp
left a comment
There was a problem hiding this comment.
This looks great, just a couple small comments
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Show resolved
Hide resolved
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Outdated
Show resolved
Hide resolved
jmarantz
left a comment
There was a problem hiding this comment.
looks great; just a few nits.
.../extensions/http/header_formatters/preserve_case/preserve_case_formatter_integration_test.cc
Show resolved
Hide resolved
jtway
left a comment
There was a problem hiding this comment.
This seems great overall. Couple minor comments.
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Show resolved
Hide resolved
.../extensions/http/header_formatters/preserve_case/preserve_case_formatter_integration_test.cc
Outdated
Show resolved
Hide resolved
.../extensions/http/header_formatters/preserve_case/preserve_case_formatter_integration_test.cc
Outdated
Show resolved
Hide resolved
source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.cc
Outdated
Show resolved
Hide resolved
alyssawilk
left a comment
There was a problem hiding this comment.
Awesome, I'm sure loads of users are going to love this one.
Two drive by comment from the "what could possibly go wrong" department.
My first thought was "What about T-E header which we add and remove?" Looks like you handle that case, but mind adding it to the integration test?
From a user experience perspective I suspect folks will probably want snow's proper casing along with your preserve casing, so if there's a header addition (say we gunzip and go from content length to transfer encoding) or header creation (send local reply with content length) we "create" the right one. Do we expect them to play well together? If so I'd suggest having the canonical config use both, update docs explaining why users who want preserve probably want create, and integration test the transformation example.
This is interesting. I didn't think about them being stacked like this. This is not how it works today. What does everyone think about this? Right now it's actually possible in the proto to configure this. I can potentially deprecate and make it repeated? That would be a pretty big change and I'm not sure it's worth it? Thoughts? |
|
We're adding this case preservation system to handle clients/servers who do case sensitive compares. |
|
OK this should be ready for another pass, thanks. |
| // non-alphanumeric character is capitalized. | ||
| ProperCase, | ||
| // A stateful formatter extension has been configured. | ||
| StatefulFormatter, |
There was a problem hiding this comment.
I think given @alyssawilk insight that we might want to generate mixed-case results for synthesized headers while preserving the case of others, maybe we want to avoid checking in the API that has these choices as exclusive?
I think from a data structure perspective we'd need to actually eliminate StatefulFormatter as a choice here and just allow users to configure both the enum and a stateful formatter (or repeated stateful formatters if we think that might be useful in the future). Does it make sense to do that now before the initial checkin?
There was a problem hiding this comment.
I'm less concerned about the code and more about the API. My understanding from the thread above is that we decided if we need this in the future we can implement a nested formatter inside the preserve case formatter for unknown headers? Because of that I think we decide we can punt for now until someone asks for it?
There was a problem hiding this comment.
Personally, I would think that any other than nested or another extension (one that may not even be in the core repo) would need to handle prioritization. For instance if you defined a stateful (preserve case), and stateless (proper case), in the current form the stateless would just end up proper casing the header keys that the stateful formatter was looking to preserve. Am I missing something @jmarantz, as it stands I'd agree 💯 with @mattklein123.
Signed-off-by: Matt Klein <mklein@lyft.com>
snowp
left a comment
There was a problem hiding this comment.
Looks good besides the one comment.
I think we might not be propagating the casing in situation where we copy the downstream headers (e.g. request shadowing), but it might not be worth trying to solve this now.
tools/code_format/check_format.py
Outdated
| "./test/common/config/registry_test.cc", "./test/integration/clusters/", | ||
| "./test/integration/filters/") | ||
| "./test/integration/filters/", | ||
| "./test/extensions/http/header_formatters/preserve_case/preserve_case_formatter_integration_test.cc" |
There was a problem hiding this comment.
The comment above suggests you should be using InjectFactory instead of of REGISTER_FACTORY, thoughts?
There was a problem hiding this comment.
This isn't possible for integration tests. This is here for the same reason test/integration/filters is here.
There was a problem hiding this comment.
Huh I thought I'd seen InjectFactory used in integration tests, but I could be wrong here
There was a problem hiding this comment.
Ah OK it looks like it can. Sure I can fix that.
Yes, it won't work in that case. I think it's not very hard to fix. We could add a clone() method to the formatter, and then clone it during header map copy. I didn't do this because I doubt anyone will notice and I didn't want to use shared_ptr. wdyt? |
I think if it's limited to request shadowing it's probably fine to leave for now, I imagine the main use case will be to format response headers, so the shadowing case is probably not important. I wasn't sure if there were other header copying cases that we needed to cover |
|
Any copying case can be fixed relatively easily by allowing formatter cloning, but like I said, I would rather wait until someone complains, because I doubt they will. It won't be hard to fix at that point. |
Signed-off-by: Matt Klein <mklein@lyft.com>
|
@snowp updated per comments |
|
is this going to be available on the latest release only or is it going to be back-ported to some older releases? |
| # HTTP header formatters | ||
| # | ||
|
|
||
| "envoy.http.stateful_header_formatters.preserve_case": "//source/extensions/http/header_formatters/preserve_case:preserve_case_formatter" |
There was a problem hiding this comment.
missing , at the end of the line.
There was a problem hiding this comment.
Will fix this in my current PR
|
@mattklein123 Is there an optimal option/improvement/suggestion for skipping this for http2 clusters when in case like istio, ingress gateway needs to allow both http1/2 traffic. We ran into istio/istio#36299 when using auto_config for case preserve leveraging envoy to auto detect http1.1/2 depending on upstream config but it didn't pick up as expected. |
This only takes effect for H1. If something else is happening I would open a new issue with repro instructions, etc. |
|
Thanks @mattklein123 : I have mentioned details of reproducing in istio/istio#36299 as it happens while using auto_config for case preserve in httpprotocol options vs explicit_http_config as mentioned in the doc. I am not sure if I should open a new issue here too or continue on the one on istio side. |
Filed new issue for the same #19149 |
1) Add new stateful header formatter extension point; 2) Add preserve case formatter extension; Fixes envoyproxy#14363 Signed-off-by: jiangshantao <jiangshantao-dbg@qq.com>
* feat: http: add HTTP/1.1 case preservation (envoyproxy#15619) 1) Add new stateful header formatter extension point; 2) Add preserve case formatter extension; Fixes envoyproxy#14363 Signed-off-by: jiangshantao <jiangshantao-dbg@qq.com> * fix: fix Error envoy_cc_library() got unexpected keyword argument: category Signed-off-by: jiangshantao <jiangshantao-dbg@qq.com> * fix: source/common/http/http1/settings.cc:39:39: error: unused parameter 'validate_scheme' Signed-off-by: jiangshantao <jiangshantao-dbg@qq.com> * feat: preserve case with proper case config Signed-off-by: jiangshantao <jiangshantao-dbg@qq.com> Co-authored-by: jiangshantao <jiangshantao-dbg@qq.com>
Fixes #14363
Risk Level: Low
Testing: New integration test
Docs Changes: Added
Release Notes: Added
Platform Specific Features: N/A