Apply changes recommended by Jetty team to JettyEmbeddedErrorHandler
Closes gh-18842
This commit is contained in:
@@ -18,20 +18,15 @@ package org.springframework.boot.web.embedded.jetty;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||||
import org.eclipse.jetty.server.handler.ErrorHandler.ErrorPageMapper;
|
|
||||||
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variation of Jetty's {@link ErrorHandler} that supports all {@link HttpMethod
|
* Variation of Jetty's {@link ErrorPageErrorHandler} that supports all {@link HttpMethod
|
||||||
* HttpMethods} rather than just {@code GET}, {@code POST} and {@code HEAD}. By default
|
* HttpMethods} rather than just {@code GET}, {@code POST} and {@code HEAD}. By default
|
||||||
* Jetty <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=446039">intentionally only
|
* Jetty <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=446039">intentionally only
|
||||||
* supports a limited set of HTTP methods</a> for error pages, however, Spring Boot
|
* supports a limited set of HTTP methods</a> for error pages, however, Spring Boot
|
||||||
@@ -40,65 +35,18 @@ import org.springframework.util.ReflectionUtils;
|
|||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Christoph Dreis
|
* @author Christoph Dreis
|
||||||
*/
|
*/
|
||||||
class JettyEmbeddedErrorHandler extends ErrorHandler implements ErrorPageMapper {
|
class JettyEmbeddedErrorHandler extends ErrorPageErrorHandler {
|
||||||
|
|
||||||
static final boolean ERROR_PAGE_FOR_METHOD_AVAILABLE;
|
@Override
|
||||||
|
public boolean errorPageForMethod(String method) {
|
||||||
static {
|
return true;
|
||||||
ERROR_PAGE_FOR_METHOD_AVAILABLE = ReflectionUtils.findMethod(ErrorHandler.class, "errorPageForMethod",
|
|
||||||
String.class) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ErrorHandler delegate;
|
|
||||||
|
|
||||||
JettyEmbeddedErrorHandler(ErrorHandler delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (!ERROR_PAGE_FOR_METHOD_AVAILABLE) {
|
baseRequest.setMethod("GET");
|
||||||
String method = request.getMethod();
|
super.doError(target, baseRequest, request, response);
|
||||||
if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method) && !HttpMethod.HEAD.is(method)) {
|
|
||||||
request = new ErrorHttpServletRequest(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.delegate.handle(target, baseRequest, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean errorPageForMethod(String method) { // Available in Jetty 9.4.21+
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getErrorPage(HttpServletRequest request) {
|
|
||||||
if (this.delegate instanceof ErrorPageMapper) {
|
|
||||||
return ((ErrorPageMapper) this.delegate).getErrorPage(request);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,8 +339,8 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(WebAppContext context) throws Exception {
|
public void configure(WebAppContext context) throws Exception {
|
||||||
ErrorHandler errorHandler = context.getErrorHandler();
|
JettyEmbeddedErrorHandler errorHandler = new JettyEmbeddedErrorHandler();
|
||||||
context.setErrorHandler(new JettyEmbeddedErrorHandler(errorHandler));
|
context.setErrorHandler(errorHandler);
|
||||||
addJettyErrorPages(errorHandler, getErrorPages());
|
addJettyErrorPages(errorHandler, getErrorPages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.boot.web.embedded.jetty;
|
package org.springframework.boot.web.embedded.jetty;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ public class JettyServlet9419WebServerFactoryTests extends AbstractJettyServletW
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void correctVersionOfJettyUsed() {
|
public void correctVersionOfJettyUsed() {
|
||||||
assertThat(JettyEmbeddedErrorHandler.ERROR_PAGE_FOR_METHOD_AVAILABLE).isFalse();
|
assertThat(ErrorHandler.class.getPackage().getImplementationVersion()).isEqualTo("9.4.19.v20190610");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import java.net.InetAddress;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.servlet.ServletContextEvent;
|
import javax.servlet.ServletContextEvent;
|
||||||
import javax.servlet.ServletContextListener;
|
import javax.servlet.ServletContextListener;
|
||||||
@@ -29,6 +31,7 @@ import org.eclipse.jetty.server.Handler;
|
|||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||||
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
@@ -59,7 +62,10 @@ public class JettyServletWebServerFactoryTests extends AbstractJettyServletWebSe
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void correctVersionOfJettyUsed() {
|
public void correctVersionOfJettyUsed() {
|
||||||
assertThat(JettyEmbeddedErrorHandler.ERROR_PAGE_FOR_METHOD_AVAILABLE).isTrue();
|
String jettyVersion = ErrorHandler.class.getPackage().getImplementationVersion();
|
||||||
|
Matcher matcher = Pattern.compile("[0-9]+.[0-9]+.([0-9]+)[\\.-].*").matcher(jettyVersion);
|
||||||
|
assertThat(matcher.find()).isTrue();
|
||||||
|
assertThat(Integer.valueOf(matcher.group(1))).isGreaterThan(19);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user