Relaxed Vary header defaults#674
Conversation
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
|
This is worse than the current state of things IMO. Has the current default caused some specific issue for you? |
|
++ to @jplatte 's feedback that this will break a lot of users since we are shifting from "conservative" defaults (include Would it work to instead have Or are there other overly conservative cases you are concerned with @seun-ja ? |
|
So, what I was thinking of when writing the referenced comment was having the various methods like |
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
jlizen
left a comment
There was a problem hiding this comment.
The approach of eagerly stripping the vary headers based on permissive() creates a problem:
CorsLayer::permissive().allow_origin(AllowOrigin::predicate(...))
This would produce no vary: origin header, when in fact we might have dynamic CORS that has multiple allowed origins. That could result in a stale cache improperly rejecting origins that DO match the predicate.
The proper way to handle this would be, like jplatte@ suggested, doing the stripping on the explicit allow_* methods.
And then, we also would need an extra Is_custom_vary parameter in the builder (or something), to make sure that we don't overwrite the user's explicit configuration.
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
| } else { | ||
| // Ensure header is present | ||
| let mut vary = self.vary.clone(); | ||
| let name = header::ACCESS_CONTROL_REQUEST_HEADERS; | ||
| if !vary.to_header().map_or(false, |(_, v)| { | ||
| v.to_str() | ||
| .unwrap_or("") | ||
| .split(',') | ||
| .any(|s| s.trim().eq_ignore_ascii_case(name.as_str())) | ||
| }) { | ||
| vary = Vary::list([name]); | ||
| } | ||
| self.vary = vary; | ||
| } |
There was a problem hiding this comment.
Instead of this complicated logic to add back the vary header if it has been removed from the default list, I think we could just do the checks to omit some vary headers in the Layer impl for CorsLayer (and additionally the Service impl of Cors, since that one also has the builder-style methods, though they are probably much less frequently used). What do you think?
There was a problem hiding this comment.
Yeah this makes more sense.
It's a lot cleaner and maintainable
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
jlizen
left a comment
There was a problem hiding this comment.
Coming together! Down to just small tweaks.
| let mut layer = self.clone(); | ||
|
|
||
| // Only set Vary if not custom | ||
| if !layer.is_vary_custom { |
There was a problem hiding this comment.
Can we extract this logic into a shared helper that can be used across both Layer::layer() and Cors::map_layer()
| // Only set Vary if not custom | ||
| if !layer.is_vary_custom { | ||
| // If all origins, methods, and headers are allowed, omit Vary | ||
| let all_origins = layer.allow_origin.is_wildcard(); |
There was a problem hiding this comment.
This logic looks fine in that it won't ever remove Vary headers from potentially dynamic CORS configurations.
But, it could be broadened to also include eg: AllowOrigin::exact("http://example.com").
Also the list method for headers/methods are constant (return all values), only the origin will vary what is returned per request.
The current approach is fine as a first step, optionally you could leave a TODO to sweep up the rest, or just add the others in now.
| ]; | ||
|
|
||
| #[tokio::test] | ||
| #[allow( |
There was a problem hiding this comment.
I don't think we need these clippy annotations on this test. Can we flip them over to expect() for all usages in this file to avoid future buildup?
| @@ -1,37 +1,106 @@ | |||
| use std::convert::Infallible; | |||
There was a problem hiding this comment.
Can we also have tests for:
- "mixed" case where eg origin is a wildcard, but headers/method include vary headers
- very_permissive emitting vary headers
- at least a couple smoke tests on the Cors::map_layer test with and without vary headers
There was a problem hiding this comment.
This should be updated to explain that the default is derived from which other configuration is set, and that setting it explicitly will pin it regardless of other configuration.
Signed-off-by: Aminu Oluwaseun Joshua <seun.aminujoshua@gmail.com>
Motivation
Fixes #539
Relaxes the default Vary header to an empty list.
Solution
Instead of the custom
Defaultimplementation adding some header values, it now simply returns the out-of-the-boxDefault, which is an empty Vector.Also, I altered the test to reflect the new change and an additional test.