use of org.eclipse.jetty.http2.frames.HeadersFrame in project jetty.project by eclipse.
the class StreamResetTest method testServerExceptionConsumesQueuedData.
@Test
public void testServerExceptionConsumesQueuedData() throws Exception {
try (StacklessLogging suppressor = new StacklessLogging(HttpChannel.class)) {
start(new HttpServlet() {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// Wait to let the data sent by the client to be queued.
Thread.sleep(1000);
throw new IllegalStateException("explictly_thrown_by_test");
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
}
});
Session client = newClient(new Session.Listener.Adapter());
Log.getLogger(HttpChannel.class).info("Expecting java.lang.IllegalStateException: explictly_thrown_by_test");
MetaData.Request request = newRequest("GET", new HttpFields());
HeadersFrame frame = new HeadersFrame(request, null, false);
FuturePromise<Stream> promise = new FuturePromise<>();
client.newStream(frame, promise, new Stream.Listener.Adapter());
Stream stream = promise.get(5, TimeUnit.SECONDS);
ByteBuffer data = ByteBuffer.allocate(FlowControlStrategy.DEFAULT_WINDOW_SIZE);
CountDownLatch dataLatch = new CountDownLatch(1);
stream.data(new DataFrame(stream.getId(), data, false), new Callback() {
@Override
public void succeeded() {
dataLatch.countDown();
}
});
// The server does not read the data, so the flow control window should be zero.
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
Assert.assertEquals(0, ((ISession) client).updateSendWindow(0));
// Wait for the server process the exception, and
// for the client to process the window updates.
Thread.sleep(2000);
Assert.assertThat(((ISession) client).updateSendWindow(0), Matchers.greaterThan(0));
}
}
use of org.eclipse.jetty.http2.frames.HeadersFrame in project jetty.project by eclipse.
the class StreamResetTest method testBlockingWriteAfterStreamReceivingReset.
@Test
public void testBlockingWriteAfterStreamReceivingReset() throws Exception {
final CountDownLatch resetLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
start(new HttpServlet() {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Charset charset = StandardCharsets.UTF_8;
byte[] data = "AFTER RESET".getBytes(charset);
response.setStatus(200);
response.setContentType("text/plain;charset=" + charset.name());
response.setContentLength(data.length * 10);
response.flushBuffer();
try {
// Wait for the reset to happen.
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
} catch (InterruptedException x) {
throw new InterruptedIOException();
}
try {
// been reset, it should throw an exception.
for (int i = 0; i < 10; i++) {
Thread.sleep(500);
response.getOutputStream().write(data);
response.flushBuffer();
}
} catch (InterruptedException x) {
} catch (IOException x) {
dataLatch.countDown();
}
}
});
Session client = newClient(new Session.Listener.Adapter());
MetaData.Request request = newRequest("GET", new HttpFields());
HeadersFrame frame = new HeadersFrame(request, null, true);
client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
stream.reset(new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code), Callback.NOOP);
resetLatch.countDown();
}
});
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
}
use of org.eclipse.jetty.http2.frames.HeadersFrame in project jetty.project by eclipse.
the class StreamResetTest method testStreamReceivingResetIsRemoved.
@Test
public void testStreamReceivingResetIsRemoved() throws Exception {
final AtomicReference<Stream> streamRef = new AtomicReference<>();
final CountDownLatch resetLatch = new CountDownLatch(1);
start(new ServerSessionListener.Adapter() {
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
return new Stream.Listener.Adapter() {
@Override
public void onReset(Stream stream, ResetFrame frame) {
Assert.assertNotNull(stream);
Assert.assertTrue(stream.isReset());
streamRef.set(stream);
resetLatch.countDown();
}
};
}
});
Session client = newClient(new Session.Listener.Adapter());
MetaData.Request request = newRequest("GET", new HttpFields());
HeadersFrame requestFrame = new HeadersFrame(request, null, false);
FuturePromise<Stream> promise = new FuturePromise<>();
client.newStream(requestFrame, promise, new Stream.Listener.Adapter());
Stream stream = promise.get(5, TimeUnit.SECONDS);
ResetFrame resetFrame = new ResetFrame(stream.getId(), ErrorCode.CANCEL_STREAM_ERROR.code);
stream.reset(resetFrame, Callback.NOOP);
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
// Wait a while to let the server remove the
// stream after returning from onReset().
Thread.sleep(1000);
Stream serverStream = streamRef.get();
Assert.assertEquals(0, serverStream.getSession().getStreams().size());
}
use of org.eclipse.jetty.http2.frames.HeadersFrame in project jetty.project by eclipse.
the class AsyncIOTest method testSomeContentAvailableAfterServiceReturns.
@Test
public void testSomeContentAvailableAfterServiceReturns() throws Exception {
final AtomicInteger count = new AtomicInteger();
start(new HttpServlet() {
@Override
protected void service(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
request.getInputStream().setReadListener(new EmptyReadListener() {
@Override
public void onDataAvailable() throws IOException {
count.incrementAndGet();
ServletInputStream input = request.getInputStream();
while (input.isReady()) {
int read = input.read();
if (read < 0)
break;
}
if (input.isFinished())
asyncContext.complete();
}
});
}
});
Session session = newClient(new Session.Listener.Adapter());
HttpFields fields = new HttpFields();
MetaData.Request metaData = newRequest("GET", fields);
HeadersFrame frame = new HeadersFrame(metaData, null, false);
final CountDownLatch latch = new CountDownLatch(1);
FuturePromise<Stream> promise = new FuturePromise<>();
session.newStream(frame, promise, new Stream.Listener.Adapter() {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
if (frame.isEndStream())
latch.countDown();
}
});
Stream stream = promise.get(5, TimeUnit.SECONDS);
// Wait until service() returns.
Thread.sleep(1000);
stream.data(new DataFrame(stream.getId(), ByteBuffer.allocate(1), false), Callback.NOOP);
// Wait until onDataAvailable() returns.
Thread.sleep(1000);
stream.data(new DataFrame(stream.getId(), ByteBuffer.allocate(1), true), Callback.NOOP);
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
// Make sure onDataAvailable() has been called twice
Assert.assertEquals(2, count.get());
}
use of org.eclipse.jetty.http2.frames.HeadersFrame in project jetty.project by eclipse.
the class PushCacheFilterTest method testPush.
@Test
public void testPush() throws Exception {
final String primaryResource = "/primary.html";
final String secondaryResource = "/secondary.png";
final byte[] secondaryData = "SECONDARY".getBytes("UTF-8");
start(new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req.getRequestURI();
ServletOutputStream output = resp.getOutputStream();
if (requestURI.endsWith(primaryResource))
output.print("<html><head></head><body>PRIMARY</body></html>");
else if (requestURI.endsWith(secondaryResource))
output.write(secondaryData);
}
});
final Session session = newClient(new Session.Listener.Adapter());
// Request for the primary and secondary resource to build the cache.
final String referrerURI = newURI(primaryResource);
HttpFields primaryFields = new HttpFields();
MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields);
final CountDownLatch warmupLatch = new CountDownLatch(1);
session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() {
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
callback.succeeded();
if (frame.isEndStream()) {
// Request for the secondary resource.
HttpFields secondaryFields = new HttpFields();
secondaryFields.put(HttpHeader.REFERER, referrerURI);
MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields);
session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() {
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
callback.succeeded();
warmupLatch.countDown();
}
});
}
}
});
Assert.assertTrue(warmupLatch.await(5, TimeUnit.SECONDS));
// Request again the primary resource, we should get the secondary resource pushed.
primaryRequest = newRequest("GET", primaryResource, primaryFields);
final CountDownLatch primaryResponseLatch = new CountDownLatch(2);
final CountDownLatch pushLatch = new CountDownLatch(2);
session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
MetaData.Response response = (MetaData.Response) frame.getMetaData();
if (response.getStatus() == HttpStatus.OK_200)
primaryResponseLatch.countDown();
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
callback.succeeded();
if (frame.isEndStream())
primaryResponseLatch.countDown();
}
@Override
public Stream.Listener onPush(Stream stream, PushPromiseFrame frame) {
return new Adapter() {
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
MetaData.Response response = (MetaData.Response) frame.getMetaData();
if (response.getStatus() == HttpStatus.OK_200)
pushLatch.countDown();
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
callback.succeeded();
if (frame.isEndStream())
pushLatch.countDown();
}
};
}
});
Assert.assertTrue(pushLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS));
}
Aggregations