Fixes #481 - Event response.success notified without waiting for content callback for HTTP/2 transport.

Fixed by notifying the response.success event only when the callback
is succeeded.
This commit is contained in:
Simone Bordet 2016-04-04 15:40:25 +02:00
parent c1997b40a5
commit 5c147288ef
3 changed files with 39 additions and 7 deletions

View File

@ -307,6 +307,7 @@ public abstract class HttpReceiver
} }
default: default:
{ {
callback.failed(new IllegalStateException("Invalid response state " + current));
return false; return false;
} }
} }

View File

@ -117,6 +117,8 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listen
{ {
byteBufferPool.release(copy); byteBufferPool.release(copy);
super.succeeded(); super.succeeded();
if (frame.isEndStream())
responseSuccess(exchange);
} }
@Override @Override
@ -127,11 +129,7 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listen
} }
}; };
if (responseContent(exchange, copy, delegate)) responseContent(exchange, copy, delegate);
{
if (frame.isEndStream())
responseSuccess(exchange);
}
} }
@Override @Override

View File

@ -19,9 +19,11 @@
package org.eclipse.jetty.http.client; package org.eclipse.jetty.http.client;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -33,15 +35,16 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.BytesContentProvider; import org.eclipse.jetty.client.util.BytesContentProvider;
import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http2.FlowControlStrategy; import org.eclipse.jetty.http2.FlowControlStrategy;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -372,6 +375,36 @@ public class HttpClientTest extends AbstractTest
Assert.assertEquals(HttpStatus.OK_200, response.getStatus()); Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
} }
@Test
public void testDownloadWithInputStreamResponseListener() throws Exception
{
String content = "hello world";
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
response.getOutputStream().print(content);
}
});
CountDownLatch latch = new CountDownLatch(1);
InputStreamResponseListener listener = new InputStreamResponseListener();
client.newRequest("localhost", connector.getLocalPort())
.scheme(getScheme())
.onResponseSuccess(response -> latch.countDown())
.send(listener);
Response response = listener.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response.getStatus());
// Response cannot succeed until we read the content.
Assert.assertFalse(latch.await(500, TimeUnit.MILLISECONDS));
InputStream input = listener.getInputStream();
Assert.assertEquals(content, IO.toString(input));
}
private void sleep(long time) throws IOException private void sleep(long time) throws IOException
{ {
try try