Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c333903

Browse filesBrowse files
committed
Http header field names must be case-insensitive
GitHub has started changing their headers from capitalized words to all lowercase. A recent change made the header fields querying case-senstive which broke gzip content detection. This was not caught by tests because recorded files remain unchanged. It is also possible that WireMock is auto-capitalizing. This fixes the case-sensitivity issue and also extends that funcionality to anyone consuming the headers generated by ResponseInfo. Fixes hub4j#751
1 parent dd55e8a commit c333903
Copy full SHA for c333903

File tree

Expand file treeCollapse file tree

2 files changed

+34
-2
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+34
-2
lines changed

‎src/main/java/org/kohsuke/github/GitHubResponse.java

Copy file name to clipboardExpand all lines: src/main/java/org/kohsuke/github/GitHubResponse.java
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
import java.net.URL;
1313
import java.nio.charset.StandardCharsets;
1414
import java.util.Collections;
15-
import java.util.HashMap;
15+
import java.util.Comparator;
1616
import java.util.List;
1717
import java.util.Map;
18+
import java.util.TreeMap;
1819

1920
import javax.annotation.CheckForNull;
2021
import javax.annotation.Nonnull;
@@ -206,6 +207,9 @@ interface BodyHandler<T> {
206207
*/
207208
static abstract class ResponseInfo {
208209

210+
private static final Comparator<String> nullableCaseInsensitiveComparator = Comparator
211+
.nullsFirst(String.CASE_INSENSITIVE_ORDER);
212+
209213
private final int statusCode;
210214
@Nonnull
211215
private final GitHubRequest request;
@@ -217,7 +221,12 @@ protected ResponseInfo(@Nonnull GitHubRequest request,
217221
@Nonnull Map<String, List<String>> headers) {
218222
this.request = request;
219223
this.statusCode = statusCode;
220-
this.headers = Collections.unmodifiableMap(new HashMap<>(headers));
224+
225+
// Response header field names must be case-insensitive.
226+
TreeMap<String, List<String>> caseInsensitiveMap = new TreeMap<>(nullableCaseInsensitiveComparator);
227+
caseInsensitiveMap.putAll(headers);
228+
229+
this.headers = Collections.unmodifiableMap(caseInsensitiveMap);
221230
}
222231

223232
/**

‎src/test/java/org/kohsuke/github/GHObjectTest.java

Copy file name to clipboardExpand all lines: src/test/java/org/kohsuke/github/GHObjectTest.java
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import org.junit.Test;
44

5+
import java.util.Objects;
6+
57
import static org.hamcrest.Matchers.*;
68

79
public class GHObjectTest extends org.kohsuke.github.AbstractGitHubWireMockTest {
@@ -16,5 +18,26 @@ public void test_toString() throws Exception {
1618
// getResponseHeaderFields is deprecated but we should not break it.
1719
assertThat(org.getResponseHeaderFields(), notNullValue());
1820
assertThat(org.getResponseHeaderFields().get("Cache-Control").get(0), is("private, max-age=60, s-maxage=60"));
21+
22+
// Header field names must be case-insensitive
23+
assertThat(org.getResponseHeaderFields().containsKey("CacHe-ContrOl"), is(true));
24+
25+
// The KeySet from header fields should also be case-insensitive
26+
assertThat(org.getResponseHeaderFields().keySet().contains("CacHe-ControL"), is(true));
27+
assertThat(org.getResponseHeaderFields().keySet().contains("CacHe-ControL"), is(true));
28+
29+
assertThat(org.getResponseHeaderFields().get("cachE-cOntrol").get(0), is("private, max-age=60, s-maxage=60"));
30+
31+
// GitHub has started changing their headers to all lowercase.
32+
// For this test we want the field names to be with mixed-case (harder to do comparison).
33+
// Ensure that it remains that way, if test resources are ever refreshed.
34+
boolean found = false;
35+
for (String key : org.getResponseHeaderFields().keySet()) {
36+
if (Objects.equals("Cache-Control", key)) {
37+
found = true;
38+
break;
39+
}
40+
}
41+
assertThat("Must have the literal expected string 'Cache-Control' for header field name", found);
1942
}
2043
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.