Getting a 403 on root requests when using a Resour

2019-02-23 18:01发布

In (embedded) Jetty, I'm trying to use a ResourceHandler to serve static files and a custom handler to respond to dynamic requests. Based on this page I have a setup that looks like this:

public static void main(String[] args) throws Exception
{
    Server server = new Server();
    SelectChannelConnector connector = new SelectChannelConnector();
    connector.setPort(8080);
    server.addConnector(connector);

    ResourceHandler resource_handler = new ResourceHandler();
    resource_handler.setDirectoriesListed(false);

    resource_handler.setResourceBase(".");

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler, new MyHandler() });
    server.setHandler(handlers);

    server.start();
    server.join();
}

This works in the sense that it correctly:

  • Serves up static content from files in my public directory, like /public/style.css
  • Runs MyHandler on paths that aren't present in the public directory, like /foo/bar

The problem is that I get a 403 in response to the root path (/). MyHandler is capable of responding to those requests, but they get intercepted by the ResourceHandler first. Is there any way to force Jetty to send / requests to MyHandler?

Thanks in advance!

2条回答
Lonely孤独者°
2楼-- · 2019-02-23 18:42

My solution:

  • put MyHandler on a differnt context path than "/" e.g. "/index"
  • use a rewrite rule to intercept calls to "/" and redirect them to "/index"

The code I use looks like this:

RewriteHandler rewriteHandler = new RewriteHandler();
rewriteHandler.setRewriteRequestURI(true);
rewriteHandler.setRewritePathInfo(false);
rewriteHandler.setOriginalPathAttribute("requestedPath");
RewriteRegexRule rewriteIndex = new RewriteRegexRule();
rewriteIndex.setRegex("^/$");
rewriteIndex.setReplacement("/index.html");
rewriteHandler.addRule(rewriteIndex);
rewriteHandler.setHandler(rootHandlerCollection);
server.setHandler(rewriteHandler);

The regex ensures to only match the exact path, so that "/whatever" is still first handled by the ResourceHandler.

查看更多
仙女界的扛把子
3楼-- · 2019-02-23 18:44

Jetty tries each Handler sequentially until one of the handlers calls setHandled(true) on the request. Not sure why ResourceHandler doesn't do this for "/".

My solution was to reverse the order in which you list the handlers so that yours is called first. Then check for the special case "/" in the URL. If you'd like to pass the request on to the ResourceHandler, simply return without declaring the request as handled.

Declare the order of handlers like this:

Server server = new Server(8080);

CustomHandler default = new CustomHandler();
default.setServer(server);

ResourceHandler files = new ResourceHandler();
files.setServer(server);
files.setResourceBase("./path/to/resources");

HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] {default, files});

server.setHandler(handlers);

server.start();
server.join();

And define CustomHandler's handle method like this:

public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
    if(!request.getRequestURI().equals("/")){
        return;
    }
    // Do Stuff...
    baseRequest.setHandled(true);
    return;
}

I agree it would be most elegant to have ResourceHandler simply yield on "/" instead of handling the response with a 403.

查看更多
登录 后发表回答