You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ab...@apache.org on 2026/10/08 09:16:27 UTC
(httpcomponents-client) branch master updated: SSE: Handle request header names case-insensitively
This is an automated email from the ASF dual-hosted git repository.
arturobernalg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git
The following commit(s) were added to refs/heads/master by this push:
new 5a3138de5 SSE: Handle request header names case-insensitively
5a3138de5 is described below
commit 5a3138de57230d72463827393554ad9e6682c0ef
Author: Arturo Bernal <ab...@apache.org>
AuthorDate: Tue Oct 6 14:10:35 2026 +0200
SSE: Handle request header names case-insensitively
---
.../client5/http/sse/impl/DefaultEventSource.java | 10 ++++--
.../http/sse/impl/DefaultEventSourceTest.java | 41 ++++++++++++++++++++++
2 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/httpclient5-sse/src/main/java/org/apache/hc/client5/http/sse/impl/DefaultEventSource.java b/httpclient5-sse/src/main/java/org/apache/hc/client5/http/sse/impl/DefaultEventSource.java
index 6d59dff0e..4a1f8b049 100644
--- a/httpclient5-sse/src/main/java/org/apache/hc/client5/http/sse/impl/DefaultEventSource.java
+++ b/httpclient5-sse/src/main/java/org/apache/hc/client5/http/sse/impl/DefaultEventSource.java
@@ -32,8 +32,9 @@
import java.net.URI;
import java.util.Map;
import java.util.Objects;
+import java.util.TreeMap;
import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
@@ -178,7 +179,8 @@ public DefaultEventSource(final CloseableHttpAsyncClient client,
final SseParser parser) {
this.client = Objects.requireNonNull(client, "client");
this.uri = Objects.requireNonNull(uri, "uri");
- this.headers = new ConcurrentHashMap<>(Objects.requireNonNull(headers, "headers"));
+ this.headers = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER);
+ this.headers.putAll(Objects.requireNonNull(headers, "headers"));
this.listener = listener != null ? listener : (id, type, data) -> { /* no-op */ };
if (scheduler != null) {
@@ -273,7 +275,9 @@ public void removeHeader(final String name) {
*/
@Override
public Map<String, String> getHeaders() {
- return new ConcurrentHashMap<>(headers);
+ final Map<String, String> copy = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ copy.putAll(headers);
+ return copy;
}
/**
diff --git a/httpclient5-sse/src/test/java/org/apache/hc/client5/http/sse/impl/DefaultEventSourceTest.java b/httpclient5-sse/src/test/java/org/apache/hc/client5/http/sse/impl/DefaultEventSourceTest.java
index 43d2d1fd5..18827f589 100644
--- a/httpclient5-sse/src/test/java/org/apache/hc/client5/http/sse/impl/DefaultEventSourceTest.java
+++ b/httpclient5-sse/src/test/java/org/apache/hc/client5/http/sse/impl/DefaultEventSourceTest.java
@@ -32,7 +32,9 @@
import java.net.URI;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
@@ -323,4 +325,43 @@ void sendsNonEmptyLastEventId() {
"42",
client.lastRequest.getFirstHeader("Last-Event-ID").getValue());
}
+
+ @Test
+ void headerNamesAreCaseInsensitive() {
+ final DefaultEventSource eventSource = new DefaultEventSource(
+ new CapturingClient(),
+ URI.create("http://localhost/sse"),
+ Collections.emptyMap(),
+ null);
+
+ eventSource.setHeader("Authorization", "one");
+ eventSource.setHeader("authorization", "two");
+
+ final Map<String, String> headers = eventSource.getHeaders();
+
+ assertEquals(1, headers.size());
+ assertEquals("two", headers.get("AUTHORIZATION"));
+
+ eventSource.removeHeader("AUTHORIZATION");
+
+ assertTrue(eventSource.getHeaders().isEmpty());
+ }
+
+ @Test
+ void initialHeaderNamesAreCaseInsensitive() {
+ final Map<String, String> initialHeaders = new LinkedHashMap<>();
+ initialHeaders.put("X-Test", "one");
+ initialHeaders.put("x-test", "two");
+
+ final DefaultEventSource eventSource = new DefaultEventSource(
+ new CapturingClient(),
+ URI.create("http://localhost/sse"),
+ initialHeaders,
+ null);
+
+ final Map<String, String> headers = eventSource.getHeaders();
+
+ assertEquals(1, headers.size());
+ assertEquals("two", headers.get("X-TEST"));
+ }
}