Skip to content

Commit 945d677

Browse files
hanbjrjernst
authored andcommitted
Fix thread context handling of headers overriding (#26068)
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.
1 parent 0ba3afe commit 945d677

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,11 +407,10 @@ private ThreadContextStruct putHeaders(Map<String, String> headers) {
407407
if (headers.isEmpty()) {
408408
return this;
409409
} else {
410-
final Map<String, String> newHeaders = new HashMap<>();
410+
final Map<String, String> newHeaders = new HashMap<>(this.requestHeaders);
411411
for (Map.Entry<String, String> entry : headers.entrySet()) {
412412
putSingleHeader(entry.getKey(), entry.getValue(), newHeaders);
413413
}
414-
newHeaders.putAll(this.requestHeaders);
415414
return new ThreadContextStruct(newHeaders, responseHeaders, transientHeaders, isSystemContext);
416415
}
417416
}

core/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.List;
3030
import java.util.Map;
3131
import java.util.function.Supplier;
32-
3332
import static org.hamcrest.Matchers.equalTo;
3433
import static org.hamcrest.Matchers.hasItem;
3534
import static org.hamcrest.Matchers.hasSize;
@@ -215,8 +214,8 @@ public void testResponseHeaders() {
215214
public void testCopyHeaders() {
216215
Settings build = Settings.builder().put("request.headers.default", "1").build();
217216
ThreadContext threadContext = new ThreadContext(build);
218-
threadContext.copyHeaders(Collections.<String,String>emptyMap().entrySet());
219-
threadContext.copyHeaders(Collections.<String,String>singletonMap("foo", "bar").entrySet());
217+
threadContext.copyHeaders(Collections.<String, String>emptyMap().entrySet());
218+
threadContext.copyHeaders(Collections.<String, String>singletonMap("foo", "bar").entrySet());
220219
assertEquals("bar", threadContext.getHeader("foo"));
221220
}
222221

@@ -443,7 +442,7 @@ public void onAfter() {
443442
assertEquals("bar", threadContext.getHeader("foo"));
444443
assertEquals("bar_transient", threadContext.getTransient("foo"));
445444
assertNotNull(threadContext.getTransient("failure"));
446-
assertEquals("exception from doRun", ((RuntimeException)threadContext.getTransient("failure")).getMessage());
445+
assertEquals("exception from doRun", ((RuntimeException) threadContext.getTransient("failure")).getMessage());
447446
assertFalse(threadContext.isDefaultContext());
448447
threadContext.putTransient("after", "after");
449448
}
@@ -604,7 +603,7 @@ protected void doRun() throws Exception {
604603
public void testMarkAsSystemContext() throws IOException {
605604
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
606605
assertFalse(threadContext.isSystemContext());
607-
try(ThreadContext.StoredContext context = threadContext.stashContext()){
606+
try (ThreadContext.StoredContext context = threadContext.stashContext()) {
608607
assertFalse(threadContext.isSystemContext());
609608
threadContext.markAsSystemContext();
610609
assertTrue(threadContext.isSystemContext());
@@ -613,6 +612,17 @@ public void testMarkAsSystemContext() throws IOException {
613612
}
614613
}
615614

615+
public void testPutHeaders() {
616+
Settings build = Settings.builder().put("request.headers.default", "1").build();
617+
ThreadContext threadContext = new ThreadContext(build);
618+
threadContext.putHeader(Collections.<String, String>emptyMap());
619+
threadContext.putHeader(Collections.<String, String>singletonMap("foo", "bar"));
620+
assertEquals("bar", threadContext.getHeader("foo"));
621+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
622+
threadContext.putHeader(Collections.<String, String>singletonMap("foo", "boom")));
623+
assertEquals("value for key [foo] already present", e.getMessage());
624+
}
625+
616626
/**
617627
* Sometimes wraps a Runnable in an AbstractRunnable.
618628
*/

0 commit comments

Comments
 (0)