diff --git a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpExchange.java b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpExchange.java index 4b475e4fead..fed75817361 100644 --- a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpExchange.java +++ b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpExchange.java @@ -62,7 +62,7 @@ public class HttpExchange // TODO } - public void responseDone() + public void responseDone(boolean success) { // TODO } diff --git a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpReceiver.java b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpReceiver.java index 69e7aac8ff0..1fb0f45a302 100644 --- a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpReceiver.java +++ b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpReceiver.java @@ -23,6 +23,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler private final AtomicReference exchange = new AtomicReference<>(); private final AtomicReference listener = new AtomicReference<>(); private final HttpConnection connection; + private boolean failed; public HttpReceiver(HttpConnection connection) { @@ -113,21 +114,23 @@ public class HttpReceiver implements HttpParser.ResponseHandler @Override public boolean messageComplete(long contentLength) { - success(); + if (!failed) + success(); return false; } protected void success() { HttpExchange exchange = this.exchange.getAndSet(null); - exchange.responseDone(); + exchange.responseDone(true); notifySuccess(listener.get(), exchange.response()); } protected void fail(Throwable failure) { + failed = true; HttpExchange exchange = this.exchange.getAndSet(null); - exchange.responseDone(); + exchange.responseDone(false); notifyFailure(listener.get(), exchange.response(), failure); } diff --git a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpSender.java b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpSender.java index 6729c73a12a..845f84923f3 100644 --- a/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpSender.java +++ b/jetty-client-new/src/main/java/org/eclipse/jetty/client/HttpSender.java @@ -105,8 +105,6 @@ public class HttpSender header = BufferUtil.EMPTY_BUFFER; if (chunk == null) chunk = BufferUtil.EMPTY_BUFFER; - if (content == null) - content = BufferUtil.EMPTY_BUFFER; endPoint.write(null, callback, header, chunk, content); if (callback.pending()) return; diff --git a/jetty-client-new/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java b/jetty-client-new/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java index 996a7d4142a..48ad25c5bba 100644 --- a/jetty-client-new/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java +++ b/jetty-client-new/src/test/java/org/eclipse/jetty/client/HttpReceiverTest.java @@ -1,162 +1,187 @@ package org.eclipse.jetty.client; +import java.io.EOFException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.io.ByteArrayEndPoint; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + public class HttpReceiverTest { -// private HttpClient client; -// -// @Before -// public void init() throws Exception -// { -// client = new HttpClient(); -// client.start(); -// } -// -// @After -// public void destroy() throws Exception -// { -// client.stop(); -// } -// -// @Test -// public void test_Receive_NoResponseContent() throws Exception -// { -// ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); -// HttpConnection connection = new HttpConnection(client, endPoint); -// endPoint.setInput("" + -// "HTTP/1.1 200 OK\r\n" + -// "Content-length: 0\r\n" + -// "\r\n"); -// final AtomicReference responseRef = new AtomicReference<>(); -// final CountDownLatch latch = new CountDownLatch(1); -// HttpReceiver receiver = new HttpReceiver(connection); -// HttpExchange exchange = new HttpExchange(); -// , null, new Response.Listener.Adapter() -// { -// @Override -// public void onSuccess(Response response) -// { -// responseRef.set(response); -// latch.countDown(); -// } -// }); -// receiver.receive(connection); -// -// Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); -// Response response = responseRef.get(); -// Assert.assertNotNull(response); -// Assert.assertEquals(200, response.status()); -// Assert.assertEquals("OK", response.reason()); -// Assert.assertSame(HttpVersion.HTTP_1_1, response.version()); -// HttpFields headers = response.headers(); -// Assert.assertNotNull(headers); -// Assert.assertEquals(1, headers.size()); -// Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH)); -// } -// -// @Test -// public void test_Receive_ResponseContent() throws Exception -// { -// ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); -// HttpConnection connection = new HttpConnection(client, endPoint); -// String content = "0123456789ABCDEF"; -// endPoint.setInput("" + -// "HTTP/1.1 200 OK\r\n" + -// "Content-length: " + content.length() + "\r\n" + -// "\r\n" + -// content); -// BufferingResponseListener listener = new BufferingResponseListener(); -// HttpReceiver receiver = new HttpReceiver(connection, null, listener); -// receiver.receive(connection); -// -// Response response = listener.await(5, TimeUnit.SECONDS); -// Assert.assertNotNull(response); -// Assert.assertEquals(200, response.status()); -// Assert.assertEquals("OK", response.reason()); -// Assert.assertSame(HttpVersion.HTTP_1_1, response.version()); -// HttpFields headers = response.headers(); -// Assert.assertNotNull(headers); -// Assert.assertEquals(1, headers.size()); -// Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH)); -// String received = listener.contentAsString("UTF-8"); -// Assert.assertEquals(content, received); -// } -// -// @Test -// public void test_Receive_ResponseContent_EarlyEOF() throws Exception -// { -// ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); -// HttpConnection connection = new HttpConnection(client, endPoint); -// String content1 = "0123456789"; -// String content2 = "ABCDEF"; -// endPoint.setInput("" + -// "HTTP/1.1 200 OK\r\n" + -// "Content-length: " + (content1.length() + content2.length()) + "\r\n" + -// "\r\n" + -// content1); -// BufferingResponseListener listener = new BufferingResponseListener(); -// HttpReceiver receiver = new HttpReceiver(connection, null, listener); -// receiver.receive(connection); -// endPoint.setInputEOF(); -// receiver.receive(connection); -// -// try -// { -// listener.await(5, TimeUnit.SECONDS); -// Assert.fail(); -// } -// catch (ExecutionException e) -// { -// Assert.assertTrue(e.getCause() instanceof EOFException); -// } -// } -// -// @Test -// public void test_Receive_ResponseContent_IdleTimeout() throws Exception -// { -// ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); -// HttpConnection connection = new HttpConnection(client, endPoint); -// endPoint.setInput("" + -// "HTTP/1.1 200 OK\r\n" + -// "Content-length: 1\r\n" + -// "\r\n"); -// BufferingResponseListener listener = new BufferingResponseListener(); -// HttpReceiver receiver = new HttpReceiver(connection, null, listener); -// receiver.receive(connection); -// // Simulate an idle timeout -// receiver.idleTimeout(); -// -// try -// { -// listener.await(5, TimeUnit.SECONDS); -// Assert.fail(); -// } -// catch (ExecutionException e) -// { -// Assert.assertTrue(e.getCause() instanceof TimeoutException); -// } -// } -// -// @Test -// public void test_Receive_BadResponse() throws Exception -// { -// ByteArrayEndPoint endPoint = new ByteArrayEndPoint(); -// HttpConnection connection = new HttpConnection(client, endPoint); -// endPoint.setInput("" + -// "HTTP/1.1 200 OK\r\n" + -// "Content-length: A\r\n" + -// "\r\n"); -// BufferingResponseListener listener = new BufferingResponseListener(); -// HttpReceiver receiver = new HttpReceiver(connection, null, listener); -// receiver.receive(connection); -// -// try -// { -// listener.await(5, TimeUnit.SECONDS); -// Assert.fail(); -// } -// catch (ExecutionException e) -// { -// Assert.assertTrue(e.getCause() instanceof HttpResponseException); -// } -// } + private HttpClient client; + private HttpDestination destination; + private ByteArrayEndPoint endPoint; + private HttpConnection connection; + private HttpSender sender; + private HttpReceiver receiver; + private HttpConversation conversation; + + @Before + public void init() throws Exception + { + client = new HttpClient(); + client.start(); + destination = new HttpDestination(client, "http", "localhost", 8080); + endPoint = new ByteArrayEndPoint(); + connection = new HttpConnection(client, endPoint, destination); + sender = new HttpSender(connection); + receiver = new HttpReceiver(connection); + conversation = new HttpConversation(client, 1); + } + + @After + public void destroy() throws Exception + { + client.stop(); + } + + protected HttpExchange newExchange(Response.Listener listener) + { + HttpExchange exchange = new HttpExchange(conversation, sender, receiver, null, listener); + conversation.add(exchange); + return exchange; + } + + @Test + public void test_Receive_NoResponseContent() throws Exception + { + final AtomicReference responseRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(1); + HttpExchange exchange = newExchange(new Response.Listener.Adapter() + { + @Override + public void onSuccess(Response response) + { + responseRef.set(response); + latch.countDown(); + } + }); + + endPoint.setInput("" + + "HTTP/1.1 200 OK\r\n" + + "Content-length: 0\r\n" + + "\r\n"); + receiver.receive(exchange); + + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); + Response response = responseRef.get(); + Assert.assertNotNull(response); + Assert.assertEquals(200, response.status()); + Assert.assertEquals("OK", response.reason()); + Assert.assertSame(HttpVersion.HTTP_1_1, response.version()); + HttpFields headers = response.headers(); + Assert.assertNotNull(headers); + Assert.assertEquals(1, headers.size()); + Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH)); + } + + @Test + public void test_Receive_ResponseContent() throws Exception + { + String content = "0123456789ABCDEF"; + endPoint.setInput("" + + "HTTP/1.1 200 OK\r\n" + + "Content-length: " + content.length() + "\r\n" + + "\r\n" + + content); + BufferingResponseListener listener = new BufferingResponseListener(); + HttpExchange exchange = newExchange(listener); + receiver.receive(exchange); + + Response response = listener.await(5, TimeUnit.SECONDS); + Assert.assertNotNull(response); + Assert.assertEquals(200, response.status()); + Assert.assertEquals("OK", response.reason()); + Assert.assertSame(HttpVersion.HTTP_1_1, response.version()); + HttpFields headers = response.headers(); + Assert.assertNotNull(headers); + Assert.assertEquals(1, headers.size()); + Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH)); + String received = listener.contentAsString("UTF-8"); + Assert.assertEquals(content, received); + } + + @Test + public void test_Receive_ResponseContent_EarlyEOF() throws Exception + { + String content1 = "0123456789"; + String content2 = "ABCDEF"; + endPoint.setInput("" + + "HTTP/1.1 200 OK\r\n" + + "Content-length: " + (content1.length() + content2.length()) + "\r\n" + + "\r\n" + + content1); + BufferingResponseListener listener = new BufferingResponseListener(); + HttpExchange exchange = newExchange(listener); + receiver.receive(exchange); + endPoint.setInputEOF(); + receiver.receive(exchange); + + try + { + listener.await(5, TimeUnit.SECONDS); + Assert.fail(); + } + catch (ExecutionException e) + { + Assert.assertTrue(e.getCause() instanceof EOFException); + } + } + + @Test + public void test_Receive_ResponseContent_IdleTimeout() throws Exception + { + endPoint.setInput("" + + "HTTP/1.1 200 OK\r\n" + + "Content-length: 1\r\n" + + "\r\n"); + BufferingResponseListener listener = new BufferingResponseListener(); + HttpExchange exchange = newExchange(listener); + receiver.receive(exchange); + // Simulate an idle timeout + receiver.idleTimeout(); + + try + { + listener.await(5, TimeUnit.SECONDS); + Assert.fail(); + } + catch (ExecutionException e) + { + Assert.assertTrue(e.getCause() instanceof TimeoutException); + } + } + + @Test + public void test_Receive_BadResponse() throws Exception + { + endPoint.setInput("" + + "HTTP/1.1 200 OK\r\n" + + "Content-length: A\r\n" + + "\r\n"); + BufferingResponseListener listener = new BufferingResponseListener(); + HttpExchange exchange = newExchange(listener); + receiver.receive(exchange); + + try + { + listener.await(5, TimeUnit.SECONDS); + Assert.fail(); + } + catch (ExecutionException e) + { + Assert.assertTrue(e.getCause() instanceof HttpResponseException); + } + } }