Export to GitHub

mockwebserver - issue #8

Zero-length PUT with Expect 100-continue hangs


Posted on Apr 12, 2013 by Massive Bear

The following test case fails on Java 7:

@Test public void emptyPutHangs() throws Exception { MockWebServer server = new MockWebServer(); server.enqueue(new MockResponse().addHeader("ETag", "ABCDEF")); server.play();

URL url = server.getUrl("/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(0);
//connection.setReadTimeout(1000); // << comment out the previous line and uncomment this and it will pass
connection.setAllowUserInteraction(false);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Expect", "100-continue"); // << comment this and it will pass
connection.setRequestProperty("Content-Length", "0");
connection.setDoOutput(true);
connection.setFixedLengthStreamingMode(0);
//connection.setFixedLengthStreamingMode(1); // comment out the previous line and uncomment these two and it will pass
//connection.getOutputStream().write(new byte [] { 1 });

assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());

RecordedRequest request = server.takeRequest();
assertEquals(request.getRequestLine(), "PUT / HTTP/1.1");
server.shutdown();

}

Removing the Expect 100-Continue header or writing a non-empty body allows the test to succeed, as does setting a non-zero read timeout (in that case, the read simply times out).

The read timeout is set to 0 because of issue 6

Attachments

Comment #1

Posted on Apr 12, 2013 by Massive Bear

Passes without problems under Java 6, too.

Comment #2

Posted on Apr 12, 2013 by Massive Bear

Is this a bug in MockWebServer? Or with Java7's HttpURLConnection?

Comment #3

Posted on Apr 12, 2013 by Grumpy Rhino

I do not understand the expected behavior on the server when a client issues a zero-length PUT with Expect: 100-continue. RFC 2616 states:

A client MUST NOT send an Expect request-header field (section 14.20) with the "100-continue" expectation if it does not intend to send a request body.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3

Other servers handle this despite the MUST NOT so perhaps mockwebserver should as well?

Comment #4

Posted on Apr 12, 2013 by Massive Bear

Other servers handle this despite the MUST NOT so perhaps mockwebserver should as well?

AWS S3 appears to be in this category, by the way.

Comment #5

Posted on Apr 13, 2013 by Massive Bear

What should mockwebserver do?

Comment #6

Posted on Apr 13, 2013 by Massive Bear

What should mockwebserver do?

It would be helpful if this test case succeeded in the same way as it would if the body were non-zero. I haven't analysed in detail where it is hanging so unfortunately don't know what changes would be required to fix this :-(

Is that something that would be easy for you to investigate?

Comment #7

Posted on Apr 13, 2013 by Massive Bear

You probably just need a mechanism to send a 100-continue response and then another response, without any intermediate request. Perhaps MockResponse should have an optional MockResponse field that it sends first? So it can send a 100 continue and then the actual response?

Comment #8

Posted on Apr 13, 2013 by Swift Cat

Here's an idea for an impl.

during MWS.readRequest, break and exit when encounter the header "Expect: 100-continue", in this case, we'd expect the MWS to have a queued MockResponse.CONTINUE (which is just code, message 100, continue)

With this change, I think MWS logic could pretty much remain as-is

Comment #9

Posted on Apr 13, 2013 by Swift Cat

well it might not work without changing MWS.processOneRequest, as readAsciiUntilCrlf() isn't expecting multiple reads from the same input stream.

Might be best to refactor MWS.processOneRequest to special-case Expect: 100-continue. Let me know if you'd like a patch or prefer to sort it out.

Comment #10

Posted on Apr 13, 2013 by Swift Cat

^^ s/readAsciiUntilCrlf/readRequest/ sorry bad paste

Comment #11

Posted on Apr 13, 2013 by Massive Bear

Please send a patch. You'll also need to fill out Google's ICLA for me to accept your code.

Comment #12

Posted on Apr 13, 2013 by Swift Cat

here's the patch. I've filled out the cla.

Attachments

Comment #13

Posted on Apr 16, 2013 by Massive Bear

This issue was closed by revision r41.

Status: Fixed

Labels:
Type-Defect Priority-Medium