Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #5025 - wrong welcome file handling with dispatcher.include() a… #5026

Merged
merged 1 commit into from
Jul 15, 2020

Conversation

grgrzybek
Copy link
Contributor

…nd non-default mapping

@grgrzybek grgrzybek force-pushed the 5025-include-welcome branch 2 times, most recently from c7d114f to 72d3d1d Compare July 4, 2020 13:52
HttpTester.Response response;

// Test included alt default
rawResponse = connector.getResponse("GET /context/gateway HTTP/1.0\r\n\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be GET /context/gateway/ HTTP/1.0\r\n\r\n as you are requesting content belonging to the url-pattern of /gateway/* which the request to /gateway will not match.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked org.eclipse.jetty.http.pathmap.PathMappings#getMatch() and /p request is successfully matched for servlet mapped to /p/* - it's kept in org.eclipse.jetty.http.pathmap.PathMappings#_prefixMap:

_prefixMap = {org.eclipse.jetty.util.ArrayTernaryTrie@2636} "{/p=MappedResource[pathSpec=ServletPathSpec["/p/*",pathDepth=2,group=PREFIX_GLOB],resource=default-servlet@2c16bab9==org.ops4j.pax.web.service.jetty.internal.EmbeddedJettyTest$11,jsp=null,order=-1,inst=true,async=true]}"
 LO: int  = 1 (0x1)
 EQ: int  = 2 (0x2)
 HI: int  = 3 (0x3)
 ROW_SIZE: int  = 4 (0x4)
 _tree: char[]  = {char[512]@2893} 
 _key: java.lang.String[]  = {java.lang.String[128]@2894} 
  2 = "/p"
 _value: java.lang.Object[]  = {java.lang.Object[128]@2895} 
  2 = {org.eclipse.jetty.http.pathmap.MappedResource@2643} "MappedResource[pathSpec=ServletPathSpec["/p/*",pathDepth=2,group=PREFIX_GLOB],resource=default-servlet@2c16bab9==org.ops4j.pax.web.service.jetty.internal.EmbeddedJettyTest$11,jsp=null,order=-1,inst=true,async=true]"
   pathSpec: org.eclipse.jetty.http.pathmap.PathSpec  = {org.eclipse.jetty.http.pathmap.ServletPathSpec@2897} "ServletPathSpec["/p/*",pathDepth=2,group=PREFIX_GLOB]"
   resource: java.lang.Object  = {org.eclipse.jetty.servlet.ServletHolder@2656} "default-servlet@2c16bab9==org.ops4j.pax.web.service.jetty.internal.EmbeddedJettyTest$11,jsp=null,order=-1,inst=true,async=true"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you've got 2 differents tests to do here:

  1. url is /context/gateway WITHOUT the trailing slash, which will go to line 377 of ResourceService that does a 302 redirect to url that adds the trailing slash

  2. url is /context/gateway/ WITH the trailing slash, which will go to the code at line 402 of ResourceService

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grgrzybek I'd still like to see one request with GET /context/gateway and one with GET /context/gateway/, because the first one will do a redirect before doing the new include path handling: I just want to ensure that we've exercised both codepaths.

req.getRequestDispatcher("/alt/").include(req, resp);
}
});
context.addServlet(gwholder, "/gateway/*");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This addServlet should be done before Server.start()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's the case in other tests inside org.eclipse.jetty.servlet.DefaultServletTest...

FS.ensureDirExists(altRoot);
Path altIndex = altRoot.resolve("index.html");

ServletHolder defholder = context.addServlet(DefaultServlet.class, "/alt/*");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This addServlet should be done before Server.start()

@joakime joakime changed the base branch from jetty-10.0.x to jetty-9.4.x July 4, 2020 15:59
@joakime joakime changed the base branch from jetty-9.4.x to jetty-10.0.x July 4, 2020 15:59
@joakime
Copy link
Contributor

joakime commented Jul 4, 2020

I'll let others look at this too, but I feel this should be done against branch jetty-9.4.x (not jetty-10.0.x)

@grgrzybek
Copy link
Contributor Author

I'm not sure about the branch. I'm mostly interested in version 9.4.x, but I see that 10.x is the "current" version being developed.

Copy link
Contributor

@janbartel janbartel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can get rid of the unnecessary "if" statement, and make 2 tests instead of 1, we're golden.

@@ -401,8 +401,13 @@ protected void sendWelcome(HttpContent content, String pathInContext, boolean en

if (welcome != null)
{
String servletPath = included ? (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH)
: request.getServletPath();
if (servletPath == null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good solution. I would delete the extra "if" at line 406 because that can never happen, unless there's a bug in jetty :)

HttpTester.Response response;

// Test included alt default
rawResponse = connector.getResponse("GET /context/gateway HTTP/1.0\r\n\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you've got 2 differents tests to do here:

  1. url is /context/gateway WITHOUT the trailing slash, which will go to line 377 of ResourceService that does a 302 redirect to url that adds the trailing slash

  2. url is /context/gateway/ WITH the trailing slash, which will go to the code at line 402 of ResourceService

…e() and non-default mapping

Signed-off-by: Grzegorz Grzybek <gr.grzybek@gmail.com>
@grgrzybek
Copy link
Contributor Author

I've just removed the extra if and changed the test, so it uses "strict" mapping for gateway servlet. What's important is not the mapping (and even a request to) for the gateway servlet, but the fact that the servlet calls dispatcher.include()`.

HttpTester.Response response;

// Test included alt default
rawResponse = connector.getResponse("GET /context/gateway HTTP/1.0\r\n\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grgrzybek I'd still like to see one request with GET /context/gateway and one with GET /context/gateway/, because the first one will do a redirect before doing the new include path handling: I just want to ensure that we've exercised both codepaths.

@grgrzybek
Copy link
Contributor Author

I've changed the mapping of the gateway servlet from prefix mapping to strict mapping (from /gateway/* which also handles /gateway requests to plain /gateway). According to Servlet spec, /context/gateway URL is handled by (mapped to) gateway servlet - there's no redirect at all. Trying /context/gateway/ request URL simply gives me 404 error.

My point with this test was to check how /alt/ request works with dispatcher.include() - it wasn't meant to test redirect/lack of redirect for the servlet that acts as a gateway.

@grgrzybek
Copy link
Contributor Author

grgrzybek commented Jul 15, 2020

When I checked:

context.addServlet(gwholder, "/gateway/*");

again, according to my expectations (and Servlet specification), all these requests:

  • /context/gateway
  • /context/gateway/
  • /context/gateway/xxx

are mapped to gateway servlet without redirect and the servlet invokes dispatcher with include for /alt/ path.
But as I said - mapping and checking the gateway servlet itself was not a point of this test - I wanted to test one line:

req.getRequestDispatcher("/alt/").include(req, resp);

:)

@janbartel
Copy link
Contributor

@grgrzybek oh, I think we're talking about different things. I was wanting to check the behaviour at line 377 of ResourceService (which sends a redirect if the request didn't end in '/'). But, as I've confirmed via a test, the redirect wouldn't work from an include anyway, as include is not permitted to mess with the response headers.

So, to sum up: we're good! Thanks for the PR.

@janbartel janbartel merged commit b08fd18 into jetty:jetty-10.0.x Jul 15, 2020
@grgrzybek
Copy link
Contributor Author

Thanks @janbartel for review! yes - I went through include + redirect attempts myself in pax-web 8 ;)

@grgrzybek
Copy link
Contributor Author

@janbartel May I kindly ask for a backport to Jetty 9.4.x too?

janbartel added a commit that referenced this pull request Jul 16, 2020
…nd non-default mapping (#5026)

Signed-off-by: Grzegorz Grzybek <gr.grzybek@gmail.com>
Signed-off-by: Jan Bartel <janb@webtide.com>
@janbartel
Copy link
Contributor

@grgrzybek I knew you were going to ask me to do that :). Done, cherrypicked back to 9.4.x branch just now.

@grgrzybek
Copy link
Contributor Author

Ha :) Thanks - much appreciated!

@grgrzybek
Copy link
Contributor Author

By the way - I don't have test yet, but when checking Jetty / Tomcat / Undertow, I saw that Jetty sets wrong value to javax.servlet.include.context_path attribute when using root context. should be empty string, but is "/". I can think about PR later, but maybe already you have idea if it's wrong? (Undertow and Tomcat set it to "").

@joakime
Copy link
Contributor

joakime commented Jul 16, 2020

@grgrzybek opened issue #5057 about that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants