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

Can JettyHttpContainer check if request has already been satisfied? #4262

Closed
dbazile opened this issue Sep 16, 2019 · 1 comment
Closed

Can JettyHttpContainer check if request has already been satisfied? #4262

dbazile opened this issue Sep 16, 2019 · 1 comment

Comments

@dbazile
Copy link
Contributor

dbazile commented Sep 16, 2019

Can the following guard be added to JettyHttpContainer::handle()?

--- JettyHttpContainer.java~	2019-09-16 15:24:40.122554831 -0400
+++ JettyHttpContainer.java	2019-09-16 15:25:42.137656034 -0400
@@ -137,6 +137,10 @@
     public void handle(final String target, final Request request, final HttpServletRequest httpServletRequest,
                        final HttpServletResponse httpServletResponse) throws IOException, ServletException {
 
+        if (request.isHandled()) {
+            return;
+        }
+
         final Response response = request.getResponse();
         final ResponseWriter responseWriter = new ResponseWriter(request, response, configSetStatusOverSendError);
         final URI baseUri = getBaseUri(request);

Currently, if JettyHttpContainer occurs downstream of a set of handlers, one of which satisfies a request, it will throw an EOFException when it tries to write to the response.

Background

I have an embedded Jetty application that has a HandlerCollection containing the following two handlers in the order shown below:

Whenever ResourceHandler successfully handles an incoming request for a static file and closes the response, JettyHttpConnector tries to "re-handle" the request without seeing that it's already handled. When it tries to write to the response output stream, an EOFException is thrown:

Sep 16, 2019 2:55:39 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
org.glassfish.jersey.server.internal.process.MappableException: org.eclipse.jetty.io.EofException: Closed
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:91)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:662)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:395)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:441)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:285)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
    at org.glassfish.jersey.jetty.JettyHttpContainer.handle(JettyHttpContainer.java:190)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:502)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:748)

Here is a snippet of the guard mechanism ResourceHandler uses to prevent clobbering the response of an upstream handler:

    /*
     * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
     */
    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        if (baseRequest.isHandled())
            return;

        if (!HttpMethod.GET.is(request.getMethod()) && !HttpMethod.HEAD.is(request.getMethod()))
        {
            // try another handler
            super.handle(target, baseRequest, request, response);
            return;
        }

        if (_resourceService.doGet(request, response))
            baseRequest.setHandled(true);
        else
            // no resource - try other handlers
            super.handle(target, baseRequest, request, response);
    }

Versions

compile 'org.eclipse.jetty:jetty-server:9.4.14.v20181114'
compile 'org.glassfish.jersey.core:jersey-server:2.26'
compile 'org.glassfish.jersey.inject:jersey-hk2:2.26'
compile 'org.glassfish.jersey.containers:jersey-container-jetty-http:2.26'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.26'
@jansupol
Copy link
Contributor

Sounds reasonable, feel free to provide a PR

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

No branches or pull requests

2 participants