From 503a52273e8f24ec73a65977f7f1eefc20d84c9b Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Thu, 8 Aug 2019 20:46:19 +1000 Subject: [PATCH] Jetty 9.4.x fix some part of the code assuming cast to HttpServletRequest is possible (#3945) * code assume request is HttpServletRequest whereas it can be ServletRequestWrapper, this fix some failing tck tests Signed-off-by: olivier lamy * return directly if the instance is already HttpServlet*Wrapper Signed-off-by: olivier lamy * checkstyle Signed-off-by: olivier lamy * changes after review Signed-off-by: olivier lamy * checkstyle Signed-off-by: olivier lamy * checkstyle and cleanup import Signed-off-by: olivier lamy --- .../org/eclipse/jetty/server/Request.java | 16 +++- .../org/eclipse/jetty/server/Response.java | 16 ++++ .../java/org/eclipse/jetty/server/Server.java | 4 +- .../server/ServletRequestWrapperTest.java | 86 +++++++++++++++++++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 jetty-server/src/test/java/org/eclipse/jetty/server/ServletRequestWrapperTest.java diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index c61e637a86f..e8c4b2960f8 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -56,6 +56,7 @@ import javax.servlet.ServletRequestWrapper; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpUpgradeHandler; @@ -2137,7 +2138,7 @@ public class Request implements HttpServletRequest AsyncContextEvent event = new AsyncContextEvent(_context, _async, state, this, servletRequest, servletResponse); event.setDispatchContext(getServletContext()); - String uri = ((HttpServletRequest)servletRequest).getRequestURI(); + String uri = unwrap(servletRequest).getRequestURI(); if (_contextPath != null && uri.startsWith(_contextPath)) uri = uri.substring(_contextPath.length()); else @@ -2149,6 +2150,19 @@ public class Request implements HttpServletRequest return _async; } + public static HttpServletRequest unwrap(ServletRequest servletRequest) + { + if (servletRequest instanceof HttpServletRequestWrapper) + { + return (HttpServletRequestWrapper)servletRequest; + } + if (servletRequest instanceof ServletRequestWrapper) + { + return unwrap(((ServletRequestWrapper)servletRequest).getRequest()); + } + return ((HttpServletRequest)servletRequest); + } + @Override public String toString() { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 87040da3730..1d2f1beeef5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -31,8 +31,11 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import javax.servlet.RequestDispatcher; import javax.servlet.ServletOutputStream; +import javax.servlet.ServletResponse; +import javax.servlet.ServletResponseWrapper; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpSession; import org.eclipse.jetty.http.CookieCompliance; @@ -1281,4 +1284,17 @@ public class Response implements HttpServletResponse response.setHeader(HttpHeader.ETAG.asString(), et); } } + + public static HttpServletResponse unwrap(ServletResponse servletResponse) + { + if (servletResponse instanceof HttpServletResponseWrapper) + { + return (HttpServletResponseWrapper)servletResponse; + } + if (servletResponse instanceof ServletResponseWrapper) + { + return unwrap(((ServletResponseWrapper)servletResponse).getResponse()); + } + return (HttpServletResponse)servletResponse; + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index da2b77e2a72..72ac6bf52b7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -529,8 +529,8 @@ public class Server extends HandlerWrapper implements Attributes } final String target = baseRequest.getPathInfo(); - final HttpServletRequest request = (HttpServletRequest)event.getSuppliedRequest(); - final HttpServletResponse response = (HttpServletResponse)event.getSuppliedResponse(); + final HttpServletRequest request = Request.unwrap(event.getSuppliedRequest()); + final HttpServletResponse response = Response.unwrap(event.getSuppliedResponse()); if (LOG.isDebugEnabled()) LOG.debug("{} {} {} on {}", request.getDispatcherType(), request.getMethod(), target, channel); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServletRequestWrapperTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServletRequestWrapperTest.java new file mode 100644 index 00000000000..1d3a757a9d3 --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServletRequestWrapperTest.java @@ -0,0 +1,86 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server; + +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestWrapper; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + +public class ServletRequestWrapperTest +{ + private Server server; + private LocalConnector connector; + private RequestHandler handler; + + @BeforeEach + public void init() throws Exception + { + server = new Server(); + connector = new LocalConnector(server, new HttpConnectionFactory()); + server.addConnector(connector); + + handler = new RequestHandler(); + server.setHandler(handler); + server.start(); + } + + @Test + public void testServletRequestWrapper() throws Exception + { + String request = "GET / HTTP/1.1\r\n" + + "Host: whatever\r\n" + + "\n"; + + String response = connector.getResponse(request); + assertThat("Response", response, containsString("200")); + } + + private class RequestWrapper extends ServletRequestWrapper + { + public RequestWrapper(ServletRequest request) + { + super(request); + } + } + + private class RequestHandler extends AbstractHandler + { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, + HttpServletResponse response) + throws IOException, ServletException + { + RequestWrapper requestWrapper = new RequestWrapper(request); + AsyncContext context = request.startAsync(requestWrapper, response); + context.complete(); + baseRequest.setHandled(true); + } + } +}