diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml index e8970daf54..2374d6be5f 100644 --- a/spring-boot-project/spring-boot-dependencies/pom.xml +++ b/spring-boot-project/spring-boot-dependencies/pom.xml @@ -107,7 +107,7 @@ 2.9.3 2.27 6.3.1 - 9.4.19.v20190610 + 9.4.21.v20190926 2.2.0.v201112011158 8.5.40 1.0.3 diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java index 1a96431bad..2bdde164a6 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedErrorHandler.java @@ -18,14 +18,13 @@ package org.springframework.boot.web.embedded.jetty; import java.io.IOException; -import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.ErrorHandler; +import org.eclipse.jetty.server.handler.ErrorHandler.ErrorPageMapper; /** * Variation of Jetty's {@link ErrorHandler} that supports all {@link HttpMethod @@ -36,7 +35,7 @@ import org.eclipse.jetty.server.handler.ErrorHandler; * * @author Phillip Webb */ -class JettyEmbeddedErrorHandler extends ErrorHandler { +class JettyEmbeddedErrorHandler extends ErrorHandler implements ErrorPageMapper { private final ErrorHandler delegate; @@ -47,32 +46,20 @@ class JettyEmbeddedErrorHandler extends ErrorHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - String method = request.getMethod(); - if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.HEAD.is(method)) { - request = new ErrorHttpServletRequest(request); - } this.delegate.handle(target, baseRequest, request, response); } - private static class ErrorHttpServletRequest extends HttpServletRequestWrapper { - - private boolean simulateGetMethod = true; - - ErrorHttpServletRequest(HttpServletRequest request) { - super(request); - } - - @Override - public String getMethod() { - return (this.simulateGetMethod ? HttpMethod.GET.toString() : super.getMethod()); - } + @Override + public boolean errorPageForMethod(String method) { + return true; + } - @Override - public ServletContext getServletContext() { - this.simulateGetMethod = false; - return super.getServletContext(); + @Override + public String getErrorPage(HttpServletRequest request) { + if (this.delegate instanceof ErrorPageMapper) { + return ((ErrorPageMapper) this.delegate).getErrorPage(request); } - + return null; } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedLegacyErrorHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedLegacyErrorHandler.java new file mode 100644 index 0000000000..b005c286c9 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyEmbeddedLegacyErrorHandler.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.embedded.jetty; + +import java.io.IOException; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.ErrorHandler; + +/** + * Variation of Jetty's {@link ErrorHandler} that supports all {@link HttpMethod + * HttpMethods} rather than just {@code GET}, {@code POST} and {@code HEAD}. Jetty + * intentionally only + * supports a limited set of HTTP methods for error pages, however, Spring Boot + * prefers Tomcat, Jetty and Undertow to all behave in the same way. + * + * @author Phillip Webb + * @deprecated As of 2.2.0 in favor of {@link JettyEmbeddedErrorHandler} due to error + * handling changes in Jetty 9.4.21.v20190926 + */ +@Deprecated +class JettyEmbeddedLegacyErrorHandler extends ErrorHandler { + + private final ErrorHandler delegate; + + JettyEmbeddedLegacyErrorHandler(ErrorHandler delegate) { + this.delegate = delegate; + } + + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + throws IOException { + String method = request.getMethod(); + if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.HEAD.is(method)) { + request = new ErrorHttpServletRequest(request); + } + this.delegate.handle(target, baseRequest, request, response); + } + + private static class ErrorHttpServletRequest extends HttpServletRequestWrapper { + + private boolean simulateGetMethod = true; + + ErrorHttpServletRequest(HttpServletRequest request) { + super(request); + } + + @Override + public String getMethod() { + return (this.simulateGetMethod ? HttpMethod.GET.toString() : super.getMethod()); + } + + @Override + public ServletContext getServletContext() { + this.simulateGetMethod = false; + return super.getServletContext(); + } + + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java index 8f7b2ca124..a4cec9f0f1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java @@ -19,6 +19,7 @@ package org.springframework.boot.web.embedded.jetty; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URL; @@ -62,6 +63,7 @@ import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -340,10 +342,20 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor @Override public void configure(WebAppContext context) throws Exception { ErrorHandler errorHandler = context.getErrorHandler(); - context.setErrorHandler(new JettyEmbeddedErrorHandler(errorHandler)); + context.setErrorHandler(wrapErrorHandler(errorHandler)); addJettyErrorPages(errorHandler, getErrorPages()); } + @SuppressWarnings("deprecation") + private ErrorHandler wrapErrorHandler(ErrorHandler errorHandler) { + Method method = ReflectionUtils.findMethod(ErrorHandler.class, "errorPageForMethod", String.class); + // Versions prior to 9.4.21.v20190926 have different error handling + if (method == null) { + return new JettyEmbeddedLegacyErrorHandler(errorHandler); + } + return new JettyEmbeddedErrorHandler(errorHandler); + } + }; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index e2adea25c3..18fbb79890 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -1073,7 +1073,6 @@ public abstract class AbstractServletWebServerFactoryTests { HttpComponentsClientHttpRequestFactory requestFactory, String... headers) throws IOException, URISyntaxException { ClientHttpRequest request = requestFactory.createRequest(new URI(url), method); - request.getHeaders().add("Cookie", "JSESSIONID=" + "123"); for (String header : headers) { String[] parts = header.split(":"); request.getHeaders().add(parts[0], parts[1]);