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:
{
callback.failed(new IllegalStateException("Invalid response state " + current));
return false;
}
}

View File

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

View File

@ -19,9 +19,11 @@
package org.eclipse.jetty.http.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.EnumSet;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
@ -33,15 +35,16 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.FutureResponseListener;
import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http2.FlowControlStrategy;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
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.thread.QueuedThreadPool;
import org.hamcrest.Matchers;
@ -372,6 +375,36 @@ public class HttpClientTest extends AbstractTest
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
{
try