This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new dee3cc39d1 Improve AsyncContext.dispatch() when dispatchersUseEncodedPaths=false
dee3cc39d1 is described below
commit dee3cc39d1fb7887b0acded60eb68a13c57258d3
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Aug 13 10:37:18 2026 +0100
Improve AsyncContext.dispatch() when dispatchersUseEncodedPaths=false
---
.../apache/catalina/core/ApplicationContext.java | 7 +++++--
java/org/apache/catalina/core/AsyncContextImpl.java | 21 +++++++++++++++++----
webapps/docs/changelog.xml | 8 ++++++++
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/catalina/core/ApplicationContext.java b/java/org/apache/catalina/core/ApplicationContext.java
index 28363b2e44..d499bbe0ab 100644
--- a/java/org/apache/catalina/core/ApplicationContext.java
+++ b/java/org/apache/catalina/core/ApplicationContext.java
@@ -372,8 +372,11 @@ public class ApplicationContext implements ServletContext {
// Remove path parameters
String uriToMap = org.apache.catalina.util.RequestUtil.stripPathParams(uri, null);
+ boolean pathIsEncoded =
+ getContext().getDispatchersUseEncodedPaths() || AsyncContextImpl.uriEncoded.get().booleanValue();
+
// Decode only if the uri derived from the provided path is expected to be encoded
- if (getContext().getDispatchersUseEncodedPaths()) {
+ if (pathIsEncoded) {
uriToMap = UDecoder.URLDecode(uriToMap, StandardCharsets.UTF_8, context.getEncodedSolidusHandlingEnum(),
context.getEncodedReverseSolidusHandlingEnum());
}
@@ -391,7 +394,7 @@ public class ApplicationContext implements ServletContext {
* getRequestURI() which returns encoded values. getContextPath() returns a decoded value. uri may be encoded or
* not. Need to prepend the context path to uri and ensure the result is correctly encoded.
*/
- if (getContext().getDispatchersUseEncodedPaths()) {
+ if (pathIsEncoded) {
uri = URLEncoder.DEFAULT.encode(getContextPath(), StandardCharsets.UTF_8) + uri;
} else {
uri = URLEncoder.DEFAULT.encode(getContextPath() + uri, StandardCharsets.UTF_8);
diff --git a/java/org/apache/catalina/core/AsyncContextImpl.java b/java/org/apache/catalina/core/AsyncContextImpl.java
index 9915d0b1e5..c22e1078c5 100644
--- a/java/org/apache/catalina/core/AsyncContextImpl.java
+++ b/java/org/apache/catalina/core/AsyncContextImpl.java
@@ -128,6 +128,10 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
private final AtomicBoolean hasErrorProcessingStarted = new AtomicBoolean(false);
private final AtomicBoolean hasOnErrorReturned = new AtomicBoolean(false);
+ /*
+ * ThreadLocal for passing over-ridden URL encoding state when dispatching.
+ */
+ static ThreadLocal<Boolean> uriEncoded = ThreadLocal.withInitial(() -> Boolean.FALSE);
/**
* Constructs an AsyncContextImpl for the given request.
@@ -219,7 +223,6 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
String path;
String pathInfo;
Request request = this.request;
- Context context = this.context;
// Calls check() so local copies are validated
ServletRequest servletRequest = getRequest();
if (servletRequest instanceof HttpServletRequest sr) {
@@ -232,10 +235,20 @@ public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
if (pathInfo != null && !pathInfo.isEmpty()) {
path = path + pathInfo;
}
- if (context.getDispatchersUseEncodedPaths()) {
- path = URLEncoder.DEFAULT.encode(path, StandardCharsets.UTF_8);
+ /*
+ * This is a dispatch of the original request path. That path will always be URI-decoded. That will cause
+ * problems in ServletContext.getRequestDispatcher() if the decoded URI contains a literal '?' as it will be
+ * treated as a query delimiter. Therefore, ignore context.getDispatchersUseEncodedPaths() here and always
+ * encode. Also need to mark this request as ignoring context.getDispatchersUseEncodedPaths() so it is handled
+ * correctly in ServletContext.getRequestDispatcher().
+ */
+ path = URLEncoder.DEFAULT.encode(path, StandardCharsets.UTF_8);
+ try {
+ uriEncoded.set(Boolean.TRUE);
+ dispatch(path);
+ } finally {
+ uriEncoded.set(Boolean.FALSE);
}
- dispatch(path);
}
@Override
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a3e0eca6c3..111fb24911 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -241,6 +241,14 @@
interface must implement this method. (markt)
</fix>
<!-- Entries for backport and removal before 12.0.0-M1 below this line -->
+ <fix>
+ Improve the handling of <code>AsyncContext.dispatch()</code> when the
+ <code>Context</code> attribute <code>dispatchersUseEncodedPaths</code>
+ is set to <code>false</code> since the application has no control over
+ the path used for the <code>AsyncContext.dispatch()</code>. Prior to
+ this fix, paths containing literal <code>'?'</code> characters were
+ truncated. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.