Skip to content

Commit

Permalink
[UNDERTOW-2245]javax.servlet.forward.mapping request attribute is not…
Browse files Browse the repository at this point in the history
… available in servlets forwarded with RequestDispatcher
  • Loading branch information
moulalis committed Apr 4, 2023
1 parent fd4cc49 commit 410ec92
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 60 deletions.
Expand Up @@ -30,6 +30,7 @@
import java.util.Map;

import static jakarta.servlet.AsyncContext.ASYNC_CONTEXT_PATH;
import static jakarta.servlet.AsyncContext.ASYNC_MAPPING;
import static jakarta.servlet.AsyncContext.ASYNC_PATH_INFO;
import static jakarta.servlet.AsyncContext.ASYNC_QUERY_STRING;
import static jakarta.servlet.AsyncContext.ASYNC_REQUEST_URI;
Expand All @@ -41,11 +42,13 @@
import static jakarta.servlet.RequestDispatcher.ERROR_SERVLET_NAME;
import static jakarta.servlet.RequestDispatcher.ERROR_STATUS_CODE;
import static jakarta.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
import static jakarta.servlet.RequestDispatcher.FORWARD_MAPPING;
import static jakarta.servlet.RequestDispatcher.FORWARD_PATH_INFO;
import static jakarta.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
import static jakarta.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
import static jakarta.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
import static jakarta.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
import static jakarta.servlet.RequestDispatcher.INCLUDE_MAPPING;
import static jakarta.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
import static jakarta.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
import static jakarta.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
Expand Down Expand Up @@ -86,6 +89,7 @@ public static ServletPathMatch dispatchForward(final String path,
requestImpl.setAttribute(FORWARD_SERVLET_PATH, requestImpl.getServletPath());
requestImpl.setAttribute(FORWARD_PATH_INFO, requestImpl.getPathInfo());
requestImpl.setAttribute(FORWARD_QUERY_STRING, requestImpl.getQueryString());
requestImpl.setAttribute(FORWARD_MAPPING, requestImpl.getHttpServletMapping());
}

final String newRequestPath = assignRequestPath(path, requestImpl, servletContext, false);
Expand Down Expand Up @@ -119,6 +123,7 @@ public static ServletPathMatch dispatchInclude(final String path,
requestImpl.setAttribute(INCLUDE_CONTEXT_PATH, servletContext.getContextPath());
requestImpl.setAttribute(INCLUDE_SERVLET_PATH, pathMatch.getMatched());
requestImpl.setAttribute(INCLUDE_PATH_INFO, pathMatch.getRemaining());
requestImpl.setAttribute(INCLUDE_MAPPING, pathMatch.getMappingMatch());
return pathMatch;
}

Expand Down Expand Up @@ -148,6 +153,7 @@ public static ServletPathMatch dispatchError(final String path, final String ser
requestImpl.setAttribute(FORWARD_SERVLET_PATH, requestImpl.getServletPath());
requestImpl.setAttribute(FORWARD_PATH_INFO, requestImpl.getPathInfo());
requestImpl.setAttribute(FORWARD_QUERY_STRING, requestImpl.getQueryString());
requestImpl.setAttribute(FORWARD_MAPPING, requestImpl.getHttpServletMapping());
}
// specific attributes for error
requestImpl.setAttribute(ERROR_REQUEST_URI, requestImpl.getRequestURI());
Expand Down Expand Up @@ -193,6 +199,7 @@ public static ServletPathMatch dispatchAsync(final String path,
requestImpl.setAttribute(ASYNC_SERVLET_PATH, requestImpl.getOriginalServletPath());
requestImpl.setAttribute(ASYNC_PATH_INFO, requestImpl.getOriginalPathInfo());
requestImpl.setAttribute(ASYNC_QUERY_STRING, requestImpl.getOriginalQueryString());
requestImpl.setAttribute(ASYNC_MAPPING, requestImpl.getHttpServletMapping());

final String newRequestPath = assignRequestPath(path, requestImpl, servletContext, false);
final ServletPathMatch pathMatch = servletContext.getDeployment().getServletPaths().getServletHandlerByPath(newRequestPath);
Expand Down
@@ -0,0 +1,16 @@
package io.undertow.servlet.test.dispatcher;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class DispatcherForwardServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
req.getRequestDispatcher("/next").forward(req, resp);
}
}

Large diffs are not rendered by default.

