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 with Configuring Specific Static Resources in the same base directory ee10 jetty 12.0.10 #11880

Closed
Emilyserap opened this issue Jun 6, 2024 · 19 comments
Labels
Bug For general bugs on Jetty side

Comments

@Emilyserap
Copy link

Emilyserap commented Jun 6, 2024

Jetty version(s)
12.0.10

Jetty Environment
ee10

Java version/vendor
17

Description
I am encountering an issue while configuring specific static resources in the same base directory. When I try to access these resources, I receive a HTTP ERROR 404 Not Found

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");

ResourceFactory resourceFactory = ResourceFactory.of(context);
context.setBaseResource(resourceFactory.newResource(mainResourceBase));

ServletHolder holderAlt = new ServletHolder("static", DefaultServlet.class);
holderAlt.setInitParameter("dirAllowed", "true");
holderAlt.setInitParameter("acceptRanges", "true");
context.addServlet(holderAlt, "/index.html");

ServletHolder holderDef = new ServletHolder("default", DefaultServlet.class);
holderDef.setInitParameter("dirAllowed", "true");
context.addServlet(holderDef, "/")
@Emilyserap Emilyserap added the Bug For general bugs on Jetty side label Jun 6, 2024
@Emilyserap Emilyserap changed the title Issue with Configuring Specific Static Resources Issue with Configuring Specific Static Resources ee10 jetty 12.0.10 Jun 6, 2024
@janbartel
Copy link
Contributor

Can you show examples of resource requests that fail?

@Emilyserap
Copy link
Author

The issue only serving the /index.html

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

Call server.setDumpAfterStart(true); before server.start(); and verify that there is a Base Resource.

I say this, because you are not checking that the line resourceFactory.newResource(mainResourceBase) is returning null (such as if it cannot find that resource).

What is mainResourceBase btw?

@Emilyserap
Copy link
Author

Emilyserap commented Jun 6, 2024

resourceFactory.newResource(mainResourceBase) is not returning null. I tested the same code in Jetty EE9, and it works correctly; I can access the request /index.html. Therefore, I think the problem is in the class DefaultServlet.java EE10.
image

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

You are using Windows (and important thing to note when working with File System issues on Java).

Can you access some of the static resources? or none of them?
If you enable DEBUG logging do you see any mentions of "alias" issues?
In the path D:\eclipse-workspace\Jetty12authEE10\bin\main\static-root\ are any of those path sub-entries a link? (hard / soft / fs / etc)

