diff --git a/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java b/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java index 6799eeb96..c121abced 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java +++ b/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java @@ -95,9 +95,16 @@ public final class RawHeaders { public void setStatusLine(String statusLine) throws IOException { // H T T P / 1 . 1 2 0 0 T e m p o r a r y R e d i r e c t // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 + if (this.responseMessage != null) { + throw new IllegalStateException("statusLine is already set"); + } + // We allow empty message without leading white space since some servers + // do not send the white space when the message is empty. + boolean hasMessage = statusLine.length() > 13; if (!statusLine.startsWith("HTTP/1.") + || statusLine.length() < 12 || statusLine.charAt(8) != ' ' - || statusLine.charAt(12) != ' ') { + || (hasMessage && statusLine.charAt(12) != ' ')) { throw new ProtocolException("Unexpected status line: " + statusLine); } int httpMinorVersion = statusLine.charAt(7) - '0'; @@ -110,7 +117,7 @@ public final class RawHeaders { } catch (NumberFormatException e) { throw new ProtocolException("Unexpected status line: " + statusLine); } - this.responseMessage = statusLine.substring(13); + this.responseMessage = hasMessage ? statusLine.substring(13) : ""; this.responseCode = responseCode; this.statusLine = statusLine; this.httpMinorVersion = httpMinorVersion; diff --git a/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java b/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java index 32649cf20..e5629f094 100644 --- a/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java +++ b/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java @@ -15,11 +15,13 @@ */ package com.squareup.okhttp.internal.http; +import java.io.IOException; import java.util.Arrays; import java.util.List; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public final class RawHeadersTest { @Test public void parseNameValueBlock() { @@ -61,4 +63,40 @@ public final class RawHeadersTest { rawHeaders.add("Transfer-Encoding", "chunked"); assertEquals(Arrays.asList(), rawHeaders.toNameValueBlock()); } + + @Test public void statusMessage() throws IOException { + RawHeaders rawHeaders = new RawHeaders(); + final String message = "Temporary Redirect"; + final int version = 1; + final int code = 200; + rawHeaders.setStatusLine("HTTP/1." + version + " " + code + " " + message); + assertEquals(message, rawHeaders.getResponseMessage()); + assertEquals(version, rawHeaders.getHttpMinorVersion()); + assertEquals(code, rawHeaders.getResponseCode()); + } + + @Test public void statusMessageWithEmptyMessage() throws IOException { + RawHeaders rawHeaders = new RawHeaders(); + final int version = 1; + final int code = 503; + rawHeaders.setStatusLine("HTTP/1." + version + " " + code + " "); + assertTrue(rawHeaders.getResponseMessage().isEmpty()); + assertEquals(version, rawHeaders.getHttpMinorVersion()); + assertEquals(code, rawHeaders.getResponseCode()); + } + + /** + * This is not defined in the protocol but some servers won't add the leading + * empty space when the message is empty. + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 + */ + @Test public void statusMessageWithEmptyMessageAndNoLeadingSpace() throws IOException { + RawHeaders rawHeaders = new RawHeaders(); + final int version = 1; + final int code = 503; + rawHeaders.setStatusLine("HTTP/1." + version + " " + code); + assertTrue(rawHeaders.getResponseMessage().isEmpty()); + assertEquals(version, rawHeaders.getHttpMinorVersion()); + assertEquals(code, rawHeaders.getResponseCode()); + } }