Search in sources :

Example 1 with HttpConnectionOverHTTP2

use of org.eclipse.jetty.http2.client.http.HttpConnectionOverHTTP2 in project jetty.project by eclipse.

the class AsyncIOServletTest method testAsyncReadEarlyEOF.

@Test
public void testAsyncReadEarlyEOF() throws Exception {
    // SSLEngine receives the close alert from the client, and when
    // the server passes the response to encrypt and write, SSLEngine
    // only generates the close alert back, without encrypting the
    // response, so we need to skip the transports over TLS.
    Assume.assumeThat(transport, Matchers.not(Matchers.isOneOf(Transport.HTTPS, Transport.H2)));
    String content = "jetty";
    int responseCode = HttpStatus.NO_CONTENT_204;
    CountDownLatch readLatch = new CountDownLatch(content.length());
    CountDownLatch errorLatch = new CountDownLatch(1);
    start(new HttpServlet() {

        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            AsyncContext asyncContext = request.startAsync();
            ServletInputStream input = request.getInputStream();
            input.setReadListener(new ReadListener() {

                @Override
                public void onDataAvailable() throws IOException {
                    while (input.isReady() && !input.isFinished()) {
                        int read = input.read();
                        // System.err.printf("%x%n", read);
                        readLatch.countDown();
                    }
                }

                @Override
                public void onAllDataRead() throws IOException {
                }

                @Override
                public void onError(Throwable x) {
                    response.setStatus(responseCode);
                    asyncContext.complete();
                    errorLatch.countDown();
                }
            });
        }
    });
    CountDownLatch responseLatch = new CountDownLatch(1);
    DeferredContentProvider contentProvider = new DeferredContentProvider();
    contentProvider.offer(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8)));
    org.eclipse.jetty.client.api.Request request = client.newRequest(newURI()).method(HttpMethod.POST).path(servletPath).content(contentProvider).onResponseSuccess(response -> responseLatch.countDown());
    Destination destination = client.getDestination(getScheme(), "localhost", connector.getLocalPort());
    FuturePromise<org.eclipse.jetty.client.api.Connection> promise = new FuturePromise<>();
    destination.newConnection(promise);
    org.eclipse.jetty.client.api.Connection connection = promise.get(5, TimeUnit.SECONDS);
    CountDownLatch clientLatch = new CountDownLatch(1);
    connection.send(request, result -> {
        assertThat(result.getResponse().getStatus(), Matchers.equalTo(responseCode));
        clientLatch.countDown();
    });
    assertTrue(readLatch.await(5, TimeUnit.SECONDS));
    switch(transport) {
        case HTTP:
        case HTTPS:
            ((HttpConnectionOverHTTP) connection).getEndPoint().shutdownOutput();
            break;
        case H2C:
        case H2:
            // In case of HTTP/2, we not only send the request, but also the preface and
            // SETTINGS frames. SETTINGS frame need to be replied, so we want to wait to
            // write the reply before shutting output down, so that the test does not fail.
            Thread.sleep(1000);
            Session session = ((HttpConnectionOverHTTP2) connection).getSession();
            ((HTTP2Session) session).getEndPoint().shutdownOutput();
            break;
        default:
            Assert.fail();
    }
    // Wait for the response to arrive before finishing the request.
    assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
    contentProvider.close();
    assertTrue(errorLatch.await(5, TimeUnit.SECONDS));
    assertTrue(clientLatch.await(5, TimeUnit.SECONDS));
}
Also used : Destination(org.eclipse.jetty.client.api.Destination) AsyncContext(javax.servlet.AsyncContext) HttpConnectionOverHTTP2(org.eclipse.jetty.http2.client.http.HttpConnectionOverHTTP2) Matchers.containsString(org.hamcrest.Matchers.containsString) ReadListener(javax.servlet.ReadListener) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) ServletInputStream(javax.servlet.ServletInputStream) HttpServlet(javax.servlet.http.HttpServlet) FuturePromise(org.eclipse.jetty.util.FuturePromise) Connection(org.eclipse.jetty.io.Connection) HttpServletResponse(javax.servlet.http.HttpServletResponse) UncheckedIOException(java.io.UncheckedIOException) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) DeferredContentProvider(org.eclipse.jetty.client.util.DeferredContentProvider) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) Test(org.junit.Test)

Example 2 with HttpConnectionOverHTTP2

use of org.eclipse.jetty.http2.client.http.HttpConnectionOverHTTP2 in project jetty.project by eclipse.

the class HttpClientTransportOverHTTP2Test method testClientStopsServerDoesNotCloseClientCloses.

