From 83f269b512fb75508d8a53f1696a370134be0219 Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Sun, 19 Apr 2015 18:26:46 +0200 Subject: [PATCH] Make DefaultCorsProcessor Servlet 2.5 compliant This commit adds CORS related headers to HttpHeaders and update DefaultCorsProcessor implementation to use ServerHttpRequest and ServerHttpResponse instead of HttpServletRequest and HttpServletResponse. Usage of ServerHttpResponse allows to avoid using Servlet 3.0 specific methods in order keep CORS support Servlet 2.5 compliant. Issue: SPR-12885 --- .../org/springframework/http/HttpHeaders.java | 163 ++++++++++++++++++ .../web/cors/CorsProcessor.java | 2 + .../springframework/web/cors/CorsUtils.java | 46 ----- .../web/cors/DefaultCorsProcessor.java | 149 +++++++++------- .../http/HttpHeadersTests.java | 70 ++++++++ .../web/cors/CorsUtilsTests.java | 4 +- .../web/cors/DefaultCorsProcessorTests.java | 122 ++++++------- .../mvc/method/RequestMappingInfo.java | 3 +- .../CorsAbstractHandlerMappingTests.java | 8 +- .../mvc/method/RequestMappingInfoTests.java | 3 +- .../method/annotation/CrossOriginTests.java | 9 +- .../sockjs/support/SockJsServiceTests.java | 23 ++- .../handler/DefaultSockJsServiceTests.java | 5 +- 13 files changed, 410 insertions(+), 197 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index d37806740c7..47f7b681c16 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -86,6 +86,46 @@ public class HttpHeaders implements MultiValueMap, Serializable * @see Section 5.3.5 of RFC 7233 */ public static final String ACCEPT_RANGES = "Accept-Ranges"; + /** + * The CORS {@code Access-Control-Allow-Credentials} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; + /** + * The CORS {@code Access-Control-Allow-Headers} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; + /** + * The CORS {@code Access-Control-Allow-Methods} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; + /** + * The CORS {@code Access-Control-Allow-Origin} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; + /** + * The CORS {@code Access-Control-Expose-Headers} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; + /** + * The CORS {@code Access-Control-Max-Age} response header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; + /** + * The CORS {@code Access-Control-Request-Headers} request header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; + /** + * The CORS {@code Access-Control-Request-Method} request header field name. + * @see CORS W3C recommandation + */ + public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; /** * The HTTP {@code Age} header field name. * @see Section 5.1 of RFC 7234 @@ -390,6 +430,129 @@ public class HttpHeaders implements MultiValueMap, Serializable return result; } + /** + * Set the (new) value of the {@code Access-Control-Allow-Credentials} response header. + */ + public void setAccessControlAllowCredentials(boolean allowCredentials) { + set(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.toString(allowCredentials)); + } + + /** + * Returns the value of the {@code Access-Control-Allow-Credentials} response header. + */ + public boolean getAccessControlAllowCredentials() { + return new Boolean(getFirst(ACCESS_CONTROL_ALLOW_CREDENTIALS)); + } + + /** + * Set the (new) value of the {@code Access-Control-Allow-Headers} response header. + */ + public void setAccessControlAllowHeaders(List allowedHeaders) { + set(ACCESS_CONTROL_ALLOW_HEADERS, toCommaDelimitedString(allowedHeaders)); + } + + /** + * Returns the value of the {@code Access-Control-Allow-Headers} response header. + */ + public List getAccessControlAllowHeaders() { + return getFirstValueAsList(ACCESS_CONTROL_ALLOW_HEADERS); + } + + /** + * Set the (new) value of the {@code Access-Control-Allow-Methods} response header. + */ + public void setAccessControlAllowMethods(List allowedMethods) { + set(ACCESS_CONTROL_ALLOW_METHODS, StringUtils.collectionToCommaDelimitedString(allowedMethods)); + } + + /** + * Returns the value of the {@code Access-Control-Allow-Methods} response header. + */ + public List getAccessControlAllowMethods() { + List result = new ArrayList(); + String value = getFirst(ACCESS_CONTROL_ALLOW_METHODS); + if (value != null) { + String[] tokens = value.split(",\\s*"); + for (String token : tokens) { + result.add(HttpMethod.valueOf(token)); + } + } + return result; + } + + /** + * Set the (new) value of the {@code Access-Control-Allow-Origin} response header. + */ + public void setAccessControlAllowOrigin(String allowedOrigin) { + set(ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigin); + } + + /** + * Returns the value of the {@code Access-Control-Allow-Origin} response header. + */ + public String getAccessControlAllowOrigin() { + return getFirst(ACCESS_CONTROL_ALLOW_ORIGIN); + } + + /** + * Set the (new) value of the {@code Access-Control-Expose-Headers} response header. + */ + public void setAccessControlExposeHeaders(List exposedHeaders) { + set(ACCESS_CONTROL_EXPOSE_HEADERS, toCommaDelimitedString(exposedHeaders)); + } + + /** + * Returns the value of the {@code Access-Control-Expose-Headers} response header. + */ + public List getAccessControlExposeHeaders() { + return getFirstValueAsList(ACCESS_CONTROL_EXPOSE_HEADERS); + } + + /** + * Set the (new) value of the {@code Access-Control-Max-Age} response header. + */ + public void setAccessControlMaxAge(long maxAge) { + set(ACCESS_CONTROL_MAX_AGE, Long.toString(maxAge)); + } + + /** + * Returns the value of the {@code Access-Control-Max-Age} response header. + *

Returns -1 when the max age is unknown. + */ + public long getAccessControlMaxAge() { + String value = getFirst(ACCESS_CONTROL_MAX_AGE); + return (value != null ? Long.parseLong(value) : -1); + } + + /** + * Set the (new) value of the {@code Access-Control-Request-Headers} request header. + */ + public void setAccessControlRequestHeaders(List requestHeaders) { + set(ACCESS_CONTROL_REQUEST_HEADERS, toCommaDelimitedString(requestHeaders)); + } + + /** + * Returns the value of the {@code Access-Control-Request-Headers} request header. + */ + public List getAccessControlRequestHeaders() { + return getFirstValueAsList(ACCESS_CONTROL_REQUEST_HEADERS); + } + + /** + * Set the (new) value of the {@code Access-Control-Request-Method} request header. + */ + public void setAccessControlRequestMethod(HttpMethod requestedMethod) { + set(ACCESS_CONTROL_REQUEST_METHOD, requestedMethod.name()); + } + + /** + * Returns the value of the {@code Access-Control-Request-Method} request header. + */ + public HttpMethod getAccessControlRequestMethod() { + String value = getFirst(ACCESS_CONTROL_REQUEST_METHOD); + return (value != null ? HttpMethod.valueOf(value) : null); + } + /** * Set the list of acceptable {@linkplain Charset charsets}, * as specified by the {@code Accept-Charset} header. diff --git a/spring-web/src/main/java/org/springframework/web/cors/CorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/CorsProcessor.java index 790e9259c15..41b85c1dafb 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/CorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/CorsProcessor.java @@ -36,6 +36,7 @@ public interface CorsProcessor { * comply with the configuration it should be rejected. * If the request is valid and complies with the configuration, CORS headers * should be added to the response. + * @return {@code false} if the request is rejected, else {@code true}. */ boolean processPreFlightRequest(CorsConfiguration conf, HttpServletRequest request, HttpServletResponse response) throws IOException; @@ -46,6 +47,7 @@ public interface CorsProcessor { * not comply with the configuration, it should be rejected. * If the request is valid and comply with the configuration, this method adds the related * CORS headers to the response. + * @return {@code false} if the request is rejected, else {@code true}. */ boolean processActualRequest(CorsConfiguration conf, HttpServletRequest request, HttpServletResponse response) throws IOException; diff --git a/spring-web/src/main/java/org/springframework/web/cors/CorsUtils.java b/spring-web/src/main/java/org/springframework/web/cors/CorsUtils.java index 19afc26ffda..e3a985eeb00 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/CorsUtils.java +++ b/spring-web/src/main/java/org/springframework/web/cors/CorsUtils.java @@ -16,14 +16,10 @@ package org.springframework.web.cors; -import java.util.Arrays; -import java.util.List; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.util.CollectionUtils; /** * Utility class for CORS request handling based on the @@ -34,48 +30,6 @@ import org.springframework.util.CollectionUtils; */ public class CorsUtils { - /** - * The CORS {@code Access-Control-Request-Headers} request header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; - /** - * The CORS {@code Access-Control-Request-Method} request header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; - /** - * The CORS {@code Access-Control-Allow-Origin} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; - /** - * The CORS {@code Access-Control-Allow-Headers} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; - /** - * The CORS {@code Access-Control-Allow-Methods} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; - /** - * The CORS {@code Access-Control-Max-Age} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; - /** - * The CORS {@code Access-Control-Allow-Credentials} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; - /** - * The CORS {@code Access-Control-Expose-Headers} response header field name. - * @see CORS W3C recommandation - */ - public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; - - /** * Returns {@code true} if the request is a valid CORS one. */ 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 96dacf2a473..e441604b1b1 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 @@ -17,11 +17,11 @@ package org.springframework.web.cors; import java.io.IOException; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.List; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -30,9 +30,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; /** * Default implementation of {@link CorsProcessor}, as defined by the @@ -43,6 +46,9 @@ import org.springframework.util.StringUtils; */ public class DefaultCorsProcessor implements CorsProcessor { + private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); + + protected final Log logger = LogFactory.getLog(getClass()); @@ -50,53 +56,74 @@ public class DefaultCorsProcessor implements CorsProcessor { public boolean processPreFlightRequest(CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) throws IOException { - Assert.isTrue(CorsUtils.isPreFlightRequest(request)); + ServerHttpRequest serverRequest = new ServletServerHttpRequest(request); + ServerHttpResponse serverResponse = new ServletServerHttpResponse(response); + boolean isPreFlight = CorsUtils.isPreFlightRequest(request); + Assert.isTrue(isPreFlight); + if (skip(serverResponse)) { + return true; + } - if (check(request, response, config)) { - setAllowOrigin(request, response, config.getAllowedOrigins(), config.isAllowCredentials()); - setAllowCredentials(response, config.isAllowCredentials()); - setAllowMethods(request, response, config.getAllowedMethods()); - setAllowHeadersHeader(request, response, config.getAllowedHeaders()); - setMaxAgeHeader(response, config.getMaxAge()); + if (check(serverRequest, serverResponse, config, isPreFlight)) { + setAllowOrigin(serverRequest, serverResponse, config.getAllowedOrigins(), config.isAllowCredentials()); + setAllowCredentials(serverResponse, config.isAllowCredentials()); + setAllowMethods(serverRequest, serverResponse, config.getAllowedMethods()); + setAllowHeadersHeader(serverRequest, serverResponse, config.getAllowedHeaders()); + setMaxAgeHeader(serverResponse, config.getMaxAge()); + serverResponse.close(); + return true; } - return true; + return false; } @Override public boolean processActualRequest(CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) throws IOException { - Assert.isTrue(CorsUtils.isCorsRequest(request) && !CorsUtils.isPreFlightRequest(request)); + ServerHttpRequest serverRequest = new ServletServerHttpRequest(request); + ServerHttpResponse serverResponse = new ServletServerHttpResponse(response); + boolean isPreFlight = CorsUtils.isPreFlightRequest(request); + Assert.isTrue(CorsUtils.isCorsRequest(request) && !isPreFlight); + if (skip(serverResponse)) { + return true; + } - if (check(request, response, config)) { - setAllowOrigin(request, response, config.getAllowedOrigins(), config.isAllowCredentials()); - setAllowCredentials(response, config.isAllowCredentials()); - setExposeHeadersHeader(response, config.getExposedHeaders()); + if (check(serverRequest, serverResponse, config, isPreFlight)) { + setAllowOrigin(serverRequest, serverResponse, config.getAllowedOrigins(), config.isAllowCredentials()); + setAllowCredentials(serverResponse, config.isAllowCredentials()); + setExposeHeadersHeader(serverResponse, config.getExposedHeaders()); + serverResponse.close(); + return true; } - return true; + return false; } - private boolean check(HttpServletRequest request, HttpServletResponse response, - CorsConfiguration config) throws IOException { - + private boolean skip(ServerHttpResponse response) { if (hasAllowOriginHeader(response)) { logger.debug("Skip adding CORS headers, response already contains \"Access-Control-Allow-Origin\""); - return false; + return true; } - if (!checkOrigin(request, config.getAllowedOrigins()) || !checkMethod(request, config.getAllowedMethods()) || - !checkHeaders(request, config.getAllowedHeaders())) { - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid CORS request"); + return false; + } + + private boolean check(ServerHttpRequest request, ServerHttpResponse response, + CorsConfiguration config, boolean isPreFlight) throws IOException { + + if (!checkOrigin(request, config.getAllowedOrigins()) || + !checkMethod(request, config.getAllowedMethods(), isPreFlight) || + !checkHeaders(request, config.getAllowedHeaders(), isPreFlight)) { + response.setStatusCode(HttpStatus.FORBIDDEN); + response.getBody().write("Invalid CORS request".getBytes(UTF8_CHARSET)); return false; } return true; } - private boolean hasAllowOriginHeader(HttpServletResponse response) { + private boolean hasAllowOriginHeader(ServerHttpResponse response) { boolean hasCorsResponseHeaders = false; try { // Perhaps a CORS Filter has already added this? - Collection headers = response.getHeaders(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN); - hasCorsResponseHeaders = !CollectionUtils.isEmpty(headers); + hasCorsResponseHeaders = response.getHeaders().getAccessControlAllowOrigin() != null; } catch (NullPointerException npe) { // See SPR-11919 and https://issues.jboss.org/browse/WFLY-3474 @@ -104,8 +131,8 @@ public class DefaultCorsProcessor implements CorsProcessor { return hasCorsResponseHeaders; } - private boolean checkOrigin(HttpServletRequest request, List allowedOrigins) { - String originHeader = request.getHeader(HttpHeaders.ORIGIN); + private boolean checkOrigin(ServerHttpRequest request, List allowedOrigins) { + String originHeader = request.getHeaders().getOrigin(); if (originHeader == null || allowedOrigins == null) { return false; } @@ -120,9 +147,10 @@ public class DefaultCorsProcessor implements CorsProcessor { return false; } - private boolean checkMethod(HttpServletRequest request, List allowedMethods) { - String requestMethod = CorsUtils.isPreFlightRequest(request) ? - request.getHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD) : request.getMethod(); + private boolean checkMethod(ServerHttpRequest request, List allowedMethods, boolean isPreFlight) { + HttpMethod requestMethod = isPreFlight ? + request.getHeaders().getAccessControlRequestMethod() : + request.getMethod(); if (allowedMethods == null) { allowedMethods = Arrays.asList(HttpMethod.GET.name()); } @@ -130,18 +158,16 @@ public class DefaultCorsProcessor implements CorsProcessor { return true; } for (String allowedMethod : allowedMethods) { - if (allowedMethod.equalsIgnoreCase(requestMethod)) { + if (allowedMethod.equalsIgnoreCase(requestMethod.name())) { return true; } } return false; } - private boolean checkHeaders(HttpServletRequest request, List allowedHeaders) { - String headerValue = request.getHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS); - String[] requestHeaders = CorsUtils.isPreFlightRequest(request) ? - StringUtils.commaDelimitedListToStringArray(headerValue) : - Collections.list(request.getHeaderNames()).toArray(new String[0]); + private boolean checkHeaders(ServerHttpRequest request, List allowedHeaders, boolean isPreFlight) { + List requestHeaders = isPreFlight ? request.getHeaders().getAccessControlRequestHeaders() : + new ArrayList(request.getHeaders().keySet()); if ((allowedHeaders != null) && allowedHeaders.contains("*")) { return true; } @@ -165,38 +191,41 @@ public class DefaultCorsProcessor implements CorsProcessor { return true; } - private void setAllowOrigin(HttpServletRequest request, HttpServletResponse response, + private void setAllowOrigin(ServerHttpRequest request, ServerHttpResponse response, List allowedOrigins, Boolean allowCredentials) { - String origin = request.getHeader(HttpHeaders.ORIGIN); + String origin = request.getHeaders().getOrigin(); if (allowedOrigins.contains("*") && (allowCredentials == null || !allowCredentials)) { - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN, "*"); + response.getHeaders().setAccessControlAllowOrigin("*"); return; } - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN, origin); - response.addHeader(HttpHeaders.VARY, HttpHeaders.ORIGIN); + response.getHeaders().setAccessControlAllowOrigin(origin); + response.getHeaders().add(HttpHeaders.VARY, HttpHeaders.ORIGIN); } - private void setAllowMethods(HttpServletRequest request, HttpServletResponse response, + private void setAllowMethods(ServerHttpRequest request, ServerHttpResponse response, List allowedMethods) { if (allowedMethods == null) { allowedMethods = Arrays.asList(HttpMethod.GET.name()); } if (allowedMethods.contains("*")) { - String headerValue = request.getHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD); - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_METHODS, headerValue); + HttpMethod method = request.getHeaders().getAccessControlRequestMethod(); + response.getHeaders().setAccessControlAllowMethods(Arrays.asList(method)); } else { - String headerValue = StringUtils.collectionToCommaDelimitedString(allowedMethods); - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_METHODS, headerValue); + List methods = new ArrayList(); + for (String method : allowedMethods) { + methods.add(HttpMethod.valueOf(method)); + } + response.getHeaders().setAccessControlAllowMethods(methods); } } - private void setAllowHeadersHeader(HttpServletRequest request, HttpServletResponse response, List allowedHeaders) { + private void setAllowHeadersHeader(ServerHttpRequest request, ServerHttpResponse response, + List allowedHeaders) { if ((allowedHeaders != null) && !allowedHeaders.isEmpty()) { - String headerValue = request.getHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS); - String[] requestHeaders = StringUtils.commaDelimitedListToStringArray(headerValue); + List requestHeaders = request.getHeaders().getAccessControlRequestHeaders(); boolean matchAll = allowedHeaders.contains("*"); List matchingHeaders = new ArrayList(); for (String requestHeader : requestHeaders) { @@ -209,28 +238,26 @@ public class DefaultCorsProcessor implements CorsProcessor { } } if (!matchingHeaders.isEmpty()) { - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS, - StringUtils.collectionToCommaDelimitedString(matchingHeaders)); + response.getHeaders().setAccessControlAllowHeaders(matchingHeaders); } } } - private void setExposeHeadersHeader(HttpServletResponse response, List exposedHeaders) { + private void setExposeHeadersHeader(ServerHttpResponse response, List exposedHeaders) { if ((exposedHeaders != null) && !exposedHeaders.isEmpty()) { - response.addHeader(CorsUtils.ACCESS_CONTROL_EXPOSE_HEADERS, - StringUtils.collectionToCommaDelimitedString(exposedHeaders)); + response.getHeaders().setAccessControlExposeHeaders(exposedHeaders); } } - private void setAllowCredentials(HttpServletResponse response, Boolean allowCredentials) { + private void setAllowCredentials(ServerHttpResponse response, Boolean allowCredentials) { if ((allowCredentials != null) && allowCredentials) { - response.addHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); + response.getHeaders().setAccessControlAllowCredentials(allowCredentials); } } - private void setMaxAgeHeader(HttpServletResponse response, Long maxAge) { + private void setMaxAgeHeader(ServerHttpResponse response, Long maxAge) { if (maxAge != null) { - response.addHeader(CorsUtils.ACCESS_CONTROL_MAX_AGE, maxAge.toString()); + response.getHeaders().setAccessControlMaxAge(maxAge); } } diff --git a/spring-web/src/test/java/org/springframework/http/HttpHeadersTests.java b/spring-web/src/test/java/org/springframework/http/HttpHeadersTests.java index c7328fce20b..d33072414a8 100644 --- a/spring-web/src/test/java/org/springframework/http/HttpHeadersTests.java +++ b/spring-web/src/test/java/org/springframework/http/HttpHeadersTests.java @@ -32,12 +32,16 @@ import java.util.TimeZone; import org.hamcrest.Matchers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import org.junit.Before; import org.junit.Test; /** * Unit tests for {@link org.springframework.http.HttpHeaders}. * @author Arjen Poutsma + * @author Sebastien Deleuze */ public class HttpHeadersTests { @@ -267,4 +271,70 @@ public class HttpHeadersTests { assertThat(headers.getAllow(), Matchers.emptyCollectionOf(HttpMethod.class)); } + @Test + public void accessControlAllowCredentials() { + assertFalse(headers.getAccessControlAllowCredentials()); + headers.setAccessControlAllowCredentials(false); + assertFalse(headers.getAccessControlAllowCredentials()); + headers.setAccessControlAllowCredentials(true); + assertTrue(headers.getAccessControlAllowCredentials()); + } + + @Test + public void accessControlAllowHeaders() { + List allowedHeaders = headers.getAccessControlAllowHeaders(); + assertThat(allowedHeaders, Matchers.emptyCollectionOf(String.class)); + headers.setAccessControlAllowHeaders(Arrays.asList("header1", "header2")); + allowedHeaders = headers.getAccessControlAllowHeaders(); + assertEquals(allowedHeaders, Arrays.asList("header1", "header2")); + } + + @Test + public void accessControlAllowMethods() { + List allowedMethods = headers.getAccessControlAllowMethods(); + assertThat(allowedMethods, Matchers.emptyCollectionOf(HttpMethod.class)); + headers.setAccessControlAllowMethods(Arrays.asList(HttpMethod.GET, HttpMethod.POST)); + allowedMethods = headers.getAccessControlAllowMethods(); + assertEquals(allowedMethods, Arrays.asList(HttpMethod.GET, HttpMethod.POST)); + } + + @Test + public void accessControlAllowOrigin() { + assertNull(headers.getAccessControlAllowOrigin()); + headers.setAccessControlAllowOrigin("*"); + assertEquals("*", headers.getAccessControlAllowOrigin()); + } + + @Test + public void accessControlExposeHeaders() { + List exposedHeaders = headers.getAccessControlExposeHeaders(); + assertThat(exposedHeaders, Matchers.emptyCollectionOf(String.class)); + headers.setAccessControlExposeHeaders(Arrays.asList("header1", "header2")); + exposedHeaders = headers.getAccessControlExposeHeaders(); + assertEquals(exposedHeaders, Arrays.asList("header1", "header2")); + } + + @Test + public void accessControlMaxAge() { + assertEquals(-1, headers.getAccessControlMaxAge()); + headers.setAccessControlMaxAge(3600); + assertEquals(3600, headers.getAccessControlMaxAge()); + } + + @Test + public void accessControlRequestHeaders() { + List requestHeaders = headers.getAccessControlRequestHeaders(); + assertThat(requestHeaders, Matchers.emptyCollectionOf(String.class)); + headers.setAccessControlRequestHeaders(Arrays.asList("header1", "header2")); + requestHeaders = headers.getAccessControlRequestHeaders(); + assertEquals(requestHeaders, Arrays.asList("header1", "header2")); + } + + @Test + public void accessControlRequestMethod() { + assertNull(headers.getAccessControlRequestMethod()); + headers.setAccessControlRequestMethod(HttpMethod.POST); + assertEquals(HttpMethod.POST, headers.getAccessControlRequestMethod()); + } + } diff --git a/spring-web/src/test/java/org/springframework/web/cors/CorsUtilsTests.java b/spring-web/src/test/java/org/springframework/web/cors/CorsUtilsTests.java index 6b03d448e78..8ec59b964b9 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/CorsUtilsTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/CorsUtilsTests.java @@ -48,7 +48,7 @@ public class CorsUtilsTests { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("OPTIONS"); request.addHeader(HttpHeaders.ORIGIN, "http://domain.com"); - request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); assertTrue(CorsUtils.isPreFlightRequest(request)); } @@ -62,7 +62,7 @@ public class CorsUtilsTests { assertFalse(CorsUtils.isPreFlightRequest(request)); request = new MockHttpServletRequest(); - request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); assertFalse(CorsUtils.isPreFlightRequest(request)); } 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 6d6fe9ad9c5..e0ee8efedf2 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 @@ -62,7 +62,7 @@ public class DefaultCorsProcessorTests { this.request.setMethod(HttpMethod.GET.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); this.processor.processActualRequest(this.conf, request, response); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @@ -72,10 +72,10 @@ public class DefaultCorsProcessorTests { this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); this.conf.addAllowedOrigin("*"); this.processor.processActualRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("*", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_MAX_AGE)); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_EXPOSE_HEADERS)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("*", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -88,10 +88,10 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("http://domain2.com/logout.html"); this.conf.setAllowCredentials(true); this.processor.processActualRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("http://domain2.com/test.html", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); - assertEquals("true", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("http://domain2.com/test.html", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals("true", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -102,10 +102,10 @@ public class DefaultCorsProcessorTests { this.conf.addAllowedOrigin("*"); this.conf.setAllowCredentials(true); this.processor.processActualRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("http://domain2.com/test.html", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); - assertEquals("true", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("http://domain2.com/test.html", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals("true", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -115,7 +115,7 @@ public class DefaultCorsProcessorTests { this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); this.conf.addAllowedOrigin("http://domain2.com/TEST.html"); this.processor.processActualRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -127,11 +127,11 @@ public class DefaultCorsProcessorTests { this.conf.addExposedHeader("header2"); this.conf.addAllowedOrigin("http://domain2.com/test.html"); this.processor.processActualRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("http://domain2.com/test.html", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_EXPOSE_HEADERS)); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1")); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2")); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("http://domain2.com/test.html", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS)); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1")); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2")); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -139,7 +139,7 @@ public class DefaultCorsProcessorTests { public void preflightRequestAllOriginsAllowed() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedOrigin("*"); this.processor.processPreFlightRequest(this.conf, request, response); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); @@ -149,7 +149,7 @@ public class DefaultCorsProcessorTests { public void preflightRequestWrongAllowedMethod() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "DELETE"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "DELETE"); this.conf.addAllowedOrigin("*"); this.processor.processPreFlightRequest(this.conf, request, response); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); @@ -159,17 +159,17 @@ public class DefaultCorsProcessorTests { public void preflightRequestMatchedAllowedMethod() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedOrigin("*"); this.processor.processPreFlightRequest(this.conf, request, response); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); - assertEquals("GET", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_METHODS)); + assertEquals("GET", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); } @Test(expected = IllegalArgumentException.class) public void preflightRequestWithoutOriginHeader() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.processor.processPreFlightRequest(this.conf, request, response); } @@ -178,7 +178,7 @@ public class DefaultCorsProcessorTests { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); this.processor.processPreFlightRequest(this.conf, request, response); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @@ -186,9 +186,9 @@ public class DefaultCorsProcessorTests { public void preflightRequestWithoutRequestMethod() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); this.processor.processPreFlightRequest(this.conf, request, response); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @@ -196,10 +196,10 @@ public class DefaultCorsProcessorTests { public void preflightRequestWithRequestAndMethodHeaderButNoConfig() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.processor.processPreFlightRequest(this.conf, request, response); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @@ -207,19 +207,19 @@ public class DefaultCorsProcessorTests { public void preflightRequestValidRequestAndConfig() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedOrigin("*"); this.conf.addAllowedMethod("GET"); this.conf.addAllowedMethod("PUT"); this.conf.addAllowedHeader("header1"); this.conf.addAllowedHeader("header2"); this.processor.processPreFlightRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("*", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_METHODS)); - assertEquals("GET,PUT", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_METHODS)); - assertFalse(response.containsHeader(CorsUtils.ACCESS_CONTROL_MAX_AGE)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("*", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); + assertEquals("GET,PUT", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)); + assertFalse(response.containsHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -227,18 +227,18 @@ public class DefaultCorsProcessorTests { public void preflightRequestCrendentials() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedOrigin("http://domain2.com/home.html"); this.conf.addAllowedOrigin("http://domain2.com/test.html"); this.conf.addAllowedOrigin("http://domain2.com/logout.html"); this.conf.addAllowedHeader("Header1"); this.conf.setAllowCredentials(true); this.processor.processPreFlightRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("http://domain2.com/test.html", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); - assertEquals("true", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("http://domain2.com/test.html", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); + assertEquals("true", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -246,16 +246,16 @@ public class DefaultCorsProcessorTests { public void preflightRequestCrendentialsWithOriginWildcard() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedOrigin("http://domain2.com/home.html"); this.conf.addAllowedOrigin("*"); this.conf.addAllowedOrigin("http://domain2.com/logout.html"); this.conf.addAllowedHeader("Header1"); this.conf.setAllowCredentials(true); this.processor.processPreFlightRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertEquals("http://domain2.com/test.html", response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertEquals("http://domain2.com/test.html", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -263,18 +263,18 @@ public class DefaultCorsProcessorTests { public void preflightRequestAllowedHeaders() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedHeader("Header1"); this.conf.addAllowedHeader("Header2"); this.conf.addAllowedHeader("Header3"); this.conf.addAllowedOrigin("http://domain2.com/test.html"); this.processor.processPreFlightRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS)); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); - assertFalse(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3")); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS)); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); + assertFalse(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3")); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } @@ -282,16 +282,16 @@ public class DefaultCorsProcessorTests { public void preflightRequestAllowsAllHeaders() throws Exception { this.request.setMethod(HttpMethod.OPTIONS.name()); this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com/test.html"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2"); - this.request.addHeader(CorsUtils.ACCESS_CONTROL_REQUEST_METHOD, "GET"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2"); + this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.conf.addAllowedHeader("*"); this.conf.addAllowedOrigin("http://domain2.com/test.html"); this.processor.processPreFlightRequest(this.conf, request, response); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_ORIGIN)); - assertTrue(response.containsHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS)); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); - assertTrue(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); - assertFalse(response.getHeader(CorsUtils.ACCESS_CONTROL_ALLOW_HEADERS).contains("*")); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + assertTrue(response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS)); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1")); + assertTrue(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2")); + assertFalse(response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("*")); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java index 4d03ab3cfa2..92760b955de 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java @@ -20,6 +20,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; +import org.springframework.http.HttpHeaders; import org.springframework.util.PathMatcher; import org.springframework.util.StringUtils; import org.springframework.web.accept.ContentNegotiationManager; @@ -245,7 +246,7 @@ public final class RequestMappingInfo implements RequestCondition