@@ -0,0 +1,16 @@
package io.undertow.servlet.test.dispatcher;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class DispatcherIncludeServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
req.getRequestDispatcher("/next").include(req, resp);
}
}
Expand Up @@ -18,18 +18,14 @@

package io.undertow.servlet.test.dispatcher;

import java.io.IOException;

import jakarta.servlet.DispatcherType;
import jakarta.servlet.ServletException;

import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.ServletContainer;
import io.undertow.servlet.api.ServletInfo;
import io.undertow.servlet.test.SimpleServletTestCase;
import io.undertow.servlet.test.dispatcher.util.DispatcherUtil;
import io.undertow.servlet.test.util.MessageFilter;
import io.undertow.servlet.test.util.MessageServlet;
import io.undertow.servlet.test.util.ParameterEchoServlet;
Expand All @@ -38,19 +34,24 @@
import io.undertow.servlet.test.util.TestResourceLoader;
import io.undertow.testutils.DefaultServer;
import io.undertow.testutils.HttpClientUtils;
import io.undertow.testutils.TestHttpClient;
import io.undertow.util.StatusCodes;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.ServletException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;

import io.undertow.testutils.TestHttpClient;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;

import static org.junit.Assert.assertEquals;
import static org.wildfly.common.Assert.assertTrue;

/**
* @author Stuart Douglas
*/
Expand Down Expand Up @@ -86,6 +87,12 @@ public static void setup() throws ServletException {
.addServlet(
new ServletInfo("parameterEcho", ParameterEchoServlet.class)
.addMapping("/echo-parameters"))
.addServlet(
new ServletInfo("/dispatchServletInclude", DispatcherIncludeServlet.class)
.addMapping("/dispatchServletInclude"))
.addServlet(
new ServletInfo("/next", NextServlet.class)
.addMapping("/next"))
.addFilter(
new FilterInfo("notIncluded", MessageFilter.class)
.addInitParam(MessageFilter.MESSAGE, "Not Included"))
Expand Down Expand Up @@ -114,9 +121,9 @@ public void testPathBasedInclude() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch");
get.setHeader("include", "/include");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
final String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "Path!Name!included", response);
assertEquals(IncludeServlet.MESSAGE + "Path!Name!included", response);
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -130,9 +137,9 @@ public void testNameBasedInclude() throws IOException {
get.setHeader("include", "include");
get.setHeader("name", "true");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
final String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "Name!included", response);
assertEquals(IncludeServlet.MESSAGE + "Name!included", response);
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -145,9 +152,9 @@ public void testPathBasedStaticInclude() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch");
get.setHeader("include", "/snippet.html");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
final String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "SnippetText", response);
assertEquals(IncludeServlet.MESSAGE + "SnippetText", response);
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -160,9 +167,9 @@ public void testPathBasedStaticIncludePost() throws IOException {
HttpPost post = new HttpPost(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch");
post.setHeader("include", "/snippet.html");
HttpResponse result = client.execute(post);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
final String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "SnippetText", response);
assertEquals(IncludeServlet.MESSAGE + "SnippetText", response);
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -176,16 +183,16 @@ public void testIncludeAggregatesQueryString() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch?a=b");
get.setHeader("include", "/path");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "pathInfo:null queryString:a=b servletPath:/dispatch requestUri:/servletContext/dispatch", response);
assertEquals(IncludeServlet.MESSAGE + "pathInfo:null queryString:a=b servletPath:/dispatch requestUri:/servletContext/dispatch", response);

