Skip to content

Commit 0dbf15c

Browse files
committed
feat(gax): add getFirstHeader to HttpHeadersUtils
1 parent 9cd618b commit 0dbf15c

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpHeadersUtils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.google.api.client.util.FieldInfo;
3535
import com.google.api.core.InternalApi;
3636
import com.google.common.collect.ImmutableList;
37+
import com.google.common.collect.Iterables;
3738
import java.util.List;
3839
import java.util.Map;
3940
import org.jspecify.annotations.NullMarked;
@@ -52,6 +53,30 @@ public class HttpHeadersUtils {
5253
return null;
5354
}
5455

56+
/**
57+
* Retrieves the first string value of a header by case-insensitive name from a headers map.
58+
*
59+
* @param headers the map of header names to header values
60+
* @param name the case-insensitive header name to look up
61+
* @return the first string value of the header, or {@code null} if not found
62+
*/
63+
public static @Nullable String getFirstHeader(Map<String, Object> headers, String name) {
64+
for (Map.Entry<String, Object> entry : headers.entrySet()) {
65+
if (entry.getKey().equalsIgnoreCase(name)) {
66+
return extractFirstString(entry.getValue());
67+
}
68+
}
69+
return null;
70+
}
71+
72+
private static @Nullable String extractFirstString(Object headerValue) {
73+
if (headerValue instanceof Iterable) {
74+
Object firstElement = Iterables.getFirst((Iterable<?>) headerValue, null);
75+
return firstElement != null ? firstElement.toString() : null;
76+
}
77+
return headerValue.toString();
78+
}
79+
5580
public static HttpHeaders setHeaders(HttpHeaders headers, Map<String, String> headersMap) {
5681
for (Map.Entry<String, String> entry : headersMap.entrySet()) {
5782
setHeader(headers, entry.getKey(), entry.getValue());

sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpHeadersUtilsTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,29 @@ void testGetUserAgentValue() {
130130
headersMap = ImmutableMap.of("Custom-Header", "CustomHeader", "accept", "Accept");
131131
assertNull(HttpHeadersUtils.getUserAgentValue(headersMap));
132132
}
133+
134+
@Test
135+
void testGetFirstHeader() {
136+
Map<String, Object> headersMap =
137+
ImmutableMap.<String, Object>builder()
138+
.put("X-Goog-Upload-URL", "https://test.googleapis.com/upload")
139+
.put("Location", ImmutableList.of("https://redirect.url", "https://secondary.url"))
140+
.put("Content-Length", 1024L)
141+
.put("Empty-List-Header", ImmutableList.of())
142+
.put("Null-First-Header", java.util.Collections.singletonList(null))
143+
.build();
144+
145+
assertEquals(
146+
"https://test.googleapis.com/upload",
147+
HttpHeadersUtils.getFirstHeader(headersMap, "X-Goog-Upload-URL"));
148+
assertEquals(
149+
"https://test.googleapis.com/upload",
150+
HttpHeadersUtils.getFirstHeader(headersMap, "x-goog-upload-url"));
151+
assertEquals(
152+
"https://redirect.url", HttpHeadersUtils.getFirstHeader(headersMap, "location"));
153+
assertEquals("1024", HttpHeadersUtils.getFirstHeader(headersMap, "content-length"));
154+
assertNull(HttpHeadersUtils.getFirstHeader(headersMap, "empty-list-header"));
155+
assertNull(HttpHeadersUtils.getFirstHeader(headersMap, "null-first-header"));
156+
assertNull(HttpHeadersUtils.getFirstHeader(headersMap, "non-existent-header"));
157+
}
133158
}

0 commit comments

Comments
 (0)