This is an automated email from the ASF dual-hosted git repository.
markt-asf 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 10c1df3da7 Improve AsyncContext.dispatch() when
dispatchersUseEncodedPaths=false
10c1df3da7 is described below
commit 10c1df3da7a6267b75f47a8c3a8c4961203500e7
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 76f64f7e94..f8400d3c57 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 d9280ae729..a2a28a25dd 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 cpath;
Request request = this.request;
- Context context = this.context;
// Calls check() so local copies are validated
ServletRequest servletRequest = getRequest();
if (servletRequest instanceof HttpServletRequest) {
@@ -233,10 +236,20 @@ public class AsyncContextImpl implements AsyncContext,
AsyncContextCallback {
if (cpath.length() > 1) {
path = path.substring(cpath.length());
}
- if (!context.getDispatchersUseEncodedPaths()) {
- path = UDecoder.URLDecode(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 = UDecoder.URLDecode(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 f94f467190..bad9fc0709 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -210,6 +210,14 @@
<code>SPNEGO</code> authentication, the user must exist in the database
for authentication to succeed. (markt)
</fix>
+ <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">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]