get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch?a=b");
get.setHeader("include", "/path?foo=bar");
result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "pathInfo:null queryString:a=b servletPath:/dispatch requestUri:/servletContext/dispatch", response);
assertEquals(IncludeServlet.MESSAGE + "pathInfo:null queryString:a=b servletPath:/dispatch requestUri:/servletContext/dispatch", response);
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -198,7 +205,7 @@ public void testAttributes() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch?n1=v1&n2=v2");
get.setHeader("include", "/path-include?url=http://test.com");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
String response = HttpClientUtils.readResponse(result);
MatcherAssert.assertThat(response, CoreMatchers.containsString(IncludeServlet.MESSAGE + "pathInfo:null queryString:n1=v1&n2=v2 servletPath:/dispatch requestUri:/servletContext/dispatch\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.request_uri:/servletContext/path-include\r\n"));
Expand All @@ -218,14 +225,15 @@ public void testAttributesEncoded() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch/dis%25patch?n1=v1&n2=v%252");
get.setHeader("include", "/path-include/path%25include?n2=v%253");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
String response = HttpClientUtils.readResponse(result);
MatcherAssert.assertThat(response, CoreMatchers.containsString(IncludeServlet.MESSAGE + "pathInfo:/dis%patch queryString:n1=v1&n2=v%252 servletPath:/dispatch requestUri:/servletContext/dispatch/dis%25patch\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.request_uri:/servletContext/path-include/path%25include\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.context_path:/servletContext\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.servlet_path:/path-include\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.path_info:/path%include\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.query_string:n2=v%253\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.mapping:"));
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -238,14 +246,15 @@ public void testAttributesEncodedExtension() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dis%25patch.dispatch?n1=v1&n2=v%252");
get.setHeader("include", "/path%25include.includeinfo?n2=v%253");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
String response = HttpClientUtils.readResponse(result);
MatcherAssert.assertThat(response, CoreMatchers.containsString(IncludeServlet.MESSAGE + "pathInfo:null queryString:n1=v1&n2=v%252 servletPath:/dis%patch.dispatch requestUri:/servletContext/dis%25patch.dispatch\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.request_uri:/servletContext/path%25include.includeinfo\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.context_path:/servletContext\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.servlet_path:/path%include.includeinfo\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.path_info:null\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.query_string:n2=v%253\r\n"));
MatcherAssert.assertThat(response, CoreMatchers.containsString("jakarta.servlet.include.mapping:"));
} finally {
client.getConnectionManager().shutdown();
}
Expand All @@ -258,9 +267,28 @@ public void testParametersAreMerged() throws IOException {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatch?param1=v11&param1=v12");
get.setHeader("include", "/echo-parameters?param1=v13&param1=v14");
HttpResponse result = client.execute(get);
Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
String response = HttpClientUtils.readResponse(result);
Assert.assertEquals(IncludeServlet.MESSAGE + "param1='v13,v14,v11,v12'", response);
assertEquals(IncludeServlet.MESSAGE + "param1='v13,v14,v11,v12'", response);
} finally {
client.getConnectionManager().shutdown();
}
}
@Test
public void testDisptacherServletInclude() throws IOException, InterruptedException {
TestHttpClient client = new TestHttpClient();
try {
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/servletContext/dispatchServletInclude");
HttpResponse result = client.execute(get);
assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
final String response = HttpClientUtils.readResponse(result);
//UNDERTOW-2245 javax.servlet.forward.mapping request attribute is not available in servlets forwarded with RequestDispatcher

assertTrue(DispatcherUtil.containsWord(response,"jakarta.servlet.include.context_path"));
assertTrue(DispatcherUtil.containsWord(response,"jakarta.servlet.include.servlet_path"));
assertTrue(DispatcherUtil.containsWord(response,"jakarta.servlet.include.request_uri"));
assertTrue(DispatcherUtil.containsWord(response,"jakarta.servlet.include.mapping"));

} finally {
client.getConnectionManager().shutdown();
}
Expand Down
Expand Up @@ -43,6 +43,7 @@ protected void doGet(final HttpServletRequest req, final HttpServletResponse res
out.println("jakarta.servlet.forward.servlet_path:" + req.getAttribute("jakarta.servlet.forward.servlet_path"));
out.println("jakarta.servlet.forward.path_info:" + req.getAttribute("jakarta.servlet.forward.path_info"));
out.println("jakarta.servlet.forward.query_string:" + req.getAttribute("jakarta.servlet.forward.query_string"));
out.println("jakarta.servlet.forward.mapping:" + req.getAttribute("jakarta.servlet.forward.mapping"));
}
}
}
Expand Up @@ -43,6 +43,7 @@ protected void doGet(final HttpServletRequest req, final HttpServletResponse res
out.println("jakarta.servlet.include.servlet_path:" + req.getAttribute("jakarta.servlet.include.servlet_path"));
out.println("jakarta.servlet.include.path_info:" + req.getAttribute("jakarta.servlet.include.path_info"));
out.println("jakarta.servlet.include.query_string:" + req.getAttribute("jakarta.servlet.include.query_string"));
out.println("jakarta.servlet.include.mapping:" + req.getAttribute("jakarta.servlet.include.mapping"));
}
}
}

0 comments on commit 410ec92

Please sign in to comment.