You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/03/21 17:32:10 UTC

[tomcat] branch 7.0.x updated: https://bz.apache.org/bugzilla/show_bug.cgi?id=63275 enc getContextPath

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/7.0.x by this push:
     new 4d571d6  https://bz.apache.org/bugzilla/show_bug.cgi?id=63275 enc getContextPath
4d571d6 is described below

commit 4d571d6897131f533a3e3ac41ccaebcde3768720
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Mar 21 14:46:14 2019 +0000

    https://bz.apache.org/bugzilla/show_bug.cgi?id=63275 enc getContextPath
    
    When using a RequestDispatcher ensure that
    HttpServletRequest.getContextPath() returns an encoded path in the
    dispatched request.
---
 .../catalina/core/ApplicationDispatcher.java       | 71 +++++++++++-----------
 ...TestApplicationContextGetRequestDispatcher.java | 14 ++++-
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/java/org/apache/catalina/core/ApplicationDispatcher.java b/java/org/apache/catalina/core/ApplicationDispatcher.java
index 49acfd6..8e2bfac 100644
--- a/java/org/apache/catalina/core/ApplicationDispatcher.java
+++ b/java/org/apache/catalina/core/ApplicationDispatcher.java
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You 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
- * 
+ *
  *      http://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.
@@ -70,7 +70,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
 
     static {
         STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
-        
+
         String wrapSameObject = System.getProperty(
                 "org.apache.catalina.core.ApplicationDispatcher.WRAP_SAME_OBJECT");
         if (wrapSameObject == null) {
@@ -156,7 +156,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
          * The outermost response that will be passed on to the invoked servlet.
          */
         ServletResponse outerResponse = null;
-        
+
         /**
          * The request wrapper we have created and installed (if any).
          */
@@ -167,7 +167,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
          * The response wrapper we have created and installed (if any).
          */
         ServletResponse wrapResponse = null;
-        
+
         /**
          * Are we performing an include() instead of a forward()?
          */
@@ -341,7 +341,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
     private void doForward(ServletRequest request, ServletResponse response)
         throws ServletException, IOException
     {
-        
+
         // Reset any output that has been buffered, but keep headers/cookies
         if (response.isCommitted()) {
             throw new IllegalStateException
@@ -382,7 +382,6 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
 
             ApplicationHttpRequest wrequest =
                 (ApplicationHttpRequest) wrapRequest(state);
-            String contextPath = context.getPath();
             HttpServletRequest hrequest = state.hrequest;
             if (hrequest.getAttribute(
                     RequestDispatcher.FORWARD_REQUEST_URI) == null) {
@@ -397,8 +396,8 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
                 wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING,
                                       hrequest.getQueryString());
             }
- 
-            wrequest.setContextPath(contextPath);
+
+            wrequest.setContextPath(context.getEncodedPath());
             wrequest.setRequestURI(requestURI);
             wrequest.setServletPath(servletPath);
             wrequest.setPathInfo(pathInfo);
@@ -424,9 +423,9 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             ((ResponseFacade) response).finish();
         } else {
             // Servlet SRV.6.2.2. The Request/Response may have been wrapped
-            // and may no longer be instance of RequestFacade 
+            // and may no longer be instance of RequestFacade
             if (wrapper.getLogger().isDebugEnabled()){
-                wrapper.getLogger().debug( " The Response is vehiculed using a wrapper: " 
+                wrapper.getLogger().debug( " The Response is vehiculed using a wrapper: "
                            + response.getClass().getName() );
             }
 
@@ -450,7 +449,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
 
     }
 
-    
+
     /**
      * Prepare the request based on the filter configuration.
      * @param request The servlet request we are processing
@@ -460,15 +459,15 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
      * @exception IOException if an input/output error occurs
      * @exception ServletException if a servlet error occurs
      */
-    private void processRequest(ServletRequest request, 
+    private void processRequest(ServletRequest request,
                                 ServletResponse response,
                                 State state)
         throws IOException, ServletException {
-                
+
         DispatcherType disInt = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
         if (disInt != null) {
             boolean doInvoke = true;
-            
+
             if (context.getFireRequestListenersOnForwards() &&
                     !context.fireRequestInitEvent(request)) {
                 doInvoke = false;
@@ -486,15 +485,15 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
                 } else {
                     invoke(state.outerRequest, response, state);
                 }
-                
+
                 if (context.getFireRequestListenersOnForwards()) {
                     context.fireRequestDestroyEvent(request);
                 }
             }
         }
     }
-    
-    
+
+
     /**
      * Combine the servletPath and the pathInfo. If pathInfo is
      * <code>null</code> it is ignored. If servletPath is <code>null</code> then
@@ -553,7 +552,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             // Check SRV.8.2 / SRV.14.2.5.1 compliance
             checkSameObjects(request, response);
         }
-        
+
         // Create a wrapped response to use for this request
         wrapResponse(state);
 
@@ -595,7 +594,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
                                       queryString);
                 wrequest.setQueryParams(queryString);
             }
-            
+
             wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
                     DispatcherType.INCLUDE);
             wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
@@ -642,7 +641,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
         wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
                 getCombinedPath());
 
-        wrequest.setContextPath(context.getPath());
+        wrequest.setContextPath(context.getEncodedPath());
         wrequest.setRequestURI(requestURI);
         wrequest.setServletPath(servletPath);
         wrequest.setPathInfo(pathInfo);
@@ -699,7 +698,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
         // Check for the servlet being marked unavailable
         if (wrapper.isUnavailable()) {
             wrapper.getLogger().warn(
-                    sm.getString("applicationDispatcher.isUnavailable", 
+                    sm.getString("applicationDispatcher.isUnavailable",
                     wrapper.getName()));
             long available = wrapper.getAvailable();
             if ((available > 0L) && (available < Long.MAX_VALUE))
@@ -728,12 +727,12 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
                               wrapper.getName()), e);
             servlet = null;
         }
-                
+
         // Get the FilterChain Here
         ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
         ApplicationFilterChain filterChain = factory.createFilterChain(request,
                                                                 wrapper,servlet);
-        
+
         // Call the service() method for the allocated servlet instance
         try {
             support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
@@ -811,14 +810,14 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
         // Reset the old context class loader
         if (oldCCL != null)
             Thread.currentThread().setContextClassLoader(oldCCL);
-        
+
         // Unwrap request/response if needed
         // See Bugzilla 30949
         unwrapRequest(state);
         unwrapResponse(state);
         // Recycle request if necessary (also BZ 30949)
         recycleRequestWrapper(state);
-        
+
         // Rethrow an exception if one was thrown by the invoked servlet
         if (ioException != null)
             throw ioException;
@@ -871,7 +870,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
         }
 
     }
-    
+
     /**
      * Unwrap the response if we have wrapped it.
      */
@@ -948,7 +947,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             if ((state.outerRequest instanceof ApplicationHttpRequest) ||
                 (state.outerRequest instanceof Request) ||
                 (state.outerRequest instanceof HttpServletRequest)) {
-                HttpServletRequest houterRequest = 
+                HttpServletRequest houterRequest =
                     (HttpServletRequest) state.outerRequest;
                 Object contextPath = houterRequest.getAttribute(
                         RequestDispatcher.INCLUDE_CONTEXT_PATH);
@@ -1023,15 +1022,15 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             ApplicationFilterChain.getLastServicedRequest();
         ServletResponse originalResponse =
             ApplicationFilterChain.getLastServicedResponse();
-        
-        // Some forwards, eg from valves will not set original values 
+
+        // Some forwards, eg from valves will not set original values
         if (originalRequest == null || originalResponse == null) {
             return;
         }
-        
+
         boolean same = false;
         ServletRequest dispatchedRequest = appRequest;
-        
+
         //find the request that was passed into the service method
         while (originalRequest instanceof ServletRequestWrapper &&
                 ((ServletRequestWrapper) originalRequest).getRequest()!=null ) {
@@ -1054,13 +1053,13 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             throw new ServletException(sm.getString(
                     "applicationDispatcher.specViolation.request"));
         }
-        
+
         same = false;
         ServletResponse dispatchedResponse = appResponse;
-        
+
         //find the response that was passed into the service method
         while (originalResponse instanceof ServletResponseWrapper &&
-                ((ServletResponseWrapper) originalResponse).getResponse() != 
+                ((ServletResponseWrapper) originalResponse).getResponse() !=
                     null ) {
             originalResponse =
                 ((ServletResponseWrapper) originalResponse).getResponse();
@@ -1070,7 +1069,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher
             if (originalResponse.equals(dispatchedResponse)) {
                 same = true;
             }
-            
+
             if (!same && dispatchedResponse instanceof ServletResponseWrapper) {
                 dispatchedResponse =
                     ((ServletResponseWrapper) dispatchedResponse).getResponse();
diff --git a/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcher.java b/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcher.java
index b2177f4..c2be051 100644
--- a/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcher.java
+++ b/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcher.java
@@ -372,8 +372,11 @@ public class TestApplicationContextGetRequestDispatcher extends TomcatBaseTest {
         // Setup Tomcat instance
         Tomcat tomcat = getTomcatInstance();
 
+        // Need to make sure we use UTF-8 for the URI
+        tomcat.getConnector().setURIEncoding("UTF-8");
+
         // No file system docBase required
-        Context ctx = tomcat.addContext("/test", null);
+        Context ctx = tomcat.addContext("/test\u6771\u4eac", null);
         ctx.setDispatchersUseEncodedPaths(useEncodedDispatchPaths);
 
         // Add a default servlet to return 404 for not found resources
@@ -399,7 +402,7 @@ public class TestApplicationContextGetRequestDispatcher extends TomcatBaseTest {
 
         StringBuilder url = new StringBuilder("http://localhost:");
         url.append(getPort());
-        url.append("/test");
+        url.append("/test%E6%9D%B1%E4%BA%AC");
         url.append(startPath);
         if (startQueryString != null) {
             url.append('?');
@@ -466,7 +469,12 @@ public class TestApplicationContextGetRequestDispatcher extends TomcatBaseTest {
                 throws ServletException, IOException {
             resp.setContentType("text/plain");
             resp.setCharacterEncoding("UTF-8");
-            resp.getWriter().print(OK);
+            String contextPath = req.getContextPath();
+            if ("/test%E6%9D%B1%E4%BA%AC".equals(contextPath)) {
+                resp.getWriter().print(OK);
+            } else {
+                resp.getWriter().print("FAIL - ContextPath");
+            }
             String qs = req.getQueryString();
             if (qs != null) {
                 resp.getWriter().print(qs);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 387c850..79d78b3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -115,6 +115,11 @@
         Ensure that the JarScanner correctly tests whether JARs found on the
         class path should be skipped when running on Java 9 or later. (markt)
       </fix>
+      <fix>
+        <bug>63275</bug>: When using a <code>RequestDispatcher</code> ensure
+        that <code>HttpServletRequest.getContextPath()</code> returns an encoded
+        path in the dispatched request. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org