diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 9c8ec37a61a..4ad2b6f3837 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -898,7 +898,7 @@ public interface HttpURI { if (hasAuthority() && !isPathValidForAuthority(path)) throw new IllegalArgumentException("Relative path with authority"); - if (!URIUtil.isLegalPath(path)) + if (!URIUtil.isValidPath(path)) throw new IllegalArgumentException("Path not correctly encoded: " + path); _uri = null; _path = path; diff --git a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java index fadab27eae8..40f33902a17 100644 --- a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java +++ b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java @@ -26,17 +26,17 @@ import org.eclipse.jetty.util.URIUtil; public class CompactPathRule extends Rule { @Override - public Request.WrapperProcessor matchAndApply(Request.WrapperProcessor input) throws IOException + public Request.WrapperProcessor matchAndApply(Request.WrapperProcessor request) throws IOException { - String path = Request.getPathInContext(input); + String path = request.getHttpURI().getCanonicalPath(); String compacted = URIUtil.compactPath(path); if (path.equals(compacted)) return null; - HttpURI uri = Request.updateHttpURI(input, compacted); + HttpURI uri = Request.newHttpURIFrom(request, compacted); - return new Request.WrapperProcessor(input) + return new Request.WrapperProcessor(request) { @Override public HttpURI getHttpURI() diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index 31c29c9a34d..4715ff637f4 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -57,6 +57,12 @@ public interface Context extends Attributes, Decorator, Executor /** scope the calling thread to the context and request and run the runnable. */ void run(Runnable runnable, Request request); - /** Return a URI path scoped to this context **/ - String pathInContext(String path); + /** + *

Get a URI path scoped to a context. For example if the context path is "/ctx" then a + * full path of "/ctx/foo/bar" will return "/foo/bar".

+ * @param fullPath A full URI path + * @return The URI path scoped to the context, or null if the fullPath is not in the context. + * The empty string is returned if the fullPath is exactly the context path. + */ + String getPathInContext(String fullPath); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e84dc1e1c46..4aa156b9220 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -166,13 +166,15 @@ public interface Request extends Attributes, Content.Source /** *

Get the canonically encoded path of the URI, scoped to the current context.

- *

The pathInContext represents the targeted resource within the current content for the request.

+ *

For example, when the request has a {@link Context} with {@code contextPath=/ctx} and the requests + * {@link HttpURI} has{@code canonicalPath=/ctx/foo}, then the path in context is {@code /foo}.

* @return The part of the canonically encoded path of the URI after any context path prefix has been removed. * @see HttpURI#getCanonicalPath() + * @see Context#getContextPath() */ static String getPathInContext(Request request) { - return request.getContext().pathInContext(request.getHttpURI().getCanonicalPath()); + return request.getContext().getPathInContext(request.getHttpURI().getCanonicalPath()); } /** @@ -703,7 +705,13 @@ public interface Request extends Attributes, Content.Source } } - static HttpURI updateHttpURI(Request request, String newPathInContext) + /** + *

Create a new {@link HttpURI} for a request by replacing the path in context

+ * @param request The request to base the HttpURI on. + * @param newPathInContext The new path in context for the URI + * @return A new immutable HttpURI for the request with the path replaced (but parameters and query string retained). + */ + static HttpURI newHttpURIFrom(Request request, String newPathInContext) { return HttpURI.build(request.getHttpURI()) .path(URIUtil.addPaths(getContextPath(request), newPathInContext)) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index b7c847cedb4..7e41050a20e 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -536,7 +536,6 @@ public class ResourceService { // Redirect to the index response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); - // TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority HttpURI.Mutable uri = HttpURI.build(request.getHttpURI()); uri.path(URIUtil.addPaths(contextPath, welcomeTarget)); return new WelcomeAction(WelcomeActionType.REDIRECT, uri.getPathQuery()); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index e7c387a456c..78ce8581b71 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -787,9 +787,9 @@ public class Server extends Handler.Wrapper implements Attributes } @Override - public String pathInContext(String path) + public String getPathInContext(String fullPath) { - return path; + return fullPath; } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 596f9e5fe2b..c68e4ea684c 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1168,17 +1168,17 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace } @Override - public String pathInContext(String path) + public String getPathInContext(String fullPath) { if (_rootContext) - return path; - if (!path.startsWith(_contextPath)) + return fullPath; + if (!fullPath.startsWith(_contextPath)) return null; - if (path.length() == _contextPath.length()) + if (fullPath.length() == _contextPath.length()) return ""; - if (path.charAt(_contextPath.length()) != '/') + if (fullPath.charAt(_contextPath.length()) != '/') return null; - return path.substring(_contextPath.length()); + return fullPath.substring(_contextPath.length()); } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java index ec2d58f69ca..83f00743993 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java @@ -102,8 +102,9 @@ public class MovedContextHandler extends ContextHandler return; String path = _newContextURL; - if (!_discardPathInfo && Request.getPathInContext(request) != null) - path = URIUtil.addPaths(path, Request.getPathInContext(request)); + String pathInContext = Request.getPathInContext(request); + if (!_discardPathInfo && pathInContext != null) + path = URIUtil.addPaths(path, pathInContext); HttpURI uri = request.getHttpURI(); StringBuilder location = new StringBuilder(); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java index 97cd2bbed5a..6d6e49e1b86 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java @@ -56,7 +56,7 @@ public abstract class ReHandlingErrorProcessor extends ErrorProcessor if (pathInContext != null) { request.setAttribute(ReHandlingErrorProcessor.class.getName(), pathInContext); - HttpURI uri = Request.updateHttpURI(request, pathInContext); + HttpURI uri = Request.newHttpURIFrom(request, pathInContext); Request.Wrapper wrapper = new ReHandleRequestWrapper(request, uri); try diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index fe78924e1e3..f456b01ca31 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -92,8 +92,9 @@ public class ResourceHandler extends Handler.Wrapper for (String welcome : _welcomes) { - String welcomeInContext = URIUtil.addPaths(Request.getPathInContext(request), welcome); - Resource welcomePath = _resourceBase.resolve(Request.getPathInContext(request)).resolve(welcome); + String pathInContext = Request.getPathInContext(request); + String welcomeInContext = URIUtil.addPaths(pathInContext, welcome); + Resource welcomePath = _resourceBase.resolve(pathInContext).resolve(welcome); if (Resources.isReadableFile(welcomePath)) return welcomeInContext; } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java index 6935719544d..a33b08e63de 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java @@ -90,7 +90,7 @@ public class TryPathsHandler extends Handler.Wrapper public TryPathsRequest(Request wrapped, String pathInContext) { super(wrapped); - _uri = Request.updateHttpURI(wrapped, URIUtil.canonicalPath(pathInContext)); + _uri = Request.newHttpURIFrom(wrapped, URIUtil.canonicalPath(pathInContext)); } @Override diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java index cf10662a627..1734e320e7b 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java @@ -73,21 +73,22 @@ public class ErrorProcessorTest @Override public void process(Request request, Response response, Callback callback) { - if (Request.getPathInContext(request).startsWith("/badmessage/")) + String pathInContext = Request.getPathInContext(request); + if (pathInContext.startsWith("/badmessage/")) { - int code = Integer.parseInt(Request.getPathInContext(request).substring(Request.getPathInContext(request).lastIndexOf('/') + 1)); + int code = Integer.parseInt(pathInContext.substring(pathInContext.lastIndexOf('/') + 1)); throw new BadMessageException(code); } // produce an exception with an JSON formatted cause message - if (Request.getPathInContext(request).startsWith("/jsonmessage/")) + if (pathInContext.startsWith("/jsonmessage/")) { String message = "\"}, \"glossary\": {\n \"title\": \"example\"\n }\n {\""; throw new TestException(message); } // produce an exception with an XML cause message - if (Request.getPathInContext(request).startsWith("/xmlmessage/")) + if (pathInContext.startsWith("/xmlmessage/")) { String message = "\n" + @@ -98,14 +99,14 @@ public class ErrorProcessorTest } // produce an exception with an HTML cause message - if (Request.getPathInContext(request).startsWith("/htmlmessage/")) + if (pathInContext.startsWith("/htmlmessage/")) { String message = "
%3Cscript%3E"; throw new TestException(message); } // produce an exception with a UTF-8 cause message - if (Request.getPathInContext(request).startsWith("/utf8message/")) + if (pathInContext.startsWith("/utf8message/")) { // @checkstyle-disable-check : AvoidEscapedUnicodeCharacters String message = "Euro is € and \u20AC and %E2%82%AC"; @@ -114,12 +115,12 @@ public class ErrorProcessorTest } // 200 response - if (Request.getPathInContext(request).startsWith("/ok/")) + if (pathInContext.startsWith("/ok/")) { Content.Sink.write( response, true, - "%s Error %s : %s%n".formatted(Request.getPathInContext(request), request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)), + "%s Error %s : %s%n".formatted(pathInContext, request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)), callback); return; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java index ff2611e39e4..b2ba83379ab 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java @@ -185,45 +185,45 @@ public interface Attributes @Override public Object removeAttribute(String name) { - return _wrapped.removeAttribute(name); + return getWrapped().removeAttribute(name); } @Override public Object setAttribute(String name, Object attribute) { - return _wrapped.setAttribute(name, attribute); + return getWrapped().setAttribute(name, attribute); } @Override public Object getAttribute(String name) { - return _wrapped.getAttribute(name); + return getWrapped().getAttribute(name); } @Override public Set getAttributeNameSet() { - return _wrapped.getAttributeNameSet(); + return getWrapped().getAttributeNameSet(); } @Override public void clearAttributes() { - _wrapped.clearAttributes(); + getWrapped().clearAttributes(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public int hashCode() { - return _wrapped.hashCode(); + return getWrapped().hashCode(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public boolean equals(Object obj) { - return _wrapped.equals(obj); + return getWrapped().equals(obj); } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index 31dc97ed0e8..4944e1c6a13 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -698,10 +698,10 @@ public final class URIUtil } /** - * @param path The path to check for legality - * @return True if the path does not contain any illegal path characters + * @param path The path to check for validity + * @return True if the path does not contain any invalid path characters */ - public static boolean isLegalPath(String path) + public static boolean isValidPath(String path) { if (path == null) return true; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 46ffeca8b7a..def3df7ce17 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -444,7 +444,7 @@ public class DefaultServlet extends HttpServlet _httpFields = fields.asImmutable(); _uri = (request.getDispatcherType() == DispatcherType.REQUEST) ? getWrapped().getHttpURI() - : Request.updateHttpURI(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); + : Request.newHttpURIFrom(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); } @Override diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index 09fb8e18f57..d80b4c4352e 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -1187,7 +1187,9 @@ public class ServletContextHandler extends ContextHandler implements Graceful @Override protected ServletContextRequest wrap(Request request) { - String pathInContext = getContext().pathInContext(request.getHttpURI().getCanonicalPath()); + // we need to directly ask the context for the pathInContext rather than use the utility static method, as + // we have not yet wrapped the request in this context. + String pathInContext = getContext().getPathInContext(request.getHttpURI().getCanonicalPath()); MatchedResource matchedResource = _servletHandler.getMatchedServlet(pathInContext); if (matchedResource == null) return null; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java index fd1d2dd98b0..4e975402dc7 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java @@ -242,8 +242,8 @@ public class ServletContextRequest extends ContextRequest implements Runnable { case "o.e.j.s.s.ServletScopedRequest.request" -> _httpServletRequest; case "o.e.j.s.s.ServletScopedRequest.response" -> _response.getHttpServletResponse(); - case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(_pathInContext).getServletName(); - case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(_pathInContext).getPattern(); + case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(getPathInContext()).getServletName(); + case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(getPathInContext()).getPattern(); default -> super.getAttribute(name); }; } diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java index bddb2328dc8..6b10a2f03cd 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java @@ -223,12 +223,13 @@ public class FormAuthenticator extends LoginAuthenticator ServletContextRequest servletContextRequest = Request.as(req, ServletContextRequest.class); ServletContextRequest.ServletApiRequest servletApiRequest = servletContextRequest.getServletApiRequest(); - boolean jSecurityCheck = isJSecurityCheck(Request.getPathInContext(req)); + String pathInContext = servletContextRequest.getPathInContext(); + boolean jSecurityCheck = isJSecurityCheck(pathInContext); mandatory |= jSecurityCheck; if (!mandatory) return new DeferredAuthentication(this); - if (isLoginOrErrorPage(Request.getPathInContext(req)) && !DeferredAuthentication.isDeferred(res)) + if (isLoginOrErrorPage(pathInContext) && !DeferredAuthentication.isDeferred(res)) return new DeferredAuthentication(this); // Handle a request for authentication. diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java index ac6b3642c8b..dcd49572522 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java @@ -1545,9 +1545,10 @@ public class Request implements HttpServletRequest _method = coreRequest.getMethod(); _uri = coreRequest.getHttpURI(); + String pathInContext = org.eclipse.jetty.server.Request.getPathInContext(coreRequest); _pathInContext = _context.getContextHandler().isCanonicalEncodingURIs() - ? org.eclipse.jetty.server.Request.getPathInContext(coreRequest) - : URIUtil.decodePath(org.eclipse.jetty.server.Request.getPathInContext(coreRequest)); + ? pathInContext + : URIUtil.decodePath(pathInContext); _httpFields = coreRequest.getHeaders(); setSecure(coreRequest.isSecure());