diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java index eead4b0b0d76..f6c412bb81f0 100644 --- a/java/org/apache/catalina/authenticator/FormAuthenticator.java +++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java @@ -219,6 +219,20 @@ public boolean authenticate(Request request, HttpServletResponse response) // No -- Save this request and redirect to the form login page if (!loginAction) { + // If this request was to the root of the context without a trailing + // '/', need to redirect to add it else the submit of the login form + // may not go to the correct web application + if (request.getServletPath().length() == 0 && request.getPathInfo() == null) { + StringBuilder location = new StringBuilder(requestURI); + location.append('/'); + if (request.getQueryString() != null) { + location.append('?'); + location.append(request.getQueryString()); + } + response.sendRedirect(response.encodeRedirectURL(location.toString())); + return false; + } + session = request.getSessionInternal(true); if (log.isDebugEnabled()) { log.debug("Save request in session '" + session.getIdInternal() + "'"); diff --git a/java/org/apache/catalina/mapper/Mapper.java b/java/org/apache/catalina/mapper/Mapper.java index f22f47a313cb..cb25eda61147 100644 --- a/java/org/apache/catalina/mapper/Mapper.java +++ b/java/org/apache/catalina/mapper/Mapper.java @@ -835,20 +835,13 @@ private final void internalMapWrapper(ContextVersion contextVersion, int pathOffset = path.getOffset(); int pathEnd = path.getEnd(); - int servletPath = pathOffset; boolean noServletPath = false; int length = contextVersion.path.length(); - if (length != (pathEnd - pathOffset)) { - servletPath = pathOffset + length; - } else { + if (length == (pathEnd - pathOffset)) { noServletPath = true; - path.append('/'); - pathOffset = path.getOffset(); - pathEnd = path.getEnd(); - servletPath = pathOffset+length; } - + int servletPath = pathOffset + length; path.setOffset(servletPath); // Rule 1 -- Exact Match @@ -1002,7 +995,13 @@ private final void internalMapWrapper(ContextVersion contextVersion, char[] buf = path.getBuffer(); if (contextVersion.resources != null && buf[pathEnd -1 ] != '/') { String pathStr = path.toString(); - WebResource file = contextVersion.resources.getResource(pathStr); + WebResource file; + // Handle context root + if (pathStr.length() == 0) { + file = contextVersion.resources.getResource("/"); + } else { + file = contextVersion.resources.getResource(pathStr); + } if (file != null && file.isDirectory() && mappingData.context.getMapperDirectoryRedirectEnabled()) { // Note: this mutates the path: do not do any processing diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java index 1043f31bc8c1..cc6217f7707b 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -331,6 +331,10 @@ public void init() throws ServletException { * @param request The servlet request we are processing */ protected String getRelativePath(HttpServletRequest request) { + return getRelativePath(request, false); + } + + protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) { // IMPORTANT: DefaultServlet can be mapped to '/' or '/path/*' but always // serves resources from the web app root with context rooted paths. // i.e. it cannot be used to mount the web app root under a sub-path @@ -356,7 +360,7 @@ protected String getRelativePath(HttpServletRequest request) { if (pathInfo != null) { result.append(pathInfo); } - if (result.length() == 0) { + if (result.length() == 0 && !allowEmptyPath) { result.append('/'); } @@ -686,7 +690,8 @@ protected void serveResource(HttpServletRequest request, boolean serveContent = content; // Identify the requested resource path - String path = getRelativePath(request); + String path = getRelativePath(request, true); + if (debug > 0) { if (serveContent) log("DefaultServlet.serveResource: Serving resource '" + @@ -696,6 +701,12 @@ protected void serveResource(HttpServletRequest request, path + "' headers only"); } + if (path.length() == 0) { + // Context root redirect + doDirectoryRedirect(request, response); + return; + } + WebResource resource = resources.getResource(path); if (!resource.exists()) { @@ -811,13 +822,7 @@ protected void serveResource(HttpServletRequest request, if (resource.isDirectory()) { if (!path.endsWith("/")) { - StringBuilder location = new StringBuilder(request.getRequestURI()); - location.append('/'); - if (request.getQueryString() != null) { - location.append('?'); - location.append(request.getQueryString()); - } - response.sendRedirect(response.encodeRedirectURL(location.toString())); + doDirectoryRedirect(request, response); return; } @@ -1026,6 +1031,16 @@ protected void serveResource(HttpServletRequest request, } } + private void doDirectoryRedirect(HttpServletRequest request, HttpServletResponse response) + throws IOException { + StringBuilder location = new StringBuilder(request.getRequestURI()); + location.append('/'); + if (request.getQueryString() != null) { + location.append('?'); + location.append(request.getQueryString()); + } + response.sendRedirect(response.encodeRedirectURL(location.toString())); + } /** * Parse the content-range header.