jetty / jetty.project

Eclipse Jetty® - Web Container & Clients - supports HTTP/2, HTTP/1.1, HTTP/1.0, websocket, servlets, and more
https://eclipse.dev/jetty
Other
3.86k stars 1.91k forks source link

DefaultServlet vs ResourceServlet #12476

Open sbernard31 opened 1 week ago

sbernard31 commented 1 week ago

Jetty Version 12.0.14

Jetty Environment ee10

Java Version 17

Question

I try to migrate from jetty 9 to 12. And It seems migration is pretty smooth :+1: but I get this warning :

2024-11-04 16:05:43,996 DefaultServlet       [WARN] DefaultServlet pathInfoOnly is set to true. Use ResourceServlet instead.  
2024-11-04 16:06:09,081 DefaultServlet       [WARN] Incorrect mapping for DefaultServlet at /*. Use ResourceServlet  

Until now, I was using DefaultServlet as a way to serve static resource. (without really understand the concept) With jetty12/ee10, I understand that I should rather use a ResourceServlet for that.

This lead me to the question what is the purpose of DefaultServlet ? I read lot about this but still not clear to me:

I describe my use case in case it helps. I use jetty programmatically without using xml configuration. I serve static resource from webapp directory of the jar of my java application and I have some REST API under /api/*

You can have a look at the code jetty 9 code and or jetty 12 version one (almost the same) from https://github.com/eclipse-leshan/leshan/pull/1667.

janbartel commented 1 week ago

@sbernard31 have also a read of https://github.com/jetty/jetty.project/issues/10296. In previous versions of jetty, we had users configuring a DefaultServlet instance to serve static content other than what the DefaultServlet with pathMapping of / would normally serve. It was very complex to code to handle a last-resort mapping of /, but also another mapping of /foo/*, especially where welcome files etc were involved. To fix this headache, we split the DefaultServlet so it is now a specialization of the general ResourceServlet. The DefaultServlet should be left mapped as /. You can use the ResourceServlet instead to serve other content from a different mapping.

sbernard31 commented 1 week ago

@janbartel

Thx a lot for quick answer. So I get in my case, as I want to map static resource on /, I need to use DefaultServlet. Maybe to clarify this is should be renamed : RootResourceServlet ?

A last question to define where are the resource on the server. Before I was using :

staticHolder.setInitParameter("resourceBase",
         LeshanServerDemo.class.getClassLoader().getResource("webapp").toExternalForm());

Now, this is deprecated and I need to use :

staticHolder.setInitParameter("baseResource",
         LeshanServerDemo.class.getClassLoader().getResource("webapp").toExternalForm());

But I also see there is a :

 ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
  context.setBaseResource(myResource));

What is the purpose of that API ? (What means to set a BaseResource on a context :thinking: ) Javadoc says :

Set the base resource to serve content from for this context, which must exist and be readable when the context is started.

but this is not clear to me.

janbartel commented 2 days ago

@sbernard31 we have always supported ContextHandler.setBaseResource method in jetty (although several versions ago we may have changed from setResourceBase. For WebAppContexts it is automatically set from the value of the parameter to setWar. For ServletContextHandlers you have to set it yourself and this will form the root of the static resources for the DefaultServlet/ResourceServlet to serve. Alternatively, you can explicitly set it to some other value on the DefaultServlet/ResourceServlet using the init params.

sbernard31 commented 1 day ago

Ok so in my case where I have only 1 DefaultServlet in my context, this is exactly the same to do :

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setBaseResource(myResourceAtGivenUri));

or

staticHolder.setInitParameter("baseResource",UriAsStringOfMyResource);