This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push: new c73c94d5a6 Process path parameters rewrite production c73c94d5a6 is described below commit c73c94d5a69e9c1acef46be4fbef1e3f803e1804 Author: remm <r...@apache.org> AuthorDate: Thu Apr 3 21:27:35 2025 +0200 Process path parameters rewrite production --- java/org/apache/catalina/connector/Request.java | 4 +- .../apache/catalina/core/ApplicationContext.java | 30 +------------- java/org/apache/catalina/util/RequestUtil.java | 46 ++++++++++++++++++++++ .../catalina/valves/rewrite/RewriteValve.java | 4 ++ .../TestApplicationContextStripPathParams.java | 45 ++++++++++++++------- webapps/docs/changelog.xml | 4 ++ 6 files changed, 87 insertions(+), 46 deletions(-) diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 9baed8c484..087d5d62a5 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -414,11 +414,11 @@ public class Request implements HttpServletRequest { // --------------------------------------------------------- Public Methods - protected void addPathParameter(String name, String value) { + public void addPathParameter(String name, String value) { coyoteRequest.addPathParameter(name, value); } - protected String getPathParameter(String name) { + public String getPathParameter(String name) { return coyoteRequest.getPathParameter(name); } diff --git a/java/org/apache/catalina/core/ApplicationContext.java b/java/org/apache/catalina/core/ApplicationContext.java index 3c1574c985..001685e6c3 100644 --- a/java/org/apache/catalina/core/ApplicationContext.java +++ b/java/org/apache/catalina/core/ApplicationContext.java @@ -374,7 +374,7 @@ public class ApplicationContext implements ServletContext { // From this point, the removal of path parameters, decoding and normalization is only for mapping purposes. // Remove path parameters - String uriToMap = stripPathParams(uri); + String uriToMap = org.apache.catalina.util.RequestUtil.stripPathParams(uri, null); // Decode only if the uri derived from the provided path is expected to be encoded if (getContext().getDispatchersUseEncodedPaths()) { @@ -449,34 +449,6 @@ public class ApplicationContext implements ServletContext { } - // Package private to facilitate testing - static String stripPathParams(String input) { - // Shortcut - if (input.indexOf(';') < 0) { - return input; - } - - StringBuilder sb = new StringBuilder(input.length()); - int pos = 0; - int limit = input.length(); - while (pos < limit) { - int nextSemiColon = input.indexOf(';', pos); - if (nextSemiColon < 0) { - nextSemiColon = limit; - } - sb.append(input, pos, nextSemiColon); - int followingSlash = input.indexOf('/', nextSemiColon); - if (followingSlash < 0) { - pos = limit; - } else { - pos = followingSlash; - } - } - - return sb.toString(); - } - - @Override public URL getResource(String path) throws MalformedURLException { diff --git a/java/org/apache/catalina/util/RequestUtil.java b/java/org/apache/catalina/util/RequestUtil.java index 85448b7ad1..36f5f072a6 100644 --- a/java/org/apache/catalina/util/RequestUtil.java +++ b/java/org/apache/catalina/util/RequestUtil.java @@ -18,6 +18,8 @@ package org.apache.catalina.util; import jakarta.servlet.http.HttpServletRequest; +import org.apache.catalina.connector.Request; + /** * General purpose request parsing and encoding utility methods. * @@ -54,4 +56,48 @@ public final class RequestUtil { return url; } + + + /** + * Strip parameters for given path. + * @param input the input path + * @param request the request to add the parameters to + * @return the cleaned path + */ + public static String stripPathParams(String input, Request request) { + // Shortcut + if (input.indexOf(';') < 0) { + return input; + } + + StringBuilder sb = new StringBuilder(input.length()); + int pos = 0; + int limit = input.length(); + while (pos < limit) { + int nextSemiColon = input.indexOf(';', pos); + if (nextSemiColon < 0) { + nextSemiColon = limit; + } + sb.append(input, pos, nextSemiColon); + int followingSlash = input.indexOf('/', nextSemiColon); + if (followingSlash < 0) { + pos = limit; + } else { + pos = followingSlash; + } + if (request != null && nextSemiColon + 1 <pos) { + String pathVariable = input.substring(nextSemiColon + 1, pos); + int equals = pathVariable.indexOf('='); + if (equals > -1 && equals + 1 < pathVariable.length()) { + String name = pathVariable.substring(0, equals); + String value = pathVariable.substring(equals + 1); + request.addPathParameter(name, value); + } + } + } + + return sb.toString(); + } + + } diff --git a/java/org/apache/catalina/valves/rewrite/RewriteValve.java b/java/org/apache/catalina/valves/rewrite/RewriteValve.java index 22902ef4d5..ab7658cbe6 100644 --- a/java/org/apache/catalina/valves/rewrite/RewriteValve.java +++ b/java/org/apache/catalina/valves/rewrite/RewriteValve.java @@ -528,6 +528,8 @@ public class RewriteValve extends ValveBase { queryStringRewriteEncoded = urlStringRewriteEncoded.substring(queryIndex + 1); urlStringRewriteEncoded = urlStringRewriteEncoded.substring(0, queryIndex); } + // Parse path parameters from rewrite production and populate request path parameters + urlStringRewriteEncoded = org.apache.catalina.util.RequestUtil.stripPathParams(urlStringRewriteEncoded, request); // Save the current context path before re-writing starts String contextPath = null; if (context) { @@ -879,4 +881,6 @@ public class RewriteValve extends ValveBase { return input; } } + + } diff --git a/test/org/apache/catalina/core/TestApplicationContextStripPathParams.java b/test/org/apache/catalina/core/TestApplicationContextStripPathParams.java index 2faea49a60..3d8a52b7e1 100644 --- a/test/org/apache/catalina/core/TestApplicationContextStripPathParams.java +++ b/test/org/apache/catalina/core/TestApplicationContextStripPathParams.java @@ -25,42 +25,57 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.apache.catalina.connector.Request; import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.catalina.util.RequestUtil; @RunWith(value = Parameterized.class) public class TestApplicationContextStripPathParams extends TomcatBaseTest { private final String input; private final String expectedOutput; + private final Boolean hasParameter; - public TestApplicationContextStripPathParams(String input, String expectedOutput) { + public TestApplicationContextStripPathParams(String input, String expectedOutput, Boolean hasParameter) { this.input = input; this.expectedOutput = expectedOutput; + this.hasParameter = hasParameter; } @Parameters(name = "{index}: input[{0}]") public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ - { "/foo", "/foo"}, - { "/foo/", "/foo/"}, - { "/foo/bar", "/foo/bar"}, - { "/foo;", "/foo"}, - { "/foo;/", "/foo/"}, - { "/foo;/bar", "/foo/bar"}, - { "/foo;a=1", "/foo"}, - { "/foo;a=1/", "/foo/"}, - { "/foo;a=1/bar", "/foo/bar"}, + { "/foo", "/foo", Boolean.FALSE }, + { "/foo/", "/foo/", Boolean.FALSE }, + { "/foo/bar", "/foo/bar", Boolean.FALSE }, + { "/foo;", "/foo", Boolean.FALSE }, + { "/foo;/", "/foo/", Boolean.FALSE }, + { "/foo;/bar", "/foo/bar", Boolean.FALSE }, + { "/foo;a=1", "/foo", Boolean.TRUE }, + { "/foo;a=1/", "/foo/", Boolean.TRUE }, + { "/foo;a=1/bar", "/foo/bar", Boolean.TRUE }, // Arguably not valid but does the right thing anyway - { ";/foo", "/foo"}, - { ";a=1/foo", "/foo"}, - { ";/foo/bar", "/foo/bar"}, - { ";/foo;a=1/bar", "/foo/bar"}, + { ";/foo", "/foo", Boolean.FALSE }, + { ";a=1/foo", "/foo", Boolean.TRUE }, + { ";/foo/bar", "/foo/bar", Boolean.FALSE }, + { ";/foo;a=1/bar", "/foo/bar", Boolean.TRUE }, + { ";/foo;=/bar", "/foo/bar", Boolean.FALSE }, + { ";/foo;a=/bar", "/foo/bar", Boolean.FALSE }, + { ";/foo;=1/bar", "/foo/bar", Boolean.FALSE }, }); } @Test public void testStringPathParams() { - String output = ApplicationContext.stripPathParams(input); + Request request = new Request(null); + request.setCoyoteRequest(new org.apache.coyote.Request()); + String output = RequestUtil.stripPathParams(input, request); Assert.assertEquals(expectedOutput, output); + String parameter = request.getPathParameter("a"); + if (hasParameter.booleanValue()) { + Assert.assertEquals("1", parameter); + } else { + Assert.assertNull(parameter); + } } } \ No newline at end of file diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index f512dc7868..e5cf260f75 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -111,6 +111,10 @@ Fix use of <code>SSS</code> in <code>SimpleDateFormat</code> pattern for <code>AccessLogValve</code>. (rjung) </fix> + <fix> + Process possible path parameters rewrite production in the rewrite + valve. (remm) + </fix> </changelog> </subsection> <subsection name="Other"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org