From ea0ce64734a9bc7fe3bf61173d0b45772b3dee09 Mon Sep 17 00:00:00 2001 From: gregw Date: Thu, 16 Jul 2020 15:30:29 +0200 Subject: [PATCH 1/2] Fixes #5057 Included root context path Root context path in include should be empty string. --- .../org/eclipse/jetty/server/Dispatcher.java | 2 +- .../jetty/server/handler/ContextHandler.java | 15 ++- .../jetty/servlet/IncludedServletTest.java | 96 +++++++++++++++++++ 3 files changed, 108 insertions(+), 5 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index acb29717a2c7..89634d9d24e5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -109,7 +109,7 @@ public void include(ServletRequest request, ServletResponse response) throws Ser IncludeAttributes attr = new IncludeAttributes(old_attr); attr._requestURI = _uri.getPath(); - attr._contextPath = _contextHandler.getContextPath(); + attr._contextPath = _contextHandler.getRequestContextPath(); attr._servletPath = null; // set by ServletHandler attr._pathInfo = _pathInContext; attr._query = _uri.getQuery(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index d89a3b861f2f..5fd7e97b4558 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -591,6 +591,16 @@ public String getContextPathEncoded() return _contextPathEncoded; } + /** + * Get the context path in a form suitable to be returned from {@link HttpServletRequest#getContextPath()} + * @return Returns the encoded contextPath, or empty string for root context + */ + public String getRequestContextPath() + { + String contextPath = getContextPathEncoded(); + return "/".equals(contextPath) ? "" : contextPath; + } + /* * @see javax.servlet.ServletContext#getInitParameter(java.lang.String) */ @@ -1267,10 +1277,7 @@ else if (_contextPath.length() == 1) __context.set(_scontext); if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/")) { - if (_contextPath.length() == 1) - baseRequest.setContextPath(""); - else - baseRequest.setContextPath(getContextPathEncoded()); + baseRequest.setContextPath(getRequestContextPath()); baseRequest.setServletPath(null); baseRequest.setPathInfo(pathInfo); } diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java index d1bb0a6ccd11..9fa688675ec1 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.servlet; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -25,8 +26,12 @@ import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -34,6 +39,7 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.toolchain.test.IO; +import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -71,6 +77,45 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se } } + public static class IncludedAttrServlet extends HttpServlet + { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + if (req.getDispatcherType() == DispatcherType.INCLUDE) + { + if (req.getAttribute("included") == null) + { + req.setAttribute("included", Boolean.TRUE); + dumpAttrs("BEFORE1", req, resp.getOutputStream()); + req.getRequestDispatcher("two").include(req, resp); + dumpAttrs("AFTER1", req, resp.getOutputStream()); + } + else + { + dumpAttrs("DURING", req, resp.getOutputStream()); + } + } + else + { + resp.setContentType("text/plain"); + dumpAttrs("BEFORE0", req, resp.getOutputStream()); + req.getRequestDispatcher("one").include(req, resp); + dumpAttrs("AFTER0", req, resp.getOutputStream()); + } + } + + private void dumpAttrs(String tag, HttpServletRequest req, ServletOutputStream out) throws IOException + { + out.println(String.format("%s: %s='%s'", tag, RequestDispatcher.INCLUDE_CONTEXT_PATH, + req.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH))); + out.println(String.format("%s: %s='%s'", tag, RequestDispatcher.INCLUDE_SERVLET_PATH, + req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH))); + out.println(String.format("%s: %s='%s'", tag, RequestDispatcher.INCLUDE_PATH_INFO, + req.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO))); + } + } + private Server server; private URI baseUri; @@ -87,6 +132,7 @@ public void startServer() throws Exception context.setContextPath("/"); context.addServlet(TopServlet.class, "/top"); context.addServlet(IncludedServlet.class, "/included"); + context.addServlet(IncludedAttrServlet.class, "/attr/*"); server.setHandler(context); @@ -173,4 +219,54 @@ private String getPotentialBody(HttpURLConnection connection) IO.close(in); } } + + @Test + public void testIncludeAttributes() throws IOException + { + URI uri = baseUri.resolve("/attr/one"); + System.out.println("GET (String): " + uri.toASCIIString()); + + InputStream in = null; + BufferedReader reader = null; + HttpURLConnection connection = null; + + try + { + connection = (HttpURLConnection)uri.toURL().openConnection(); + connection.connect(); + assertThat(connection.getResponseCode(), is(HttpURLConnection.HTTP_OK)); + in = connection.getInputStream(); + reader = new BufferedReader(new InputStreamReader(in)); + List result = new ArrayList<>(); + String line = reader.readLine(); + while (line != null) + { + result.add(line); + line = reader.readLine(); + } + + assertThat(result, Matchers.contains( + "BEFORE0: javax.servlet.include.context_path='null'", + "BEFORE0: javax.servlet.include.servlet_path='null'", + "BEFORE0: javax.servlet.include.path_info='null'", + "BEFORE1: javax.servlet.include.context_path=''", + "BEFORE1: javax.servlet.include.servlet_path='/attr'", + "BEFORE1: javax.servlet.include.path_info='/one'", + "DURING: javax.servlet.include.context_path=''", + "DURING: javax.servlet.include.servlet_path='/attr'", + "DURING: javax.servlet.include.path_info='/two'", + "AFTER1: javax.servlet.include.context_path=''", + "AFTER1: javax.servlet.include.servlet_path='/attr'", + "AFTER1: javax.servlet.include.path_info='/one'", + "AFTER0: javax.servlet.include.context_path='null'", + "AFTER0: javax.servlet.include.servlet_path='null'", + "AFTER0: javax.servlet.include.path_info='null'" + )); + } + finally + { + IO.close(reader); + IO.close(in); + } + } } From 1fbe47459773a3df5de0bdb7266f8347a109424b Mon Sep 17 00:00:00 2001 From: gregw Date: Mon, 20 Jul 2020 16:01:59 +0200 Subject: [PATCH 2/2] Issue #5057 merged context path methods as result of review. ServletContent.getContextPath now returns the encoded contextPath (if anybody is silly enough to have one). --- .../src/main/java/org/eclipse/jetty/server/Server.java | 2 +- .../eclipse/jetty/server/handler/ContextHandler.java | 10 ++++------ .../org/eclipse/jetty/servlet/IncludedServletTest.java | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) 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 af8bcf1db36e..31fd92146029 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 @@ -528,7 +528,7 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio // this is a dispatch with a path ServletContext context = event.getServletContext(); String query = baseRequest.getQueryString(); - baseRequest.setURIPathQuery(URIUtil.addEncodedPaths(context == null ? null : URIUtil.encodePath(context.getContextPath()), path)); + baseRequest.setURIPathQuery(URIUtil.addEncodedPaths(context == null ? null : context.getContextPath(), path)); HttpURI uri = baseRequest.getHttpURI(); baseRequest.setPathInfo(uri.getDecodedPath()); if (uri.getQuery() != null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 5fd7e97b4558..7960b0fc91ad 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -593,12 +593,13 @@ public String getContextPathEncoded() /** * Get the context path in a form suitable to be returned from {@link HttpServletRequest#getContextPath()} + * or {@link ServletContext#getContextPath()}. * @return Returns the encoded contextPath, or empty string for root context */ public String getRequestContextPath() { - String contextPath = getContextPathEncoded(); - return "/".equals(contextPath) ? "" : contextPath; + String contextPathEncoded = getContextPathEncoded(); + return "/".equals(contextPathEncoded) ? "" : contextPathEncoded; } /* @@ -2425,10 +2426,7 @@ public String getServletContextName() @Override public String getContextPath() { - if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH)) - return ""; - - return _contextPath; + return getRequestContextPath(); } @Override diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java index 9fa688675ec1..56adffae1e61 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/IncludedServletTest.java @@ -224,8 +224,6 @@ private String getPotentialBody(HttpURLConnection connection) public void testIncludeAttributes() throws IOException { URI uri = baseUri.resolve("/attr/one"); - System.out.println("GET (String): " + uri.toASCIIString()); - InputStream in = null; BufferedReader reader = null; HttpURLConnection connection = null;