Is the path D:\eclipse-workspace\Jetty12authEE10\bin\main\static-root\ using the exact case (as stored on disk) of each sub-entry in that path? (if you are being lazy and using C:\foo\bar when the actual directories are C:\Foo\Bar then this would trigger all sorts of security features and alias checking behaviors as the paths are not exactly the same. (This also goes for the requested resources within that base resource. eg: don't request /index.html if the stored on disk file is Index.Html)

@Emilyserap
Copy link
Author

Emilyserap commented Jun 6, 2024

I can access to all the static resources except index.html. For example, I can access to static resources that end with .js. However, I can't access the static resource index.html. Here is my configuration:

Server server = new Server();
		ServerConnector connector = new ServerConnector(server);
		connector.setPort(8080);
		server.addConnector(connector);
		URI webRootUri = findDefaultBaseResource();
		System.err.println("Default Base Resource is " + webRootUri);

		ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS | 
                ServletContextHandler.SECURITY);
		context.setContextPath("/welcome");
		ResourceFactory resourceFactory = ResourceFactory.of(context);
		context.setBaseResource(resourceFactory.newResource(webRootUri));

		final var holderJs = new ServletHolder("js", DefaultServlet.class);
		holderJs.setInitParameter("dirAllowed", "true");
		holderJs.setInitParameter("cacheControl", "public, max-age=0, must-revalidate");

		context.addServlet(holderJs, "*.js"); // Map to all paths ending with .js
		ServletHolder holderAlt = new ServletHolder("static", DefaultServlet.class);
		holderAlt.setInitParameter("dirAllowed", "false");

		holderAlt.setInitParameter("cacheControl", "no-store");
		context.addServlet(holderAlt, "/index.html");
		ServletHolder holderDef = new ServletHolder("default", DefaultServlet.class);
		holderDef.setInitParameter("dirAllowed", "true");
		context.addServlet(holderDef, "/");
		server.setHandler(context);
		server.start();
		server.join();`

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

Can you please copy/paste?
Don't use screenshots / images, as it doesn't help others in the future. (people searching for help cannot find similar issues).
Also, it doesn't help us when helping you.

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

You only need 1 DefaultServlet and it will always be mapped to / (no other url-pattern).
Get rid of the other ones.

If you want welcome file behavior, use one of the ServletContextHandler.setWelcomeFiles() methods.

@Emilyserap
Copy link
Author

Emilyserap commented Jun 6, 2024

If I want to specify a configuration for the static resource index.html, for example, or for other resources ending with .js, because not all of them have the same InitParameter?

ServletHolder holderAlt = new ServletHolder("static", DefaultServlet.class);
holderAlt.setInitParameter("dirAllowed", "false");
holderAlt.setInitParameter("cacheControl", "no-store");
context.addServlet(holderAlt, "/index.html");
ServletHolder holderDef = new ServletHolder("default", DefaultServlet.class);
holderDef.setInitParameter("dirAllowed", "true");
context.addServlet(holderDef, "/");

For the static resource index.html, we have set .setInitParameter("dirAllowed", "false"); and for the default, we have set .setInitParameter("dirAllowed", "true");

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

If I want to specify a configuration for the static resource index.html, for example, or for other resources ending with .js, because not all of them have the same InitParameter

DefaultServlet does not work with url-patterns that are absolute-path (eg: /index.html), or suffix based (eg: *.js). It only works with default (eg: /) or directory-prefix (eg: /static/*)

@Emilyserap
Copy link
Author

Emilyserap commented Jun 6, 2024

so I cannot assign special configurations for non-default DefaultServlets?
But I don't understand if the problem is related to class DefaultServlet in Jetty 12 ee10, because the same code worked in Jetty 12 ee9, allowing access to all resources, including index.html with specific configuration to the index.html

@joakime
Copy link
Contributor

joakime commented Jun 6, 2024

so I cannot assign special configurations for non-default DefaultServlets?

You can, but there are restrictions.

  • Extra configurations MUST be done on new DefaultServlet instances (you cannot reuse the ServletHolder)
  • Extra DefaultServlet instances only support url-patterns defined as either ...
    1. default pattern: only /
    2. prefix directory pattern: eg: /static/* or /css/* or /scripts/*, but not /foo.* as that's not a directory.
  • Each new DefaultServlet needs it's own Base Resource

See example at https://github.com/jetty/jetty-examples/blob/12.0.x/embedded/ee10-file-server/src/main/java/examples/ServletFileServerMultipleLocations.java

@Emilyserap Emilyserap changed the title Issue with Configuring Specific Static Resources ee10 jetty 12.0.10 Issue with Configuring Specific Static Resources the same base directory ee10 jetty 12.0.10 Jun 6, 2024
@Emilyserap Emilyserap changed the title Issue with Configuring Specific Static Resources the same base directory ee10 jetty 12.0.10 Issue with Configuring Specific Static Resources in the same base directory ee10 jetty 12.0.10 Jun 6, 2024
@Emilyserap
Copy link
Author

Emilyserap commented Jun 7, 2024

so I cannot assign special configurations for non-default DefaultServlets?

You can, but there are restrictions.

  • Extra configurations MUST be done on new DefaultServlet instances (you cannot reuse the ServletHolder)

  • Extra DefaultServlet instances only support url-patterns defined as either ...

    1. default pattern: only /
    2. prefix directory pattern: eg: /static/* or /css/* or /scripts/*, but not /foo.* as that's not a directory.
  • Each new DefaultServlet needs it's own Base Resource

See example at https://github.com/jetty/jetty-examples/blob/12.0.x/embedded/ee10-file-server/src/main/java/examples/ServletFileServerMultipleLocations.java

Thanks for this information. so If I need to configure the static resource index.html, I must place this file in a different base resource and then add the baseResource parameter to the ServletHolder

@joakime
Copy link
Contributor

joakime commented Jun 7, 2024

The static resource /index.html is served by the servlet default url-pattern of /.

Why do you need an entirely separate DefaultServlet for a precise / absolute-path url-pattern?
It makes no sense to have a DefaultServlet mapping for that.

@Emilyserap
Copy link
Author

I see a serious regression with the DefaultServlet in EE10 compared to EE9.
I think the problem is in the DefaultServlet class and it affects the DefaultServlet when serving a single, unique file. Please refer to this issue #11791

@joakime
Copy link
Contributor

joakime commented Jun 7, 2024

Why do you need that?
Don't get hung up on the process, don't get caught up in the details, what's important to know is the end result.

If it's just for Cache-Control, then you are doing this entirely in the wrong place, as Cache-Control is applied to all resources in the entire Base Resource, not specific entries based on the DefaultServlet. (the Cache-Control init-param in DefaultServlet just configures the low level ResourceService which handles serving content from the Base Resource)

The whole point of serving static files from DefaultServlet is to serve them from a Base Resource.
If you hardcode an absolute url-pattern then that will not be served from the Base Resource in the way you expect.

Take this for example...

  • Base Resource: C:\data\webroot\
  • Context-Path: /app
  • Default Servlet URL Pattern: /
  • HTTP Request Path: /app/css/main.css

That request will result in a lookup against the Base Resource + (Path-In-Context).
The Path-In-Context is the path that is left over after you remove the Context-Path, and the url-pattern.
So that would mean C:\data\webroot\ + /css/main.css
Meaning that C:\data\webroot\css\main.css is what is served.

If you have an absolute-path url-pattern of say /index.html, and the request is /app/index.html, the Path-In-Context is `` (blank) as the url-pattern is excluded.
The lookup will attempt to load from Base Resource the file C:\data\webroot\, which wont work.

Then with all of this you are still not handling welcome file logic at all with your Cache-Control.
The user could use the request path /app/ and the welcome files logic will serve /index.html which wouldn't apply your custom Cache-Control either.

If you have specific Cache-Control behavior, that's not handled via DefaultServlet configuration, but rather by paying attention to the Response Content-Type and from where that response was generated (eg: the request path, but don't forget about welcome-files logic!). This is typically done via custom Servlet filters setup against specific paths.

@janbartel
Copy link
Contributor

@Emilyserap see my comment over on this other issue here: #11884 (comment). It's not a regression, ee10 is not trying to be bug-for-bug compatible with previous versions. We are attempting to clean up the DefaultServlet. I think the piece we are missing is the ResourceServlet (see #10738) that in the meanwhile can probably be worked around via the ResourceHandler (see linked comment for a link to the doco).

@Emilyserap
Copy link
Author

@Emilyserap see my comment over on this other issue here: #11884 (comment). It's not a regression, ee10 is not trying to be bug-for-bug compatible with previous versions. We are attempting to clean up the DefaultServlet. I think the piece we are missing is the ResourceServlet (see #10738) that in the meanwhile can probably be worked around via the ResourceHandler (see linked comment for a link to the doco).

Thanks for the explanation. Otherwise, when will the ResourceServlet be ready?

@janbartel
Copy link
Contributor

@Emilyserap #11933 has been merged into jetty-12.0.x, so should be part of this month's 12.0.12 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side
Projects
None yet
Development

No branches or pull requests

3 participants