@Test
public void testClientStopsServerDoesNotCloseClientCloses() throws Exception {
    try (ServerSocket server = new ServerSocket(0)) {
        List<Session> sessions = new ArrayList<>();
        HTTP2Client h2Client = new HTTP2Client();
        HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client) {

            @Override
            protected HttpConnectionOverHTTP2 newHttpConnection(HttpDestination destination, Session session) {
                sessions.add(session);
                return super.newHttpConnection(destination, session);
            }
        }, null);
        QueuedThreadPool clientExecutor = new QueuedThreadPool();
        clientExecutor.setName("client");
        client.setExecutor(clientExecutor);
        client.start();
        CountDownLatch resultLatch = new CountDownLatch(1);
        client.newRequest("localhost", server.getLocalPort()).send(result -> {
            if (result.getResponse().getStatus() == HttpStatus.OK_200)
                resultLatch.countDown();
        });
        ByteBufferPool byteBufferPool = new MappedByteBufferPool();
        ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
        Generator generator = new Generator(byteBufferPool);
        try (Socket socket = server.accept()) {
            socket.setSoTimeout(1000);
            OutputStream output = socket.getOutputStream();
            InputStream input = socket.getInputStream();
            ServerParser parser = new ServerParser(byteBufferPool, new ServerParser.Listener.Adapter() {

                @Override
                public void onHeaders(HeadersFrame request) {
                    // Server's preface.
                    generator.control(lease, new SettingsFrame(new HashMap<>(), false));
                    // Reply to client's SETTINGS.
                    generator.control(lease, new SettingsFrame(new HashMap<>(), true));
                    // Response.
                    MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
                    HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true);
                    generator.control(lease, response);
                    try {
                        // Write the frames.
                        for (ByteBuffer buffer : lease.getByteBuffers()) output.write(BufferUtil.toArray(buffer));
                    } catch (Throwable x) {
                        x.printStackTrace();
                    }
                }
            }, 4096, 8192);
            byte[] bytes = new byte[1024];
            while (true) {
                try {
                    int read = input.read(bytes);
                    if (read < 0)
                        Assert.fail();
                    parser.parse(ByteBuffer.wrap(bytes, 0, read));
                } catch (SocketTimeoutException x) {
                    break;
                }
            }
            Assert.assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
            // The client will send a GO_AWAY, but the server will not close.
            client.stop();
            // Give some time to process the stop/close operations.
            Thread.sleep(1000);
            Assert.assertTrue(h2Client.getBeans(Session.class).isEmpty());
            for (Session session : sessions) {
                Assert.assertTrue(session.isClosed());
                Assert.assertTrue(((HTTP2Session) session).isDisconnected());
            }
        }
    }
}
Also used : ByteBufferPool(org.eclipse.jetty.io.ByteBufferPool) MappedByteBufferPool(org.eclipse.jetty.io.MappedByteBufferPool) ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) HeadersFrame(org.eclipse.jetty.http2.frames.HeadersFrame) SettingsFrame(org.eclipse.jetty.http2.frames.SettingsFrame) QueuedThreadPool(org.eclipse.jetty.util.thread.QueuedThreadPool) MetaData(org.eclipse.jetty.http.MetaData) HttpFields(org.eclipse.jetty.http.HttpFields) ServerParser(org.eclipse.jetty.http2.parser.ServerParser) InputStream(java.io.InputStream) ServerSocket(java.net.ServerSocket) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuffer(java.nio.ByteBuffer) MappedByteBufferPool(org.eclipse.jetty.io.MappedByteBufferPool) ContentResponse(org.eclipse.jetty.client.api.ContentResponse) HttpServletResponse(javax.servlet.http.HttpServletResponse) SocketTimeoutException(java.net.SocketTimeoutException) HttpClient(org.eclipse.jetty.client.HttpClient) HTTP2Client(org.eclipse.jetty.http2.client.HTTP2Client) HttpDestination(org.eclipse.jetty.client.HttpDestination) ServerSocket(java.net.ServerSocket) Socket(java.net.Socket) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) Generator(org.eclipse.jetty.http2.generator.Generator) Test(org.junit.Test)

Example 3 with HttpConnectionOverHTTP2

use of org.eclipse.jetty.http2.client.http.HttpConnectionOverHTTP2 in project jetty.project by eclipse.

the class HttpClientTransportOverHTTP2Test method testLastStreamId.

