Skip to content

Commit dddcc5e

Browse files
committed
Ignore trailing slash in Origin header
See gh-26892
1 parent 582b94d commit dddcc5e

File tree

4 files changed

+32
-7
lines changed

4 files changed

+32
-7
lines changed

spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,9 @@ public String checkOrigin(@Nullable String requestOrigin) {
551551
if (!StringUtils.hasText(requestOrigin)) {
552552
return null;
553553
}
554+
if (requestOrigin.endsWith("/")) {
555+
requestOrigin = requestOrigin.substring(0, requestOrigin.length() - 1);
556+
}
554557
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
555558
if (this.allowedOrigins.contains(ALL)) {
556559
validateAllowCredentials();

spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -291,6 +291,7 @@ public void checkOriginAllowed() {
291291

292292
config.setAllowedOrigins(Collections.singletonList("https://domain.com"));
293293
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
294+
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com");
294295

295296
config.setAllowCredentials(false);
296297
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");

spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -170,10 +170,19 @@ public void actualRequestCaseInsensitiveOriginMatch() throws Exception {
170170
this.conf.addAllowedOrigin("https://DOMAIN2.com");
171171

172172
this.processor.processRequest(this.conf, this.request, this.response);
173+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
173174
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
174-
assertThat(this.response.getHeaders(HttpHeaders.VARY)).contains(HttpHeaders.ORIGIN,
175-
HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
175+
}
176+
177+
@Test // gh-26892
178+
public void actualRequestTrailingSlashOriginMatch() throws Exception {
179+
this.request.setMethod(HttpMethod.GET.name());
180+
this.request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com/");
181+
this.conf.addAllowedOrigin("https://domain2.com");
182+
183+
this.processor.processRequest(this.conf, this.request, this.response);
176184
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
185+
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
177186
}
178187

179188
@Test

spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -172,10 +172,22 @@ public void actualRequestCaseInsensitiveOriginMatch() {
172172
this.processor.process(this.conf, exchange);
173173

174174
ServerHttpResponse response = exchange.getResponse();
175+
assertThat((Object) response.getStatusCode()).isNull();
175176
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
176-
assertThat(response.getHeaders().get(VARY)).contains(ORIGIN,
177-
ACCESS_CONTROL_REQUEST_METHOD, ACCESS_CONTROL_REQUEST_HEADERS);
177+
}
178+
179+
@Test // gh-26892
180+
public void actualRequestTrailingSlashOriginMatch() {
181+
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest
182+
.method(HttpMethod.GET, "http://localhost/test.html")
183+
.header(HttpHeaders.ORIGIN, "https://domain2.com/"));
184+
185+
this.conf.addAllowedOrigin("https://domain2.com");
186+
this.processor.process(this.conf, exchange);
187+
188+
ServerHttpResponse response = exchange.getResponse();
178189
assertThat((Object) response.getStatusCode()).isNull();
190+
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
179191
}
180192

181193
@Test

0 commit comments

Comments
 (0)