Skip to content

Commit 4b7292f

Browse files
committed
Fix an off-by-one bug in ForwardedHeaderTransformer
Consistently with what is done in ForwardedHeaderFilter. Closes gh-33465
1 parent 83be0f2 commit 4b7292f

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

spring-web/src/main/java/org/springframework/web/server/adapter/ForwardedHeaderTransformer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,6 +53,7 @@
5353
* in which case it removes but does not use the headers.
5454
*
5555
* @author Rossen Stoyanchev
56+
* @author Sebastien Deleuze
5657
* @since 5.1
5758
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
5859
* @see <a href="https://docs.spring.io/spring-framework/reference/web/webflux/reactive-spring.html#webflux-forwarded-headers">Forwarded Headers</a>
@@ -165,7 +166,7 @@ private static String getForwardedPrefix(ServerHttpRequest request) {
165166
String[] rawPrefixes = StringUtils.tokenizeToStringArray(header, ",");
166167
for (String rawPrefix : rawPrefixes) {
167168
int endIndex = rawPrefix.length();
168-
while (endIndex > 1 && rawPrefix.charAt(endIndex - 1) == '/') {
169+
while (endIndex > 0 && rawPrefix.charAt(endIndex - 1) == '/') {
169170
endIndex--;
170171
}
171172
prefix.append((endIndex != rawPrefix.length() ? rawPrefix.substring(0, endIndex) : rawPrefix));

spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* @author Eddú Meléndez
4949
* @author Rob Winch
5050
* @author Brian Clozel
51+
* @author Sebastien Deleuze
5152
*/
5253
class ForwardedHeaderFilterTests {
5354

@@ -442,6 +443,15 @@ void shouldConcatenatePrefixesWithTrailingSlashes() throws Exception {
442443
assertThat(actual.getRequestURL().toString()).isEqualTo("http://localhost/first/second/mvc-showcase");
443444
}
444445

446+
@Test
447+
void shouldRemoveSingleTrailingSlash() throws Exception {
448+
request.addHeader(X_FORWARDED_PREFIX, "/prefix,/");
449+
request.setRequestURI("/mvc-showcase");
450+
451+
HttpServletRequest actual = filterAndGetWrappedRequest();
452+
assertThat(actual.getRequestURL().toString()).isEqualTo("http://localhost/prefix/mvc-showcase");
453+
}
454+
445455
@Test
446456
void requestURLNewStringBuffer() throws Exception {
447457
request.addHeader(X_FORWARDED_PREFIX, "/prefix/");

spring-web/src/test/java/org/springframework/web/server/adapter/ForwardedHeaderTransformerTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* Tests for {@link ForwardedHeaderTransformer}.
3333
*
3434
* @author Rossen Stoyanchev
35+
* @author Sebastien Deleuze
3536
*/
3637
class ForwardedHeaderTransformerTests {
3738

@@ -170,6 +171,17 @@ void shouldConcatenatePrefixesWithTrailingSlashes() {
170171
assertForwardedHeadersRemoved(request);
171172
}
172173

174+
@Test // gh-33465
175+
void shouldRemoveSingleTrailingSlash() {
176+
HttpHeaders headers = new HttpHeaders();
177+
headers.add("X-Forwarded-Prefix", "/prefix,/");
178+
ServerHttpRequest request = this.requestMutator.apply(getRequest(headers));
179+
180+
assertThat(request.getURI()).isEqualTo(URI.create("https://example.com/prefix/path"));
181+
assertThat(request.getPath().value()).isEqualTo("/prefix/path");
182+
assertForwardedHeadersRemoved(request);
183+
}
184+
173185
@Test
174186
void forwardedForNotPresent() {
175187
HttpHeaders headers = new HttpHeaders();

0 commit comments

Comments
 (0)