@Test
public void testLastStreamId() throws Exception {
    prepareServer(new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), new ServerSessionListener.Adapter() {

        @Override
        public Map<Integer, Integer> onPreface(Session session) {
            Map<Integer, Integer> settings = new HashMap<>();
            settings.put(SettingsFrame.MAX_CONCURRENT_STREAMS, 1);
            return settings;
        }

        @Override
        public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
            MetaData.Request request = (MetaData.Request) frame.getMetaData();
            if (HttpMethod.HEAD.is(request.getMethod())) {
                stream.getSession().close(ErrorCode.REFUSED_STREAM_ERROR.code, null, Callback.NOOP);
            } else {
                MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
                stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP);
            }
            return null;
        }
    }));
    server.start();
    CountDownLatch latch = new CountDownLatch(2);
    AtomicInteger lastStream = new AtomicInteger();
    AtomicReference<Stream> streamRef = new AtomicReference<>();
    CountDownLatch streamLatch = new CountDownLatch(1);
    client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()) {

        @Override
        protected HttpConnectionOverHTTP2 newHttpConnection(HttpDestination destination, Session session) {
            return new HttpConnectionOverHTTP2(destination, session) {

                @Override
                protected HttpChannelOverHTTP2 newHttpChannel(boolean push) {
                    return new HttpChannelOverHTTP2(getHttpDestination(), this, getSession(), push) {

                        @Override
                        public void setStream(Stream stream) {
                            super.setStream(stream);
                            streamRef.set(stream);
                            streamLatch.countDown();
                        }
                    };
                }
            };
        }

        @Override
        protected void onClose(HttpConnectionOverHTTP2 connection, GoAwayFrame frame) {
            super.onClose(connection, frame);
            lastStream.set(frame.getLastStreamId());
            latch.countDown();
        }
    }, null);
    QueuedThreadPool clientExecutor = new QueuedThreadPool();
    clientExecutor.setName("client");
    client.setExecutor(clientExecutor);
    client.start();
    // Prime the connection to allow client and server prefaces to be exchanged.
    ContentResponse response = client.newRequest("localhost", connector.getLocalPort()).path("/zero").timeout(5, TimeUnit.SECONDS).send();
    Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
    org.eclipse.jetty.client.api.Request request = client.newRequest("localhost", connector.getLocalPort()).method(HttpMethod.HEAD).path("/one");
    request.send(result -> {
        if (result.isFailed())
            latch.countDown();
    });
    Assert.assertTrue(streamLatch.await(5, TimeUnit.SECONDS));
    Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
    Stream stream = streamRef.get();
    Assert.assertNotNull(stream);
    Assert.assertEquals(lastStream.get(), stream.getId());
}
Also used : HashMap(java.util.HashMap) ContentResponse(org.eclipse.jetty.client.api.ContentResponse) HttpConfiguration(org.eclipse.jetty.server.HttpConfiguration) HeadersFrame(org.eclipse.jetty.http2.frames.HeadersFrame) QueuedThreadPool(org.eclipse.jetty.util.thread.QueuedThreadPool) MetaData(org.eclipse.jetty.http.MetaData) HttpFields(org.eclipse.jetty.http.HttpFields) Stream(org.eclipse.jetty.http2.api.Stream) OutputStream(java.io.OutputStream) InputStream(java.io.InputStream) Request(org.eclipse.jetty.server.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) GoAwayFrame(org.eclipse.jetty.http2.frames.GoAwayFrame) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ContentResponse(org.eclipse.jetty.client.api.ContentResponse) HttpServletResponse(javax.servlet.http.HttpServletResponse) RawHTTP2ServerConnectionFactory(org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HttpClient(org.eclipse.jetty.client.HttpClient) HTTP2Client(org.eclipse.jetty.http2.client.HTTP2Client) HttpDestination(org.eclipse.jetty.client.HttpDestination) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) Test(org.junit.Test)

Aggregations

CountDownLatch (java.util.concurrent.CountDownLatch)3 HttpServletResponse (javax.servlet.http.HttpServletResponse)3 HTTP2Session (org.eclipse.jetty.http2.HTTP2Session)3 Session (org.eclipse.jetty.http2.api.Session)3 Test (org.junit.Test)3 InputStream (java.io.InputStream)2 OutputStream (java.io.OutputStream)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2 HttpClient (org.eclipse.jetty.client.HttpClient)2 HttpDestination (org.eclipse.jetty.client.HttpDestination)2 ContentResponse (org.eclipse.jetty.client.api.ContentResponse)2 HttpFields (org.eclipse.jetty.http.HttpFields)2 MetaData (org.eclipse.jetty.http.MetaData)2 HTTP2Client (org.eclipse.jetty.http2.client.HTTP2Client)2 HeadersFrame (org.eclipse.jetty.http2.frames.HeadersFrame)2 QueuedThreadPool (org.eclipse.jetty.util.thread.QueuedThreadPool)2 IOException (java.io.IOException)1 InterruptedIOException (java.io.InterruptedIOException)1 UncheckedIOException (java.io.UncheckedIOException)1 ServerSocket (java.net.ServerSocket)1