mirror of
https://github.com/square/okhttp.git
synced 2026-01-24 04:02:07 +03:00
Merge pull request #459 from square/jwilson_0119_icy
Permit status lines like 'ICY 200 OK'
This commit is contained in:
@@ -18,26 +18,48 @@ public final class StatusLine {
|
||||
// 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
|
||||
|
||||
// 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) != ' '
|
||||
|| (hasMessage && statusLine.charAt(12) != ' ')) {
|
||||
// Parse protocol like "HTTP/1.1" followed by a space.
|
||||
int codeStart;
|
||||
int httpMinorVersion;
|
||||
if (statusLine.startsWith("HTTP/1.")) {
|
||||
if (statusLine.length() < 9 || statusLine.charAt(8) != ' ') {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
httpMinorVersion = statusLine.charAt(7) - '0';
|
||||
codeStart = 9;
|
||||
if (httpMinorVersion < 0 || httpMinorVersion > 9) {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
} else if (statusLine.startsWith("ICY ")) {
|
||||
// Shoutcast uses ICY instead of "HTTP/1.0".
|
||||
httpMinorVersion = 0;
|
||||
codeStart = 4;
|
||||
} else {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
int httpMinorVersion = statusLine.charAt(7) - '0';
|
||||
if (httpMinorVersion < 0 || httpMinorVersion > 9) {
|
||||
|
||||
// Parse response code like "200". Always 3 digits.
|
||||
if (statusLine.length() < codeStart + 3) {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
int responseCode;
|
||||
try {
|
||||
responseCode = Integer.parseInt(statusLine.substring(9, 12));
|
||||
responseCode = Integer.parseInt(statusLine.substring(codeStart, codeStart + 3));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
this.responseMessage = hasMessage ? statusLine.substring(13) : "";
|
||||
|
||||
// Parse an optional response message like "OK" or "Not Modified". If it
|
||||
// exists, it is separated from the response code by a space.
|
||||
String responseMessage = "";
|
||||
if (statusLine.length() > codeStart + 3) {
|
||||
if (statusLine.charAt(codeStart + 3) != ' ') {
|
||||
throw new ProtocolException("Unexpected status line: " + statusLine);
|
||||
}
|
||||
responseMessage = statusLine.substring(codeStart + 4);
|
||||
}
|
||||
|
||||
this.responseMessage = responseMessage;
|
||||
this.responseCode = responseCode;
|
||||
this.statusLine = statusLine;
|
||||
this.httpMinorVersion = httpMinorVersion;
|
||||
@@ -64,5 +86,4 @@ public final class StatusLine {
|
||||
public String message() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
package com.squareup.okhttp.internal.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class StatusLineTest {
|
||||
@@ -53,4 +55,63 @@ public final class StatusLineTest {
|
||||
assertEquals(version, statusLine.httpMinorVersion());
|
||||
assertEquals(code, statusLine.code());
|
||||
}
|
||||
|
||||
// https://github.com/square/okhttp/issues/386
|
||||
@Test public void shoutcast() throws IOException {
|
||||
StatusLine statusLine = new StatusLine("ICY 200 OK");
|
||||
assertEquals("OK", statusLine.message());
|
||||
assertEquals(0, statusLine.httpMinorVersion());
|
||||
assertEquals(200, statusLine.code());
|
||||
}
|
||||
|
||||
@Test public void missingProtocol() throws IOException {
|
||||
assertInvalid("");
|
||||
assertInvalid(" ");
|
||||
assertInvalid("200 OK");
|
||||
assertInvalid(" 200 OK");
|
||||
}
|
||||
|
||||
@Test public void protocolVersions() throws IOException {
|
||||
assertInvalid("HTTP/2.0 200 OK");
|
||||
assertInvalid("HTTP/2.1 200 OK");
|
||||
assertInvalid("HTTP/-.1 200 OK");
|
||||
assertInvalid("HTTP/1.- 200 OK");
|
||||
assertInvalid("HTTP/0.1 200 OK");
|
||||
assertInvalid("HTTP/101 200 OK");
|
||||
assertInvalid("HTTP/1.1_200 OK");
|
||||
}
|
||||
|
||||
@Test public void nonThreeDigitCode() throws IOException {
|
||||
assertInvalid("HTTP/1.1 OK");
|
||||
assertInvalid("HTTP/1.1 2 OK");
|
||||
assertInvalid("HTTP/1.1 20 OK");
|
||||
assertInvalid("HTTP/1.1 2000 OK");
|
||||
assertInvalid("HTTP/1.1 two OK");
|
||||
assertInvalid("HTTP/1.1 2");
|
||||
assertInvalid("HTTP/1.1 2000");
|
||||
assertInvalid("HTTP/1.1 two");
|
||||
}
|
||||
|
||||
@Test public void truncated() throws IOException {
|
||||
assertInvalid("");
|
||||
assertInvalid("H");
|
||||
assertInvalid("HTTP/1");
|
||||
assertInvalid("HTTP/1.");
|
||||
assertInvalid("HTTP/1.1");
|
||||
assertInvalid("HTTP/1.1 ");
|
||||
assertInvalid("HTTP/1.1 2");
|
||||
assertInvalid("HTTP/1.1 20");
|
||||
}
|
||||
|
||||
@Test public void wrongMessageDelimiter() throws IOException {
|
||||
assertInvalid("HTTP/1.1 200_");
|
||||
}
|
||||
|
||||
private void assertInvalid(String statusLine) throws IOException {
|
||||
try {
|
||||
new StatusLine(statusLine);
|
||||
fail();
|
||||
} catch (ProtocolException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1324,6 +1324,32 @@ public final class URLConnectionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void shoutcast() throws Exception {
|
||||
server.enqueue(new MockResponse().setStatus("ICY 200 OK")
|
||||
// .addHeader("HTTP/1.0 200 OK")
|
||||
.addHeader("Accept-Ranges: none")
|
||||
.addHeader("Content-Type: audio/mpeg")
|
||||
.addHeader("icy-br:128")
|
||||
.addHeader("ice-audio-info: bitrate=128;samplerate=44100;channels=2")
|
||||
.addHeader("icy-br:128")
|
||||
.addHeader("icy-description:Rock")
|
||||
.addHeader("icy-genre:riders")
|
||||
.addHeader("icy-name:A2RRock")
|
||||
.addHeader("icy-pub:1")
|
||||
.addHeader("icy-url:http://www.A2Rradio.com")
|
||||
.addHeader("Server: Icecast 2.3.3-kh8")
|
||||
.addHeader("Cache-Control: no-cache")
|
||||
.addHeader("Pragma: no-cache")
|
||||
.addHeader("Expires: Mon, 26 Jul 1997 05:00:00 GMT")
|
||||
.addHeader("icy-metaint:16000")
|
||||
.setBody("mp3 data"));
|
||||
server.play();
|
||||
HttpURLConnection connection = client.open(server.getUrl("/"));
|
||||
assertEquals(200, connection.getResponseCode());
|
||||
assertEquals("OK", connection.getResponseMessage());
|
||||
assertContent("mp3 data", connection);
|
||||
}
|
||||
|
||||
@Test public void cannotSetNegativeFixedLengthStreamingMode() throws Exception {
|
||||
server.play();
|
||||
HttpURLConnection connection = client.open(server.getUrl("/"));
|
||||
|
||||
Reference in New Issue
Block a user