Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2014-04-23 19:26:08 +0000
committerSimone Bordet2014-04-23 19:26:08 +0000
commit03f03412c7a930de5d66310460ad6a628aad992f (patch)
treefece39e02da7d9aee4a37a457ac956400cde066e
parent2176822e038b3b8af6eedbf283c46977d41d1c93 (diff)
downloadorg.eclipse.jetty.project-03f03412c7a930de5d66310460ad6a628aad992f.tar.gz
org.eclipse.jetty.project-03f03412c7a930de5d66310460ad6a628aad992f.tar.xz
org.eclipse.jetty.project-03f03412c7a930de5d66310460ad6a628aad992f.zip
409788 - Large POST body causes java.lang.IllegalStateException: SENDING => HEADERS.
Fixed case where the response completes before the request.
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java28
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientDuplexTest.java61
2 files changed, 87 insertions, 2 deletions
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
index 3930c78849..e694182d40 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
@@ -325,10 +325,22 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_START:
- case STATUS_EXCEPTED:
- case STATUS_WAITING_FOR_RESPONSE:
set = _status.compareAndSet(oldStatus,newStatus);
break;
+ case STATUS_WAITING_FOR_RESPONSE:
+ if (isResponseCompleted())
+ {
+ // Don't change the status, it's too late.
+ ignored = true;
+ getEventListener().onRequestCommitted();
+ }
+ else
+ {
+ // The 1xx cases go from COMPLETED => WAITING again.
+ set = _status.compareAndSet(oldStatus,newStatus);
+ }
+ break;
+ case STATUS_EXCEPTED:
case STATUS_CANCELLING:
case STATUS_EXPIRED:
// Don't change the status, it's too late
@@ -396,6 +408,10 @@ public class HttpExchange
if (set = _status.compareAndSet(oldStatus,STATUS_PARSING_CONTENT))
getEventListener().onRequestCommitted();
break;
+ case STATUS_COMPLETED:
+ if (set = _status.compareAndSet(oldStatus,newStatus))
+ getEventListener().onResponseComplete();
+ break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set = _status.compareAndSet(oldStatus,newStatus);
@@ -423,6 +439,14 @@ public class HttpExchange
return set;
}
+ private boolean isResponseCompleted()
+ {
+ synchronized (this)
+ {
+ return _onResponseCompleteDone;
+ }
+ }
+
private boolean setStatusExpired(int newStatus, int oldStatus)
{
boolean set;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientDuplexTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientDuplexTest.java
index 57b9086610..96c4f2e95e 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientDuplexTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientDuplexTest.java
@@ -28,6 +28,7 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
@@ -301,6 +302,66 @@ public class HttpClientDuplexTest
socket.close();
}
+
+ @Test
+ public void testResponseCompleteBeforeRequestContent() throws Exception
+ {
+ // Must be greater than 2 to stay in "sending"
+ // state and trigger the condition of this test.
+ int contentLength = 16;
+ final byte[] chunk = new byte[]{'A'};
+ final AtomicInteger requestContent = new AtomicInteger(contentLength);
+ ContentExchange exchange = new ContentExchange(true)
+ {
+ @Override
+ public Buffer getRequestContentChunk(Buffer buffer) throws IOException
+ {
+ if (requestContent.decrementAndGet() > 0)
+ return new ByteArrayBuffer(chunk);
+ return null;
+ }
+ };
+ exchange.setURL("http://localhost:" + server.getLocalPort());
+ // The test needs a fake content source to invoke
+ // getRequestContentChunk() which will provide the content.
+ exchange.setRequestContentSource(new ClosedInputStream());
+ exchange.setRequestHeader("Content-Length", String.valueOf(contentLength));
+ client.send(exchange);
+
+ Socket socket = server.accept();
+ BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
+ OutputStream output = socket.getOutputStream();
+
+ // Read headers.
+ while (true)
+ {
+ String line = input.readLine();
+ Assert.assertNotNull(line);
+ if (line.length() == 0)
+ break;
+ }
+
+ // Send the whole response.
+ String responseHeaders = "" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 0\r\n" +
+ "\r\n";
+ output.write(responseHeaders.getBytes("UTF-8"));
+ output.flush();
+
+ // Read request content on server.
+ while (true)
+ {
+ if (input.read() < 0)
+ break;
+ }
+
+ Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
+ Assert.assertEquals(200, exchange.getResponseStatus());
+
+ socket.close();
+ }
+
private boolean await(CountDownLatch latch, long millis) throws InterruptedIOException
{
try

Back to the top