diff --git a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java index e90d450751..7403938469 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java @@ -119,6 +119,10 @@ public class DefaultCorsProcessor implements CorsProcessor { String requestOrigin = request.getHeaders().getOrigin(); String allowOrigin = checkOrigin(config, requestOrigin); + HttpHeaders responseHeaders = response.getHeaders(); + + responseHeaders.add(HttpHeaders.VARY, HttpHeaders.ORIGIN); + if (allowOrigin == null) { logger.debug("Rejecting CORS request because '" + requestOrigin + "' origin is not allowed"); rejectRequest(response); @@ -141,9 +145,7 @@ public class DefaultCorsProcessor implements CorsProcessor { return false; } - HttpHeaders responseHeaders = response.getHeaders(); responseHeaders.setAccessControlAllowOrigin(allowOrigin); - responseHeaders.add(HttpHeaders.VARY, HttpHeaders.ORIGIN); if (preFlightRequest) { responseHeaders.setAccessControlAllowMethods(allowMethods); diff --git a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java index 4d82fbfc80..39ecfae87b 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java @@ -105,6 +105,9 @@ public class DefaultCorsProcessor implements CorsProcessor { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); + HttpHeaders responseHeaders = response.getHeaders(); + + response.getHeaders().add(HttpHeaders.VARY, HttpHeaders.ORIGIN); String requestOrigin = request.getHeaders().getOrigin(); String allowOrigin = checkOrigin(config, requestOrigin); @@ -130,9 +133,7 @@ public class DefaultCorsProcessor implements CorsProcessor { return false; } - HttpHeaders responseHeaders = response.getHeaders(); responseHeaders.setAccessControlAllowOrigin(allowOrigin); - responseHeaders.add(HttpHeaders.VARY, HttpHeaders.ORIGIN); if (preFlightRequest) { responseHeaders.setAccessControlAllowMethods(allowMethods); diff --git a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java index ba666056cc..c929c10e4c 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java @@ -65,6 +65,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_FORBIDDEN, this.response.getStatus()); } @@ -89,6 +90,7 @@ public class DefaultCorsProcessorTests { assertEquals("*", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -106,6 +108,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -121,6 +124,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -132,6 +136,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -149,6 +154,7 @@ public class DefaultCorsProcessorTests { assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1")); assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2")); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -160,6 +166,7 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("*"); this.processor.processRequest(this.conf, this.request, this.response); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -171,6 +178,7 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("*"); this.processor.processRequest(this.conf, this.request, this.response); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_FORBIDDEN, this.response.getStatus()); } @@ -184,6 +192,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); assertEquals("GET,HEAD", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); } @Test @@ -193,6 +202,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_FORBIDDEN, this.response.getStatus()); } @@ -204,6 +214,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_FORBIDDEN, this.response.getStatus()); } @@ -216,6 +227,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_FORBIDDEN, this.response.getStatus()); } @@ -237,6 +249,7 @@ public class DefaultCorsProcessorTests { assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); assertEquals("GET,PUT", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -257,6 +270,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -275,6 +289,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals("http://domain2.com", this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -295,6 +310,7 @@ public class DefaultCorsProcessorTests { assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); assertFalse(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3")); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -313,6 +329,7 @@ public class DefaultCorsProcessorTests { assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); assertTrue(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); assertFalse(this.response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("*")); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } @@ -328,6 +345,7 @@ public class DefaultCorsProcessorTests { this.processor.processRequest(this.conf, this.request, this.response); assertTrue(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertFalse(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS)); + assertEquals(HttpHeaders.ORIGIN, this.response.getHeader(HttpHeaders.VARY)); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); } diff --git a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java index 115fae252a..bf396e6a7b 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java @@ -63,6 +63,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); } @@ -87,6 +88,7 @@ public class DefaultCorsProcessorTests { assertEquals("*", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN)); assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -104,6 +106,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -119,6 +122,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -130,6 +134,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -147,6 +152,7 @@ public class DefaultCorsProcessorTests { assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); assertTrue(response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1")); assertTrue(response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2")); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -157,7 +163,9 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("*"); this.processor.process(this.conf, exchange); - assertNull(exchange.getResponse().getStatusCode()); + ServerHttpResponse response = exchange.getResponse(); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); + assertNull(response.getStatusCode()); } @@ -168,7 +176,9 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("*"); this.processor.process(this.conf, exchange); - assertEquals(HttpStatus.FORBIDDEN, exchange.getResponse().getStatusCode()); + ServerHttpResponse response = exchange.getResponse(); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); + assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); } @Test @@ -180,6 +190,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertNull(response.getStatusCode()); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertEquals("GET,HEAD", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); } @@ -190,6 +201,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); } @@ -201,6 +213,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); } @@ -214,6 +227,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); } @@ -237,6 +251,7 @@ public class DefaultCorsProcessorTests { assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); assertEquals("GET,PUT", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); assertFalse(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -259,6 +274,7 @@ public class DefaultCorsProcessorTests { assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN)); assertTrue(response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals("true", response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -279,6 +295,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals("http://domain2.com", response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -301,6 +318,7 @@ public class DefaultCorsProcessorTests { assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); assertFalse(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3")); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -321,6 +339,7 @@ public class DefaultCorsProcessorTests { assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); assertTrue(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); assertFalse(response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("*")); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); } @@ -338,6 +357,7 @@ public class DefaultCorsProcessorTests { ServerHttpResponse response = exchange.getResponse(); assertTrue(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)); assertFalse(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS)); + assertEquals(HttpHeaders.ORIGIN, response.getHeaders().getFirst(HttpHeaders.VARY)); assertNull(response.getStatusCode()); }