Consistent HttpMethod identity comparisons
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -61,7 +61,6 @@ public class HttpHandlerConnector implements ClientHttpConnector {
|
|||||||
|
|
||||||
private static Log logger = LogFactory.getLog(HttpHandlerConnector.class);
|
private static Log logger = LogFactory.getLog(HttpHandlerConnector.class);
|
||||||
|
|
||||||
|
|
||||||
private final HttpHandler handler;
|
private final HttpHandler handler;
|
||||||
|
|
||||||
|
|
||||||
@@ -118,8 +117,7 @@ public class HttpHandlerConnector implements ClientHttpConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ServerHttpResponse prepareResponse(ServerHttpResponse response, ServerHttpRequest request) {
|
private ServerHttpResponse prepareResponse(ServerHttpResponse response, ServerHttpRequest request) {
|
||||||
return HttpMethod.HEAD.equals(request.getMethod()) ?
|
return (request.getMethod() == HttpMethod.HEAD ? new HttpHeadResponseDecorator(response) : response);
|
||||||
new HttpHeadResponseDecorator(response) : response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientHttpResponse adaptResponse(MockServerHttpResponse response, Flux<DataBuffer> body) {
|
private ClientHttpResponse adaptResponse(MockServerHttpResponse response, Flux<DataBuffer> body) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -81,7 +81,7 @@ final class SimpleBufferingAsyncClientHttpRequest extends AbstractBufferingAsync
|
|||||||
public ClientHttpResponse call() throws Exception {
|
public ClientHttpResponse call() throws Exception {
|
||||||
SimpleBufferingClientHttpRequest.addHeaders(connection, headers);
|
SimpleBufferingClientHttpRequest.addHeaders(connection, headers);
|
||||||
// JDK <1.8 doesn't support getOutputStream with HTTP DELETE
|
// JDK <1.8 doesn't support getOutputStream with HTTP DELETE
|
||||||
if (HttpMethod.DELETE == getMethod() && bufferedOutput.length == 0) {
|
if (getMethod() == HttpMethod.DELETE && bufferedOutput.length == 0) {
|
||||||
connection.setDoOutput(false);
|
connection.setDoOutput(false);
|
||||||
}
|
}
|
||||||
if (connection.getDoOutput() && outputStreaming) {
|
if (connection.getDoOutput() && outputStreaming) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -69,7 +69,7 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp
|
|||||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
||||||
addHeaders(this.connection, headers);
|
addHeaders(this.connection, headers);
|
||||||
// JDK <1.8 doesn't support getOutputStream with HTTP DELETE
|
// JDK <1.8 doesn't support getOutputStream with HTTP DELETE
|
||||||
if (HttpMethod.DELETE == getMethod() && bufferedOutput.length == 0) {
|
if (getMethod() == HttpMethod.DELETE && bufferedOutput.length == 0) {
|
||||||
this.connection.setDoOutput(false);
|
this.connection.setDoOutput(false);
|
||||||
}
|
}
|
||||||
if (this.connection.getDoOutput() && this.outputStreaming) {
|
if (this.connection.getDoOutput() && this.outputStreaming) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,12 +20,12 @@ import java.net.URISyntaxException;
|
|||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.ipc.netty.http.server.HttpServerRequest;
|
import reactor.ipc.netty.http.server.HttpServerRequest;
|
||||||
import reactor.ipc.netty.http.server.HttpServerResponse;
|
import reactor.ipc.netty.http.server.HttpServerResponse;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@@ -67,7 +67,7 @@ public class ReactorHttpHandlerAdapter
|
|||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HttpMethod.HEAD.equals(adaptedRequest.getMethod())) {
|
if (adaptedRequest.getMethod() == HttpMethod.HEAD) {
|
||||||
adaptedResponse = new HttpHeadResponseDecorator(adaptedResponse);
|
adaptedResponse = new HttpHeadResponseDecorator(adaptedResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
|||||||
ServerHttpRequest httpRequest = createRequest(((HttpServletRequest) request), asyncContext);
|
ServerHttpRequest httpRequest = createRequest(((HttpServletRequest) request), asyncContext);
|
||||||
ServerHttpResponse httpResponse = createResponse(((HttpServletResponse) response), asyncContext);
|
ServerHttpResponse httpResponse = createResponse(((HttpServletResponse) response), asyncContext);
|
||||||
|
|
||||||
if (HttpMethod.HEAD.equals(httpRequest.getMethod())) {
|
if (httpRequest.getMethod() == HttpMethod.HEAD) {
|
||||||
httpResponse = new HttpHeadResponseDecorator(httpResponse);
|
httpResponse = new HttpHeadResponseDecorator(httpResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,7 +19,6 @@ package org.springframework.http.server.reactive;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
@@ -66,11 +65,10 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(HttpServerExchange exchange) throws Exception {
|
public void handleRequest(HttpServerExchange exchange) throws Exception {
|
||||||
|
|
||||||
ServerHttpRequest request = new UndertowServerHttpRequest(exchange, getDataBufferFactory());
|
ServerHttpRequest request = new UndertowServerHttpRequest(exchange, getDataBufferFactory());
|
||||||
ServerHttpResponse response = new UndertowServerHttpResponse(exchange, getDataBufferFactory());
|
ServerHttpResponse response = new UndertowServerHttpResponse(exchange, getDataBufferFactory());
|
||||||
|
|
||||||
if (HttpMethod.HEAD.equals(request.getMethod())) {
|
if (request.getMethod() == HttpMethod.HEAD) {
|
||||||
response = new HttpHeadResponseDecorator(response);
|
response = new HttpHeadResponseDecorator(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +81,6 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
|
|||||||
|
|
||||||
private final HttpServerExchange exchange;
|
private final HttpServerExchange exchange;
|
||||||
|
|
||||||
|
|
||||||
public HandlerResultSubscriber(HttpServerExchange exchange) {
|
public HandlerResultSubscriber(HttpServerExchange exchange) {
|
||||||
this.exchange = exchange;
|
this.exchange = exchange;
|
||||||
}
|
}
|
||||||
@@ -95,7 +92,7 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(Void aVoid) {
|
public void onNext(Void aVoid) {
|
||||||
// no op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -106,8 +103,8 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
|
|||||||
logger.debug("Closing connection");
|
logger.debug("Closing connection");
|
||||||
this.exchange.getConnection().close();
|
this.exchange.getConnection().close();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException ex2) {
|
||||||
// Ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -123,4 +120,5 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
|
|||||||
this.exchange.endExchange();
|
this.exchange.endExchange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public abstract class CorsUtils {
|
|||||||
* Returns {@code true} if the request is a valid CORS pre-flight one.
|
* Returns {@code true} if the request is a valid CORS pre-flight one.
|
||||||
*/
|
*/
|
||||||
public static boolean isPreFlightRequest(ServerHttpRequest request) {
|
public static boolean isPreFlightRequest(ServerHttpRequest request) {
|
||||||
return (isCorsRequest(request) && HttpMethod.OPTIONS == request.getMethod() &&
|
return (request.getMethod() == HttpMethod.OPTIONS && isCorsRequest(request) &&
|
||||||
request.getHeaders().get(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
|
request.getHeaders().get(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ public abstract class CorsUtils {
|
|||||||
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
|
* {@code Forwarded}, {@code X-Forwarded-Proto}, {@code X-Forwarded-Host} and
|
||||||
* @code X-Forwarded-Port} headers.
|
* @code X-Forwarded-Port} headers.
|
||||||
* @return {@code true} if the request is a same-origin one, {@code false} in case
|
* @return {@code true} if the request is a same-origin one, {@code false} in case
|
||||||
* of cross-origin request.
|
* of a cross-origin request
|
||||||
*/
|
*/
|
||||||
public static boolean isSameOrigin(ServerHttpRequest request) {
|
public static boolean isSameOrigin(ServerHttpRequest request) {
|
||||||
String origin = request.getHeaders().getOrigin();
|
String origin = request.getHeaders().getOrigin();
|
||||||
@@ -67,7 +67,8 @@ public abstract class CorsUtils {
|
|||||||
Assert.notNull(actualHost, "Actual request host must not be null");
|
Assert.notNull(actualHost, "Actual request host must not be null");
|
||||||
Assert.isTrue(actualPort != -1, "Actual request port must not be undefined");
|
Assert.isTrue(actualPort != -1, "Actual request port must not be undefined");
|
||||||
UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build();
|
UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build();
|
||||||
return (actualHost.equals(originUrl.getHost()) && actualPort == getPort(originUrl.getScheme(), originUrl.getPort()));
|
return (actualHost.equals(originUrl.getHost()) &&
|
||||||
|
actualPort == getPort(originUrl.getScheme(), originUrl.getPort()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getPort(@Nullable String scheme, int port) {
|
private static int getPort(@Nullable String scheme, int port) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -46,6 +46,7 @@ public class HttpPutFormContentFilterTests {
|
|||||||
|
|
||||||
private MockFilterChain filterChain;
|
private MockFilterChain filterChain;
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
filter = new HttpPutFormContentFilter();
|
filter = new HttpPutFormContentFilter();
|
||||||
@@ -56,6 +57,7 @@ public class HttpPutFormContentFilterTests {
|
|||||||
filterChain = new MockFilterChain();
|
filterChain = new MockFilterChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void wrapPutAndPatchOnly() throws Exception {
|
public void wrapPutAndPatchOnly() throws Exception {
|
||||||
request.setContent("foo=bar".getBytes("ISO-8859-1"));
|
request.setContent("foo=bar".getBytes("ISO-8859-1"));
|
||||||
@@ -63,7 +65,7 @@ public class HttpPutFormContentFilterTests {
|
|||||||
request.setMethod(method.name());
|
request.setMethod(method.name());
|
||||||
filterChain = new MockFilterChain();
|
filterChain = new MockFilterChain();
|
||||||
filter.doFilter(request, response, filterChain);
|
filter.doFilter(request, response, filterChain);
|
||||||
if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PATCH)) {
|
if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
|
||||||
assertNotSame("Should wrap HTTP method " + method, request, filterChain.getRequest());
|
assertNotSame("Should wrap HTTP method " + method, request, filterChain.getRequest());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -204,7 +206,7 @@ public class HttpPutFormContentFilterTests {
|
|||||||
assertArrayEquals(new String[] {"value4"}, parameters.get("name4"));
|
assertArrayEquals(new String[] {"value4"}, parameters.get("name4"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-15835
|
@Test // SPR-15835
|
||||||
public void hiddenHttpMethodFilterFollowedByHttpPutFormContentFilter() throws Exception {
|
public void hiddenHttpMethodFilterFollowedByHttpPutFormContentFilter() throws Exception {
|
||||||
request.addParameter("_method", "PUT");
|
request.addParameter("_method", "PUT");
|
||||||
request.addParameter("hiddenField", "testHidden");
|
request.addParameter("hiddenField", "testHidden");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -45,7 +45,6 @@ import org.springframework.web.server.ServerWebInputException;
|
|||||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||||
import org.springframework.web.util.pattern.PathPattern;
|
import org.springframework.web.util.pattern.PathPattern;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for classes for which {@link RequestMappingInfo} defines
|
* Abstract base class for classes for which {@link RequestMappingInfo} defines
|
||||||
* the mapping between a request and a handler method.
|
* the mapping between a request and a handler method.
|
||||||
@@ -358,7 +357,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
|||||||
private static Set<HttpMethod> initAllowedHttpMethods(Set<HttpMethod> declaredMethods) {
|
private static Set<HttpMethod> initAllowedHttpMethods(Set<HttpMethod> declaredMethods) {
|
||||||
if (declaredMethods.isEmpty()) {
|
if (declaredMethods.isEmpty()) {
|
||||||
return EnumSet.allOf(HttpMethod.class).stream()
|
return EnumSet.allOf(HttpMethod.class).stream()
|
||||||
.filter(method -> !method.equals(HttpMethod.TRACE))
|
.filter(method -> method != HttpMethod.TRACE)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -29,16 +29,8 @@ import org.springframework.mock.web.test.server.MockServerWebExchange;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.springframework.web.bind.annotation.RequestMethod.*;
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link RequestMethodsRequestCondition}.
|
* Unit tests for {@link RequestMethodsRequestCondition}.
|
||||||
@@ -67,7 +59,7 @@ public class RequestMethodsRequestConditionTests {
|
|||||||
public void getMatchingConditionWithEmptyConditions() throws Exception {
|
public void getMatchingConditionWithEmptyConditions() throws Exception {
|
||||||
RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();
|
RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();
|
||||||
for (RequestMethod method : RequestMethod.values()) {
|
for (RequestMethod method : RequestMethod.values()) {
|
||||||
if (!OPTIONS.equals(method)) {
|
if (method != OPTIONS) {
|
||||||
ServerWebExchange exchange = getExchange(method.name());
|
ServerWebExchange exchange = getExchange(method.name());
|
||||||
assertNotNull(condition.getMatchingCondition(exchange));
|
assertNotNull(condition.getMatchingCondition(exchange));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -848,7 +848,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
|||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
|
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
|
||||||
if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
|
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
|
||||||
processRequest(request, response);
|
processRequest(request, response);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -434,16 +434,16 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
|||||||
Set<HttpMethod> result = new LinkedHashSet<>(declaredMethods.size());
|
Set<HttpMethod> result = new LinkedHashSet<>(declaredMethods.size());
|
||||||
if (declaredMethods.isEmpty()) {
|
if (declaredMethods.isEmpty()) {
|
||||||
for (HttpMethod method : HttpMethod.values()) {
|
for (HttpMethod method : HttpMethod.values()) {
|
||||||
if (!HttpMethod.TRACE.equals(method)) {
|
if (method != HttpMethod.TRACE) {
|
||||||
result.add(method);
|
result.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
boolean hasHead = declaredMethods.contains("HEAD");
|
|
||||||
for (String method : declaredMethods) {
|
for (String method : declaredMethods) {
|
||||||
result.add(HttpMethod.valueOf(method));
|
HttpMethod httpMethod = HttpMethod.valueOf(method);
|
||||||
if (!hasHead && "GET".equals(method)) {
|
result.add(httpMethod);
|
||||||
|
if (httpMethod == HttpMethod.GET) {
|
||||||
result.add(HttpMethod.HEAD);
|
result.add(HttpMethod.HEAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -174,7 +174,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
|||||||
if (this.supportedMethods == null) {
|
if (this.supportedMethods == null) {
|
||||||
allowedMethods = new ArrayList<>(HttpMethod.values().length - 1);
|
allowedMethods = new ArrayList<>(HttpMethod.values().length - 1);
|
||||||
for (HttpMethod method : HttpMethod.values()) {
|
for (HttpMethod method : HttpMethod.values()) {
|
||||||
if (!HttpMethod.TRACE.equals(method)) {
|
if (method != HttpMethod.TRACE) {
|
||||||
allowedMethods.add(method.name());
|
allowedMethods.add(method.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,13 +191,13 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the "Allow" header value to use in response to an HTTP OPTIONS
|
* Return the "Allow" header value to use in response to an HTTP OPTIONS request
|
||||||
* request based on the configured {@link #setSupportedMethods supported
|
* based on the configured {@link #setSupportedMethods supported methods} also
|
||||||
* methods} also automatically adding "OPTIONS" to the list even if not
|
* automatically adding "OPTIONS" to the list even if not present as a supported
|
||||||
* present as a supported method. This means sub-classes don't have to
|
* method. This means subclasses don't have to explicitly list "OPTIONS" as a
|
||||||
* explicitly list "OPTIONS" as a supported method as long as HTTP OPTIONS
|
* supported method as long as HTTP OPTIONS requests are handled before making a
|
||||||
* requests are handled before making a call to
|
* call to {@link #checkRequest(HttpServletRequest)}.
|
||||||
* {@link #checkRequest(HttpServletRequest)}.
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected String getAllowHeader() {
|
protected String getAllowHeader() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.springframework.web.servlet.mvc.condition;
|
package org.springframework.web.servlet.mvc.condition;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@@ -27,17 +26,8 @@ import org.springframework.http.HttpHeaders;
|
|||||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.springframework.web.bind.annotation.RequestMethod.*;
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
@@ -63,7 +53,7 @@ public class RequestMethodsRequestConditionTests {
|
|||||||
public void getMatchingConditionWithEmptyConditions() {
|
public void getMatchingConditionWithEmptyConditions() {
|
||||||
RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();
|
RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();
|
||||||
for (RequestMethod method : RequestMethod.values()) {
|
for (RequestMethod method : RequestMethod.values()) {
|
||||||
if (!OPTIONS.equals(method)) {
|
if (method != OPTIONS) {
|
||||||
HttpServletRequest request = new MockHttpServletRequest(method.name(), "");
|
HttpServletRequest request = new MockHttpServletRequest(method.name(), "");
|
||||||
assertNotNull(condition.getMatchingCondition(request));
|
assertNotNull(condition.getMatchingCondition(request));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.web.servlet.mvc.method;
|
package org.springframework.web.servlet.mvc.method;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -26,7 +23,6 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -63,6 +59,8 @@ import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
|||||||
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
|
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test fixture with {@link RequestMappingInfoHandlerMapping}.
|
* Test fixture with {@link RequestMappingInfoHandlerMapping}.
|
||||||
@@ -157,9 +155,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-9603
|
@Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-9603
|
||||||
|
|
||||||
@Test(expected = HttpMediaTypeNotAcceptableException.class)
|
|
||||||
public void getHandlerRequestMethodMatchFalsePositive() throws Exception {
|
public void getHandlerRequestMethodMatchFalsePositive() throws Exception {
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/users");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/users");
|
||||||
request.addHeader("Accept", "application/xml");
|
request.addHeader("Accept", "application/xml");
|
||||||
@@ -167,9 +163,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
this.handlerMapping.getHandler(request);
|
this.handlerMapping.getHandler(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-8462
|
@Test // SPR-8462
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getHandlerMediaTypeNotSupported() throws Exception {
|
public void getHandlerMediaTypeNotSupported() throws Exception {
|
||||||
testHttpMediaTypeNotSupportedException("/person/1");
|
testHttpMediaTypeNotSupportedException("/person/1");
|
||||||
testHttpMediaTypeNotSupportedException("/person/1/");
|
testHttpMediaTypeNotSupportedException("/person/1/");
|
||||||
@@ -197,18 +191,14 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-8462
|
@Test // SPR-8462
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getHandlerMediaTypeNotAccepted() throws Exception {
|
public void getHandlerMediaTypeNotAccepted() throws Exception {
|
||||||
testHttpMediaTypeNotAcceptableException("/persons");
|
testHttpMediaTypeNotAcceptableException("/persons");
|
||||||
testHttpMediaTypeNotAcceptableException("/persons/");
|
testHttpMediaTypeNotAcceptableException("/persons/");
|
||||||
testHttpMediaTypeNotAcceptableException("/persons.json");
|
testHttpMediaTypeNotAcceptableException("/persons.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-12854
|
@Test // SPR-12854
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getHandlerUnsatisfiedServletRequestParameterException() throws Exception {
|
public void getHandlerUnsatisfiedServletRequestParameterException() throws Exception {
|
||||||
try {
|
try {
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/params");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/params");
|
||||||
@@ -275,10 +265,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
assertEquals("2", uriVariables.get("path2"));
|
assertEquals("2", uriVariables.get("path2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-9098
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test // SPR-9098
|
||||||
public void handleMatchUriTemplateVariablesDecode() {
|
public void handleMatchUriTemplateVariablesDecode() {
|
||||||
RequestMappingInfo key = RequestMappingInfo.paths("/{group}/{identifier}").build();
|
RequestMappingInfo key = RequestMappingInfo.paths("/{group}/{identifier}").build();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/group/a%2Fb");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/group/a%2Fb");
|
||||||
@@ -502,6 +490,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Controller
|
@Controller
|
||||||
private static class UserController {
|
private static class UserController {
|
||||||
@@ -515,6 +504,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingInfoHandlerMapping {
|
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingInfoHandlerMapping {
|
||||||
|
|
||||||
public void registerHandler(Object handler) {
|
public void registerHandler(Object handler) {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -515,7 +514,7 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
|
|||||||
protected void sendMethodNotAllowed(ServerHttpResponse response, HttpMethod... httpMethods) {
|
protected void sendMethodNotAllowed(ServerHttpResponse response, HttpMethod... httpMethods) {
|
||||||
logger.warn("Sending Method Not Allowed (405)");
|
logger.warn("Sending Method Not Allowed (405)");
|
||||||
response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
|
response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
|
||||||
response.getHeaders().setAllow(new HashSet<>(Arrays.asList(httpMethods)));
|
response.getHeaders().setAllow(new LinkedHashSet<>(Arrays.asList(httpMethods)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -545,7 +544,7 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||||
if (HttpMethod.GET == request.getMethod()) {
|
if (request.getMethod() == HttpMethod.GET) {
|
||||||
addNoCacheHeaders(response);
|
addNoCacheHeaders(response);
|
||||||
if (checkOrigin(request, response)) {
|
if (checkOrigin(request, response)) {
|
||||||
response.getHeaders().setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
|
response.getHeaders().setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
|
||||||
@@ -555,14 +554,14 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (HttpMethod.OPTIONS == request.getMethod()) {
|
else if (request.getMethod() == HttpMethod.OPTIONS) {
|
||||||
if (checkOrigin(request, response)) {
|
if (checkOrigin(request, response)) {
|
||||||
addCacheHeaders(response);
|
addCacheHeaders(response);
|
||||||
response.setStatusCode(HttpStatus.NO_CONTENT);
|
response.setStatusCode(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sendMethodNotAllowed(response, HttpMethod.OPTIONS, HttpMethod.GET);
|
sendMethodNotAllowed(response, HttpMethod.GET, HttpMethod.OPTIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -590,7 +589,7 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||||
if (!HttpMethod.GET.equals(request.getMethod())) {
|
if (request.getMethod() != HttpMethod.GET) {
|
||||||
sendMethodNotAllowed(response, HttpMethod.GET);
|
sendMethodNotAllowed(response, HttpMethod.GET);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -252,7 +252,7 @@ public class TransportHandlingSockJsService extends AbstractSockJsService implem
|
|||||||
try {
|
try {
|
||||||
HttpMethod supportedMethod = transportType.getHttpMethod();
|
HttpMethod supportedMethod = transportType.getHttpMethod();
|
||||||
if (supportedMethod != request.getMethod()) {
|
if (supportedMethod != request.getMethod()) {
|
||||||
if (HttpMethod.OPTIONS == request.getMethod() && transportType.supportsCors()) {
|
if (request.getMethod() == HttpMethod.OPTIONS && transportType.supportsCors()) {
|
||||||
if (checkOrigin(request, response, HttpMethod.OPTIONS, supportedMethod)) {
|
if (checkOrigin(request, response, HttpMethod.OPTIONS, supportedMethod)) {
|
||||||
response.setStatusCode(HttpStatus.NO_CONTENT);
|
response.setStatusCode(HttpStatus.NO_CONTENT);
|
||||||
addCacheHeaders(response);
|
addCacheHeaders(response);
|
||||||
|
|||||||
Reference in New Issue
Block a user