Skip to content

Commit 72ce8d9

Browse files
authored
Avoid duplicate headers when injecting on java.net http client (#10315)
* Avoid duplicate headers when injecting on java.net http client * Use TreeMap
1 parent 9032c6d commit 72ce8d9

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

dd-java-agent/instrumentation/java/java-net/java-net-11.0/src/main/java11/datadog/trace/instrumentation/httpclient/HeadersAdvice.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@
44
import static datadog.trace.instrumentation.httpclient.HttpHeadersInjectAdapter.KEEP;
55
import static datadog.trace.instrumentation.httpclient.HttpHeadersInjectAdapter.SETTER;
66
import static datadog.trace.instrumentation.httpclient.JavaNetClientDecorator.DECORATE;
7+
import static java.lang.String.CASE_INSENSITIVE_ORDER;
78

89
import java.net.http.HttpHeaders;
9-
import java.util.HashMap;
1010
import java.util.List;
1111
import java.util.Map;
12+
import java.util.TreeMap;
1213
import net.bytebuddy.asm.Advice;
1314

1415
public class HeadersAdvice {
1516
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
1617
public static void methodExit(@Advice.Return(readOnly = false) HttpHeaders headers) {
17-
final Map<String, List<String>> headerMap = new HashMap<>(headers.map());
18+
// Note: adding duplicate keys will throw an IllegalArgumentException so we need to dedupe
19+
// case insensitively
20+
final Map<String, List<String>> headerMap = new TreeMap<>(CASE_INSENSITIVE_ORDER);
21+
headerMap.putAll(headers.map());
1822
DECORATE.injectContext(getCurrentContext(), headerMap, SETTER);
1923
headers = HttpHeaders.of(headerMap, KEEP);
2024
}

dd-java-agent/instrumentation/java/java-net/java-net-11.0/src/test/groovy/datadog/trace/instrumentation/httpclient/JavaHttpClientTest.groovy

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package datadog.trace.instrumentation.httpclient
22

3-
import datadog.trace.agent.test.base.HttpClientTest
3+
44
import static datadog.trace.instrumentation.httpclient.JavaNetClientDecorator.DECORATE
55

6+
import datadog.trace.agent.test.base.HttpClientTest
67
import java.net.http.HttpClient
78
import java.net.http.HttpRequest
89
import java.net.http.HttpResponse
@@ -42,6 +43,22 @@ abstract class JavaHttpClientTest extends HttpClientTest {
4243
boolean testRedirects() {
4344
false
4445
}
46+
47+
def 'should not inject duplicate headers'() {
48+
when:
49+
def status = doRequest("GET", server.address.resolve("/success"),
50+
// our codec inject names all lowercase
51+
["X-Datadog-Trace-ID": "0"])
52+
53+
then:
54+
status == 200
55+
assertTraces(2) {
56+
trace(size(1)) {
57+
clientSpan(it, null)
58+
}
59+
server.distributedRequestTrace(it, trace(0).last())
60+
}
61+
}
4562
}
4663

4764
class JavaHttpClientV0Test extends JavaHttpClientTest {

0 commit comments

Comments
 (0)