Skip to content

Commit da5ef38

Browse files
neerajbhattclaude
andcommitted
fix: address review feedback on HeaderAccessor bridging
- Hoist the anonymous HeaderAccessor in DefaultServerTransportSecurityValidator#validateHeaders(Map) into a named MapHeaderAccessor nested class - Filter out null header values before findFirst() in MapHeaderAccessor - Preserve original header name casing in ServerTransportSecurityValidator#toHttpHeaderValidator, matching the case-sensitive behavior of the removed HttpServletRequestUtils#extractHeaders - Correct @SInCE tags on HeaderAccessor and HttpServletHeaderAccessor to 2.1.0 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 5436fc1 commit da5ef38

5 files changed

Lines changed: 38 additions & 27 deletions

File tree

‎mcp-core/src/main/java/io/modelcontextprotocol/server/transport/DefaultServerTransportSecurityValidator.java‎

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.ArrayList;
88
import java.util.List;
99
import java.util.Map;
10+
import java.util.Objects;
1011

1112
import io.modelcontextprotocol.util.Assert;
1213

@@ -50,22 +51,7 @@ private DefaultServerTransportSecurityValidator(List<String> allowedOrigins, Lis
5051
@Override
5152
@Deprecated
5253
public void validateHeaders(Map<String, List<String>> headers) throws ServerTransportSecurityException {
53-
validate(new HeaderAccessor() {
54-
@Override
55-
public List<String> getHeader(String name) {
56-
return headers.entrySet()
57-
.stream()
58-
.filter(entry -> entry.getKey().equalsIgnoreCase(name))
59-
.map(Map.Entry::getValue)
60-
.findFirst()
61-
.orElse(List.of());
62-
}
63-
64-
@Override
65-
public List<String> getHeaderNames() {
66-
return List.copyOf(headers.keySet());
67-
}
68-
});
54+
validate(new MapHeaderAccessor(headers));
6955
}
7056

7157
@Override
@@ -152,6 +138,37 @@ public static Builder builder() {
152138
return new Builder();
153139
}
154140

141+
/**
142+
* {@link HeaderAccessor} view over a {@code Map<String, List<String>>}, used to
143+
* bridge the deprecated {@link #validateHeaders(Map)} to
144+
* {@link #validate(HeaderAccessor)}.
145+
*/
146+
private static final class MapHeaderAccessor implements HeaderAccessor {
147+
148+
private final Map<String, List<String>> headers;
149+
150+
private MapHeaderAccessor(Map<String, List<String>> headers) {
151+
this.headers = headers;
152+
}
153+
154+
@Override
155+
public List<String> getHeader(String name) {
156+
return headers.entrySet()
157+
.stream()
158+
.filter(entry -> entry.getKey().equalsIgnoreCase(name))
159+
.map(Map.Entry::getValue)
160+
.filter(Objects::nonNull)
161+
.findFirst()
162+
.orElse(List.of());
163+
}
164+
165+
@Override
166+
public List<String> getHeaderNames() {
167+
return List.copyOf(headers.keySet());
168+
}
169+
170+
}
171+
155172
/**
156173
* Builder for creating instances of {@link DefaultServerTransportSecurityValidator}.
157174
*/

‎mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HeaderAccessor.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* {@code HttpServletRequest}).
1313
*
1414
* @author Neeraj Bhatt
15-
* @since 0.16.0
15+
* @since 2.1.0
1616
* @see ServerHttpHeaderValidator
1717
*/
1818
public interface HeaderAccessor {

‎mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletHeaderAccessor.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* For internal use only.
1818
*
1919
* @author Neeraj Bhatt
20-
* @since 0.16.0
20+
* @since 2.1.0
2121
* @see HeaderAccessor
2222
*/
2323
final class HttpServletHeaderAccessor implements HeaderAccessor {

‎mcp-core/src/main/java/io/modelcontextprotocol/server/transport/ServerTransportSecurityValidator.java‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
package io.modelcontextprotocol.server.transport;
66

7-
import java.util.ArrayList;
8-
import java.util.Collections;
97
import java.util.List;
108
import java.util.Map;
9+
import java.util.function.Function;
1110
import java.util.stream.Collectors;
1211

1312
/**
@@ -40,12 +39,7 @@ static ServerHttpHeaderValidator toHttpHeaderValidator(ServerTransportSecurityVa
4039
return accessor -> {
4140
var collectedHeaders = accessor.getHeaderNames()
4241
.stream()
43-
.collect(Collectors.<String, String, List<String>>toUnmodifiableMap(String::toLowerCase,
44-
accessor::getHeader, (l1, l2) -> {
45-
var merged = new ArrayList<>(l1);
46-
merged.addAll(l2);
47-
return Collections.unmodifiableList(merged);
48-
}));
42+
.collect(Collectors.toUnmodifiableMap(Function.identity(), accessor::getHeader));
4943
validator.validateHeaders(collectedHeaders);
5044
};
5145
}

‎mcp-core/src/test/java/io/modelcontextprotocol/server/transport/DefaultServerTransportSecurityValidatorTests.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ void noopAcceptsAll() {
484484
@Test
485485
void legacyValidatorAdaptsToHeaderAccessor() {
486486
ServerTransportSecurityValidator legacyValidator = headers -> {
487-
List<String> origins = headers.getOrDefault("origin", List.of());
487+
List<String> origins = headers.getOrDefault("Origin", List.of());
488488
if (!origins.isEmpty() && origins.get(0).contains("evil")) {
489489
throw new ServerTransportSecurityException(403, "Invalid Origin header");
490490
}

0 commit comments

Comments
 (0)