-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When checking if key exists in ThreadContextStruct:putHeaders() method,should put requestHeaders in map first #26068
Conversation
Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually? |
@cbuescher This PR has been on for a long time and hasn't been noticed. I hope the great God can review it. Thanks |
@hanbj Sorry, but we get to it when we get to it. 6 days isn't really that long when you consider we have over a hundred open PRs, lots of open issues. I hope you understand. In the meantime it might help to understand what problem this change is trying to solve, did you run into a problem with this? Is there an open issue this fixes? |
@cbuescher I'm very very sorry. I didn't mean that. I'm sorry to trouble you |
No problem, I just wanted to explain that PRs get picked up whenever anybody has time to review them. |
And I forgot to add, thanks for taking the time and effort to look at this and submit a PR at all ;-) |
The change looks correct to me, but I think it needs a test (in |
@rjernst I add a test. Thank you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the added test. I left a couple minor comments. Once those are addressed I will kick off CI (it would fail right now due to wildcard imports).
import static org.hamcrest.Matchers.hasItem; | ||
import static org.hamcrest.Matchers.hasSize; | ||
import static org.hamcrest.Matchers.sameInstance; | ||
import static org.hamcrest.Matchers.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you run gradle precommit
? This will fail. We do not use wildcard imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I often use formatting shortcut keys.
assertEquals("bar", threadContext.getHeader("foo")); | ||
try { | ||
threadContext.putHeader(Collections.<String, String>singletonMap("foo", "boom")); | ||
} catch (IllegalArgumentException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use expectThrows(...)
instead of try/catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes,so much the better.
@@ -407,11 +407,10 @@ private ThreadContextStruct putHeaders(Map<String, String> headers) { | |||
if (headers.isEmpty()) { | |||
return this; | |||
} else { | |||
final Map<String, String> newHeaders = new HashMap<>(); | |||
final Map<String, String> newHeaders = new HashMap<>(this.requestHeaders); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized I'm unsure about this fix. The putSingleHeader
below will fail if the key already exists, so anything in requestHeaders can then not be overriden. I think what we want instead is a loop over requestHeaders after the headers loop, but which uses putIfAbsent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't quite catch what you mean.
First of all, I didn't submit this PR before.
1, create a new HashMap instance (newHeaders).
2, traversal parameter headers.
The two step above means check whether the headers's key if exists in newHeaders.
The parameter headers is a Map. It doesn't have the same key. Just put the data in headers into newHeaders.
What we need to do is check if the parameter headers's key already exists in requestHeaders.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this logic is not changed, the following:
newHeaders.putAll (this.requestHeaders);
requestHeaders also overwrites the same key in headers, but the user doesn't know it.
For instance:
headers: ("foo", "bar")
requestHeaders: ("foo", "boom")
After running newHeaders.putAll (this.requestHeaders);
Will become: newHeaders: ("foo", "boom")
However, the user thinks the value corresponding to the foo is bar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you misunderstood my comment. Look at the implementation of putSingleHeader
, which is what the loop over headers
calls to add each header. It will throw an exception if a key already exists. This means with your change if a key exists in requestHeaders
and headers
, an exception will be thrown, while before, the value from requestHeaders
would have "won". The bug here is that the requestHeaders
value should be the fallback, right? So then, instead of initializing the newHeaders
to requestHeaders
, you can iterate over requestHeaders
in place of the current putAll
call, and use newHeaders.putIfAbsent
, so that the value would only be added if headers
did not contain that key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, you can still initialize the newHeaders
to requestHeaders
, but change the call to putSingleHeader
to newHeaders.put
. Since headers
and requestHeaders
are already maps, there is no possibility for duplicate keys within themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know what you mean now. You don't want to thrown an exception.
I found it throw an exception in the putRequest method, So I did the same.
I've also found that in the stashAndMergeHeaders method, if a key exists in context.requestHeaders and headers, the value from requestHeaders would have "won".
I'm not sure now. I hope you can give me a conclusion. if a key exists in requestHeaders and headers, whether requestHeaders to overwrite headers or headers to overwrite requestHeaders.
Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the method takes in headers
, I assume those should "win" over what was in the context headers map before. However, I did notice that in stashAndMergeHeaders
, the requestHeaders
are merged into the headers being passed into putHeaders
, and the order is again such that requestHeaders
wins over headers
. @s1monw can you clarify what the original intention was here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rjernst I think the fix is good. it's really just a shortcut for a single header. I wonder if we should de-optimize and just iterate over the map and use putHeader(string,string) instead? also the test looks great
@rjernst do you want to pull this in? |
@elasticmachine ok to test |
Thanks @hanbj. Sorry for the long delay in merging. |
Previously collisions in headers between old and new contexts could be silently ignored, allowing the original context's headers to "win". This commit fixes the headers to require they are disjoint.
* master: (22 commits) Allow only a fixed-size receive predictor (elastic#26165) Add Homebrew instructions to getting started ingest: Fix bug that prevent date_index_name processor from accepting timestamps specified as a json number Scripting: Fix expressions to temporarily support filter scripts (elastic#26824) Docs: Add note to contributing docs warning against tool based refactoring (elastic#26936) Fix thread context handling of headers overriding (elastic#26068) SearchWhileCreatingIndexIT: remove usage of _only_nodes update Lucene version for 6.0-RC2 version Calculate and cache result when advanceExact is called (elastic#26920) Test query builder bwc against previous supported versions instead of just the current version. Set minimum_master_nodes on rolling-upgrade test (elastic#26911) Return List instead of an array from settings (elastic#26903) remove _primary and _replica shard preferences (elastic#26791) fixing typo in datehistogram-aggregation.asciidoc (elastic#26924) [API] Added the `terminate_after` parameter to the REST spec for "Count" API Setup debug logging for qa.full-cluster-restart Enable BWC testing against other remotes Use LF line endings in Painless generated files (elastic#26822) [DOCS] Added info about snapshotting your data before an upgrade. Add documentation about disabling `_field_names`. (elastic#26813) ...
* master: Fix handling of paths containing parentheses Allow only a fixed-size receive predictor (elastic#26165) Add Homebrew instructions to getting started ingest: Fix bug that prevent date_index_name processor from accepting timestamps specified as a json number Scripting: Fix expressions to temporarily support filter scripts (elastic#26824) Docs: Add note to contributing docs warning against tool based refactoring (elastic#26936) Fix thread context handling of headers overriding (elastic#26068) SearchWhileCreatingIndexIT: remove usage of _only_nodes
Pinging @elastic/es-distributed |
1、The parameter headers does not have the same key, so the checksum doesn't make sense
2、When checking that key already exists in requestHeaders, you should first put