mirror of
https://github.com/square/okhttp.git
synced 2026-01-24 04:02:07 +03:00
feedback from #413 and a few optimizations on hpack.
This commit is contained in:
@@ -33,7 +33,7 @@ import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import org.eclipse.jetty.npn.NextProtoNego;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.asByteStringList;
|
||||
import static com.squareup.okhttp.internal.Util.byteStringList;
|
||||
|
||||
/** A basic SPDY server that serves the contents of a local directory. */
|
||||
public final class SpdyServer implements IncomingStreamHandler {
|
||||
@@ -109,7 +109,7 @@ public final class SpdyServer implements IncomingStreamHandler {
|
||||
|
||||
private void send404(SpdyStream stream, String path) throws IOException {
|
||||
List<ByteString> responseHeaders =
|
||||
asByteStringList(":status", "404", ":version", "HTTP/1.1", "content-type", "text/plain");
|
||||
byteStringList(":status", "404", ":version", "HTTP/1.1", "content-type", "text/plain");
|
||||
stream.reply(responseHeaders, true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
String text = "Not found: " + path;
|
||||
@@ -119,7 +119,7 @@ public final class SpdyServer implements IncomingStreamHandler {
|
||||
|
||||
private void serveDirectory(SpdyStream stream, String[] files) throws IOException {
|
||||
List<ByteString> responseHeaders =
|
||||
asByteStringList(":status", "200", ":version", "HTTP/1.1", "content-type",
|
||||
byteStringList(":status", "200", ":version", "HTTP/1.1", "content-type",
|
||||
"text/html; charset=UTF-8");
|
||||
stream.reply(responseHeaders, true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
@@ -133,8 +133,9 @@ public final class SpdyServer implements IncomingStreamHandler {
|
||||
private void serveFile(SpdyStream stream, File file) throws IOException {
|
||||
InputStream in = new FileInputStream(file);
|
||||
byte[] buffer = new byte[8192];
|
||||
stream.reply(asByteStringList(":status", "200", ":version", "HTTP/1.1", "content-type",
|
||||
contentType(file)), true);
|
||||
stream.reply(
|
||||
byteStringList(":status", "200", ":version", "HTTP/1.1", "content-type", contentType(file)),
|
||||
true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
int count;
|
||||
while ((count = in.read(buffer)) != -1) {
|
||||
|
||||
@@ -104,6 +104,20 @@ public final class ByteString {
|
||||
return new ByteString(result);
|
||||
}
|
||||
|
||||
public static ByteString concat(ByteString... byteStrings) {
|
||||
int size = 0;
|
||||
for (ByteString byteString : byteStrings) {
|
||||
size += byteString.size();
|
||||
}
|
||||
byte[] result = new byte[size];
|
||||
int pos = 0;
|
||||
for (ByteString byteString : byteStrings) {
|
||||
System.arraycopy(byteString.data, 0, result, pos, byteString.size());
|
||||
pos += byteString.size();
|
||||
}
|
||||
return ByteString.of(result);
|
||||
}
|
||||
|
||||
private ByteString(byte[] data) {
|
||||
this.data = data; // Trusted internal constructor doesn't clone data.
|
||||
}
|
||||
|
||||
@@ -393,11 +393,11 @@ public final class Util {
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ByteString> asByteStringList(String... strings) {
|
||||
List<ByteString> out = new ArrayList<ByteString>(strings.length);
|
||||
public static List<ByteString> byteStringList(String... strings) {
|
||||
List<ByteString> result = new ArrayList<ByteString>(strings.length);
|
||||
for (String string : strings) {
|
||||
out.add(ByteString.encodeUtf8(string));
|
||||
result.add(ByteString.encodeUtf8(string));
|
||||
}
|
||||
return out;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public interface FrameReader extends Closeable {
|
||||
|
||||
public interface Handler {
|
||||
void data(boolean inFinished, int streamId, InputStream in, int length) throws IOException;
|
||||
|
||||
/**
|
||||
* Create or update incoming headers, creating the corresponding streams
|
||||
* if necessary. Frames that trigger this are SPDY SYN_STREAM, HEADERS, and
|
||||
@@ -38,10 +39,9 @@ public interface FrameReader extends Closeable {
|
||||
* @param inFinished true if the sender will not send further frames.
|
||||
* @param streamId the stream owning these headers.
|
||||
* @param associatedStreamId the stream that triggered the sender to create
|
||||
* this stream.
|
||||
* this stream.
|
||||
* @param priority or -1 for no priority. For SPDY, priorities range from 0
|
||||
* (highest) thru 7 (lowest). For HTTP/2.0, priorities range from 0
|
||||
* @param nameValueBlock
|
||||
* (highest) thru 7 (lowest). For HTTP/2.0, priorities range from 0
|
||||
*/
|
||||
void headers(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId,
|
||||
int priority, List<ByteString> nameValueBlock, HeadersMode headersMode);
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
@@ -16,22 +15,27 @@ import java.util.List;
|
||||
final class HpackDraft05 {
|
||||
|
||||
// Visible for testing.
|
||||
static class HeaderEntry implements Cloneable {
|
||||
static class HeaderEntry {
|
||||
final ByteString name;
|
||||
final ByteString value;
|
||||
final int size;
|
||||
// read when in headerTable
|
||||
boolean referenced = true;
|
||||
|
||||
HeaderEntry(ByteString name, ByteString value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.size = 32 + name.size() + value.size();
|
||||
this(name, value, 32 + name.size() + value.size());
|
||||
}
|
||||
|
||||
public HeaderEntry(String name, String value) {
|
||||
HeaderEntry(String name, String value) {
|
||||
this(ByteString.encodeUtf8(name), ByteString.encodeUtf8(value));
|
||||
}
|
||||
|
||||
private HeaderEntry(ByteString name, ByteString value, int size) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/** Adds name and value, if this entry is referenced. */
|
||||
void addTo(List<ByteString> out) {
|
||||
if (!referenced) return;
|
||||
@@ -40,19 +44,15 @@ final class HpackDraft05 {
|
||||
}
|
||||
|
||||
@Override public HeaderEntry clone() {
|
||||
try {
|
||||
return (HeaderEntry) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
return new HeaderEntry(name, value, size);
|
||||
}
|
||||
}
|
||||
|
||||
static final int PREFIX_6_BITS = 0x3f;
|
||||
static final int PREFIX_7_BITS = 0x7f;
|
||||
static final int PREFIX_8_BITS = 0xff;
|
||||
private static final int PREFIX_6_BITS = 0x3f;
|
||||
private static final int PREFIX_7_BITS = 0x7f;
|
||||
private static final int PREFIX_8_BITS = 0xff;
|
||||
|
||||
static final List<HeaderEntry> STATIC_HEADER_TABLE = Arrays.asList(
|
||||
private static final HeaderEntry[] STATIC_HEADER_TABLE = new HeaderEntry[] {
|
||||
new HeaderEntry(":authority", ""),
|
||||
new HeaderEntry(":method", "GET"),
|
||||
new HeaderEntry(":method", "POST"),
|
||||
@@ -113,7 +113,7 @@ final class HpackDraft05 {
|
||||
new HeaderEntry("vary", ""),
|
||||
new HeaderEntry("via", ""),
|
||||
new HeaderEntry("www-authenticate", "")
|
||||
);
|
||||
};
|
||||
|
||||
private HpackDraft05() {
|
||||
}
|
||||
@@ -126,7 +126,7 @@ final class HpackDraft05 {
|
||||
private long bytesLeft = 0;
|
||||
|
||||
// Visible for testing.
|
||||
final List<HeaderEntry> headerTable = new ArrayList<HeaderEntry>(); // TODO: default capacity?
|
||||
final List<HeaderEntry> headerTable = new ArrayList<HeaderEntry>(5); // average of 5 headers
|
||||
final BitSet staticReferenceSet = new BitSet();
|
||||
long headerTableSize = 0;
|
||||
long maxHeaderTableSize = 4096; // TODO: needs to come from SETTINGS_HEADER_TABLE_SIZE.
|
||||
@@ -180,7 +180,7 @@ final class HpackDraft05 {
|
||||
public void emitReferenceSet() {
|
||||
for (int i = staticReferenceSet.nextSetBit(0); i != -1;
|
||||
i = staticReferenceSet.nextSetBit(i + 1)) {
|
||||
STATIC_HEADER_TABLE.get(i).addTo(emittedHeaders);
|
||||
STATIC_HEADER_TABLE[i].addTo(emittedHeaders);
|
||||
}
|
||||
for (int i = headerTable.size() - 1; i != -1; i--) {
|
||||
headerTable.get(i).addTo(emittedHeaders);
|
||||
@@ -202,7 +202,7 @@ final class HpackDraft05 {
|
||||
if (maxHeaderTableSize == 0) {
|
||||
staticReferenceSet.set(index - headerTable.size());
|
||||
} else {
|
||||
HeaderEntry staticEntry = STATIC_HEADER_TABLE.get(index - headerTable.size());
|
||||
HeaderEntry staticEntry = STATIC_HEADER_TABLE[index - headerTable.size()];
|
||||
insertIntoHeaderTable(-1, staticEntry.clone());
|
||||
}
|
||||
} else if (!headerTable.get(index).referenced) {
|
||||
@@ -246,7 +246,7 @@ final class HpackDraft05 {
|
||||
|
||||
private ByteString getName(int index) {
|
||||
if (isStaticHeader(index)) {
|
||||
return STATIC_HEADER_TABLE.get(index - headerTable.size()).name;
|
||||
return STATIC_HEADER_TABLE[index - headerTable.size()].name;
|
||||
} else {
|
||||
return headerTable.get(index).name;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,16 @@ public class ByteStringTest {
|
||||
assertByteArraysEquals(new byte[] { 0x62, 0x63 }, out.toByteArray());
|
||||
}
|
||||
|
||||
@Test public void concat() {
|
||||
assertEquals(ByteString.of(), ByteString.concat());
|
||||
assertEquals(ByteString.of(), ByteString.concat(ByteString.EMPTY));
|
||||
assertEquals(ByteString.of(), ByteString.concat(ByteString.EMPTY, ByteString.EMPTY));
|
||||
ByteString foo = ByteString.encodeUtf8("foo");
|
||||
ByteString bar = ByteString.encodeUtf8("bar");
|
||||
assertEquals(foo, ByteString.concat(foo));
|
||||
assertEquals(ByteString.encodeUtf8("foobar"), ByteString.concat(foo, bar));
|
||||
}
|
||||
|
||||
private static void assertByteArraysEquals(byte[] a, byte[] b) {
|
||||
assertEquals(Arrays.toString(a), Arrays.toString(b));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.List;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.asByteStringList;
|
||||
import static com.squareup.okhttp.internal.Util.byteStringList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class HpackDraft05Test {
|
||||
@@ -45,7 +45,7 @@ public class HpackDraft05Test {
|
||||
@Test public void tooLargeToHPackIsStillEmitted() throws IOException {
|
||||
char[] tooLarge = new char[4096];
|
||||
Arrays.fill(tooLarge, 'a');
|
||||
final List<ByteString> sentHeaders = asByteStringList("foo", new String(tooLarge));
|
||||
final List<ByteString> sentHeaders = byteStringList("foo", new String(tooLarge));
|
||||
|
||||
ByteArrayOutputStream out = literalHeaders(sentHeaders);
|
||||
bytesIn.set(out.toByteArray());
|
||||
@@ -80,7 +80,7 @@ public class HpackDraft05Test {
|
||||
HpackDraft05.HeaderEntry entry = hpackReader.headerTable.get(0);
|
||||
checkEntry(entry, "custom-key", "custom-header", 55, true);
|
||||
|
||||
assertEquals(asByteStringList("custom-key", "custom-header"), hpackReader.getAndReset());
|
||||
assertEquals(byteStringList("custom-key", "custom-header"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ public class HpackDraft05Test {
|
||||
|
||||
assertEquals(0, hpackReader.headerTable.size());
|
||||
|
||||
assertEquals(asByteStringList(":path", "/sample/path"), hpackReader.getAndReset());
|
||||
assertEquals(byteStringList(":path", "/sample/path"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +122,7 @@ public class HpackDraft05Test {
|
||||
HpackDraft05.HeaderEntry entry = hpackReader.headerTable.get(0);
|
||||
checkEntry(entry, ":method", "GET", 42, true);
|
||||
|
||||
assertEquals(asByteStringList(":method", "GET"), hpackReader.getAndReset());
|
||||
assertEquals(byteStringList(":method", "GET"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +142,7 @@ public class HpackDraft05Test {
|
||||
// Not buffered in header table.
|
||||
assertEquals(0, hpackReader.headerTable.size());
|
||||
|
||||
assertEquals(asByteStringList(":method", "GET"), hpackReader.getAndReset());
|
||||
assertEquals(byteStringList(":method", "GET"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,10 +208,10 @@ public class HpackDraft05Test {
|
||||
assertEquals(180, hpackReader.headerTableSize);
|
||||
|
||||
// Decoded header set:
|
||||
assertEquals(asByteStringList( //
|
||||
":method", "GET", //
|
||||
":scheme", "http", //
|
||||
":path", "/", //
|
||||
assertEquals(byteStringList(
|
||||
":method", "GET",
|
||||
":scheme", "http",
|
||||
":path", "/",
|
||||
":authority", "www.example.com"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
@@ -253,11 +253,11 @@ public class HpackDraft05Test {
|
||||
assertEquals(233, hpackReader.headerTableSize);
|
||||
|
||||
// Decoded header set:
|
||||
assertEquals(asByteStringList( //
|
||||
":method", "GET", //
|
||||
":scheme", "http", //
|
||||
":path", "/", //
|
||||
":authority", "www.example.com", //
|
||||
assertEquals(byteStringList(
|
||||
":method", "GET",
|
||||
":scheme", "http",
|
||||
":path", "/",
|
||||
":authority", "www.example.com",
|
||||
"cache-control", "no-cache"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
@@ -322,11 +322,11 @@ public class HpackDraft05Test {
|
||||
|
||||
// Decoded header set:
|
||||
// TODO: order is not correct per docs, but then again, the spec doesn't require ordering.
|
||||
assertEquals(asByteStringList( //
|
||||
":method", "GET", //
|
||||
":authority", "www.example.com", //
|
||||
":scheme", "https", //
|
||||
":path", "/index.html", //
|
||||
assertEquals(byteStringList(
|
||||
":method", "GET",
|
||||
":authority", "www.example.com",
|
||||
":scheme", "https",
|
||||
":path", "/index.html",
|
||||
"custom-key", "custom-value"), hpackReader.getAndReset());
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ public class HpackDraft05Test {
|
||||
}
|
||||
|
||||
@Test public void headersRoundTrip() throws IOException {
|
||||
List<ByteString> sentHeaders = asByteStringList("name", "value");
|
||||
List<ByteString> sentHeaders = byteStringList("name", "value");
|
||||
hpackWriter.writeHeaders(sentHeaders);
|
||||
ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
|
||||
HpackDraft05.Reader reader = new HpackDraft05.Reader(new DataInputStream(bytesIn));
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.asByteStringList;
|
||||
import static com.squareup.okhttp.internal.Util.byteStringList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -32,7 +32,7 @@ public class Http20Draft09Test {
|
||||
static final int expectedStreamId = 15;
|
||||
|
||||
@Test public void onlyOneLiteralHeadersFrame() throws IOException {
|
||||
final List<ByteString> sentHeaders = asByteStringList("name", "value");
|
||||
final List<ByteString> sentHeaders = byteStringList("name", "value");
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
DataOutputStream dataOut = new DataOutputStream(out);
|
||||
@@ -74,7 +74,7 @@ public class Http20Draft09Test {
|
||||
|
||||
// Write the first headers frame.
|
||||
{
|
||||
byte[] headerBytes = literalHeaders(asByteStringList("foo", "bar"));
|
||||
byte[] headerBytes = literalHeaders(byteStringList("foo", "bar"));
|
||||
dataOut.writeShort(headerBytes.length);
|
||||
dataOut.write(Http20Draft09.TYPE_HEADERS);
|
||||
dataOut.write(0); // no flags
|
||||
@@ -84,7 +84,7 @@ public class Http20Draft09Test {
|
||||
|
||||
// Write the continuation frame, specifying no more frames are expected.
|
||||
{
|
||||
byte[] headerBytes = literalHeaders(asByteStringList("baz", "qux"));
|
||||
byte[] headerBytes = literalHeaders(byteStringList("baz", "qux"));
|
||||
dataOut.writeShort(headerBytes.length);
|
||||
dataOut.write(Http20Draft09.TYPE_CONTINUATION);
|
||||
dataOut.write(Http20Draft09.FLAG_END_HEADERS | Http20Draft09.FLAG_END_STREAM);
|
||||
@@ -106,7 +106,7 @@ public class Http20Draft09Test {
|
||||
assertEquals(expectedStreamId, streamId);
|
||||
assertEquals(-1, associatedStreamId);
|
||||
assertEquals(-1, priority);
|
||||
assertEquals(asByteStringList("foo", "bar", "baz", "qux"), nameValueBlock);
|
||||
assertEquals(byteStringList("foo", "bar", "baz", "qux"), nameValueBlock);
|
||||
assertEquals(HeadersMode.HTTP_20_HEADERS, headersMode);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.UTF_8;
|
||||
import static com.squareup.okhttp.internal.Util.asByteStringList;
|
||||
import static com.squareup.okhttp.internal.Util.byteStringList;
|
||||
import static com.squareup.okhttp.internal.spdy.ErrorCode.CANCEL;
|
||||
import static com.squareup.okhttp.internal.spdy.ErrorCode.FLOW_CONTROL_ERROR;
|
||||
import static com.squareup.okhttp.internal.spdy.ErrorCode.INTERNAL_ERROR;
|
||||
@@ -68,15 +68,15 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame()
|
||||
.synReply(false, 1, asByteStringList("a", "android"));
|
||||
.synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.sendFrame().data(true, 1, "robot".getBytes("UTF-8"));
|
||||
peer.acceptFrame(); // DATA
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
assertEquals(asByteStringList("a", "android"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
assertEquals(byteStringList("a", "android"), stream.getResponseHeaders());
|
||||
assertStreamData("robot", stream.getInputStream());
|
||||
writeAndClose(stream, "c3po");
|
||||
assertEquals(0, connection.openStreamCount());
|
||||
@@ -89,20 +89,20 @@ public final class SpdyConnectionTest {
|
||||
assertFalse(synStream.outFinished);
|
||||
assertEquals(1, synStream.streamId);
|
||||
assertEquals(0, synStream.associatedStreamId);
|
||||
assertEquals(asByteStringList("b", "banana"), synStream.nameValueBlock);
|
||||
assertEquals(byteStringList("b", "banana"), synStream.nameValueBlock);
|
||||
MockSpdyPeer.InFrame requestData = peer.takeFrame();
|
||||
assertTrue(Arrays.equals("c3po".getBytes("UTF-8"), requestData.data));
|
||||
}
|
||||
|
||||
@Test public void headersOnlyStreamIsClosedAfterReplyHeaders() throws Exception {
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("b", "banana"));
|
||||
peer.play();
|
||||
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), false, false);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), false, false);
|
||||
assertEquals(1, connection.openStreamCount());
|
||||
assertEquals(asByteStringList("b", "banana"), stream.getResponseHeaders());
|
||||
assertEquals(byteStringList("b", "banana"), stream.getResponseHeaders());
|
||||
assertEquals(0, connection.openStreamCount());
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(true, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(true, 1, byteStringList("a", "android"));
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
connection.newStream(asByteStringList("b", "banana"), false, true);
|
||||
connection.newStream(byteStringList("b", "banana"), false, true);
|
||||
assertEquals(1, connection.openStreamCount());
|
||||
connection.ping().roundTripTime(); // Ensure that the SYN_REPLY has been received.
|
||||
assertEquals(0, connection.openStreamCount());
|
||||
@@ -131,7 +131,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void serverCreatesStreamAndClientReplies() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 5, 129, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 5, 129, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.play();
|
||||
|
||||
@@ -140,10 +140,10 @@ public final class SpdyConnectionTest {
|
||||
IncomingStreamHandler handler = new IncomingStreamHandler() {
|
||||
@Override public void receive(SpdyStream stream) throws IOException {
|
||||
receiveCount.incrementAndGet();
|
||||
assertEquals(asByteStringList("a", "android"), stream.getRequestHeaders());
|
||||
assertEquals(byteStringList("a", "android"), stream.getRequestHeaders());
|
||||
assertEquals(null, stream.getErrorCode());
|
||||
assertEquals(5, stream.getPriority());
|
||||
stream.reply(asByteStringList("b", "banana"), true);
|
||||
stream.reply(byteStringList("b", "banana"), true);
|
||||
}
|
||||
};
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(handler).build();
|
||||
@@ -154,13 +154,13 @@ public final class SpdyConnectionTest {
|
||||
assertEquals(HeadersMode.SPDY_REPLY, reply.headersMode);
|
||||
assertFalse(reply.inFinished);
|
||||
assertEquals(2, reply.streamId);
|
||||
assertEquals(asByteStringList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(byteStringList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(1, receiveCount.get());
|
||||
}
|
||||
|
||||
@Test public void replyWithNoData() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.play();
|
||||
|
||||
@@ -168,7 +168,7 @@ public final class SpdyConnectionTest {
|
||||
final AtomicInteger receiveCount = new AtomicInteger();
|
||||
IncomingStreamHandler handler = new IncomingStreamHandler() {
|
||||
@Override public void receive(SpdyStream stream) throws IOException {
|
||||
stream.reply(asByteStringList("b", "banana"), false);
|
||||
stream.reply(byteStringList("b", "banana"), false);
|
||||
receiveCount.incrementAndGet();
|
||||
}
|
||||
};
|
||||
@@ -179,7 +179,7 @@ public final class SpdyConnectionTest {
|
||||
assertEquals(TYPE_HEADERS, reply.type);
|
||||
assertEquals(HeadersMode.SPDY_REPLY, reply.headersMode);
|
||||
assertTrue(reply.inFinished);
|
||||
assertEquals(asByteStringList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(byteStringList("b", "banana"), reply.nameValueBlock);
|
||||
assertEquals(1, receiveCount.get());
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void bogusReplyFrameDoesNotDisruptConnection() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synReply(false, 42, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 42, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(false, 2, 0);
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -350,7 +350,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void clientClosesClientOutputStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("b", "banana"));
|
||||
peer.acceptFrame(); // TYPE_DATA
|
||||
peer.acceptFrame(); // TYPE_DATA with FLAG_FIN
|
||||
peer.acceptFrame(); // PING
|
||||
@@ -361,7 +361,7 @@ public final class SpdyConnectionTest {
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, false);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, false);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
out.write("square".getBytes(UTF_8));
|
||||
out.flush();
|
||||
@@ -407,7 +407,7 @@ public final class SpdyConnectionTest {
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
connection.ping().roundTripTime(); // Ensure that the RST_CANCEL has been received.
|
||||
try {
|
||||
@@ -449,7 +449,7 @@ public final class SpdyConnectionTest {
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), false, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), false, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
OutputStream out = stream.getOutputStream();
|
||||
in.close();
|
||||
@@ -494,7 +494,7 @@ public final class SpdyConnectionTest {
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
OutputStream out = stream.getOutputStream();
|
||||
in.close();
|
||||
@@ -530,7 +530,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void serverClosesClientInputStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("b", "banana"));
|
||||
peer.sendFrame().data(true, 1, "square".getBytes(UTF_8));
|
||||
peer.play();
|
||||
|
||||
@@ -538,7 +538,7 @@ public final class SpdyConnectionTest {
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket())
|
||||
.handler(REJECT_INCOMING_STREAMS)
|
||||
.build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), false, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), false, true);
|
||||
InputStream in = stream.getInputStream();
|
||||
assertStreamData("square", in);
|
||||
assertEquals(0, connection.openStreamCount());
|
||||
@@ -554,17 +554,17 @@ public final class SpdyConnectionTest {
|
||||
@Test public void remoteDoubleSynReply() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("b", "banana"));
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("c", "cola"), true, true);
|
||||
assertEquals(asByteStringList("a", "android"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("c", "cola"), true, true);
|
||||
assertEquals(byteStringList("a", "android"), stream.getResponseHeaders());
|
||||
connection.ping().roundTripTime(); // Ensure that the 2nd SYN REPLY has been received.
|
||||
try {
|
||||
stream.getInputStream().read();
|
||||
@@ -587,9 +587,9 @@ public final class SpdyConnectionTest {
|
||||
|
||||
@Test public void remoteDoubleSynStream() throws Exception {
|
||||
// write the mocking script
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // SYN_REPLY
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, byteStringList("b", "banana"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.play();
|
||||
|
||||
@@ -598,9 +598,9 @@ public final class SpdyConnectionTest {
|
||||
IncomingStreamHandler handler = new IncomingStreamHandler() {
|
||||
@Override public void receive(SpdyStream stream) throws IOException {
|
||||
receiveCount.incrementAndGet();
|
||||
assertEquals(asByteStringList("a", "android"), stream.getRequestHeaders());
|
||||
assertEquals(byteStringList("a", "android"), stream.getRequestHeaders());
|
||||
assertEquals(null, stream.getErrorCode());
|
||||
stream.reply(asByteStringList("c", "cola"), true);
|
||||
stream.reply(byteStringList("c", "cola"), true);
|
||||
}
|
||||
};
|
||||
new SpdyConnection.Builder(true, peer.openSocket()).handler(handler).build();
|
||||
@@ -619,7 +619,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void remoteSendsDataAfterInFinished() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.sendFrame().data(true, 1, "robot".getBytes("UTF-8"));
|
||||
peer.sendFrame().data(true, 1, "c3po".getBytes("UTF-8")); // Ignored.
|
||||
peer.sendFrame().ping(false, 2, 0); // Ping just to make sure the stream was fastforwarded.
|
||||
@@ -628,8 +628,8 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
assertEquals(asByteStringList("a", "android"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
assertEquals(byteStringList("a", "android"), stream.getResponseHeaders());
|
||||
assertStreamData("robot", stream.getInputStream());
|
||||
|
||||
// verify the peer received what was expected
|
||||
@@ -644,7 +644,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void remoteSendsTooMuchData() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("b", "banana"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("b", "banana"));
|
||||
peer.sendFrame().data(false, 1, new byte[64 * 1024 + 1]);
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(false, 2, 0); // Ping just to make sure the stream was fastforwarded.
|
||||
@@ -653,8 +653,8 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
assertEquals(asByteStringList("b", "banana"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
assertEquals(byteStringList("b", "banana"), stream.getResponseHeaders());
|
||||
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
@@ -679,7 +679,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
try {
|
||||
stream.getResponseHeaders();
|
||||
fail();
|
||||
@@ -709,8 +709,8 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream1 = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
SpdyStream stream2 = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream1 = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
SpdyStream stream2 = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
connection.ping().roundTripTime(); // Ensure that the GO_AWAY has been received.
|
||||
stream1.getOutputStream().write("abc".getBytes(UTF_8));
|
||||
try {
|
||||
@@ -722,7 +722,7 @@ public final class SpdyConnectionTest {
|
||||
stream1.getOutputStream().write("def".getBytes(UTF_8));
|
||||
stream1.getOutputStream().close();
|
||||
try {
|
||||
connection.newStream(asByteStringList("c", "cola"), true, true);
|
||||
connection.newStream(byteStringList("c", "cola"), true, true);
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
assertEquals("shutdown", expected.getMessage());
|
||||
@@ -747,13 +747,13 @@ public final class SpdyConnectionTest {
|
||||
peer.acceptFrame(); // SYN_STREAM 1
|
||||
peer.acceptFrame(); // GOAWAY
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, asByteStringList("b", "b")); // Should be ignored!
|
||||
peer.sendFrame().synStream(false, false, 2, 0, 0, 0, byteStringList("b", "b")); // Should be ignored!
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
connection.newStream(byteStringList("a", "android"), true, true);
|
||||
Ping ping = connection.ping();
|
||||
connection.shutdown(PROTOCOL_ERROR);
|
||||
assertEquals(1, connection.openStreamCount());
|
||||
@@ -800,12 +800,12 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("a", "android"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("a", "android"), true, true);
|
||||
assertEquals(1, connection.openStreamCount());
|
||||
connection.close();
|
||||
assertEquals(0, connection.openStreamCount());
|
||||
try {
|
||||
connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
assertEquals("shutdown", expected.getMessage());
|
||||
@@ -850,14 +850,14 @@ public final class SpdyConnectionTest {
|
||||
@Test public void readTimeoutExpires() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
stream.setReadTimeout(1000);
|
||||
InputStream in = stream.getInputStream();
|
||||
long startNanos = System.nanoTime();
|
||||
@@ -880,16 +880,16 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().headers(1, asByteStringList("c", "c3po"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.sendFrame().headers(1, byteStringList("c", "c3po"));
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
connection.ping().roundTripTime(); // Ensure that the HEADERS has been received.
|
||||
assertEquals(asByteStringList("a", "android", "c", "c3po"), stream.getResponseHeaders());
|
||||
assertEquals(byteStringList("a", "android", "c", "c3po"), stream.getResponseHeaders());
|
||||
|
||||
// verify the peer received what was expected
|
||||
MockSpdyPeer.InFrame synStream = peer.takeFrame();
|
||||
@@ -903,14 +903,14 @@ public final class SpdyConnectionTest {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.acceptFrame(); // PING
|
||||
peer.sendFrame().headers(1, asByteStringList("c", "c3po"));
|
||||
peer.sendFrame().headers(1, byteStringList("c", "c3po"));
|
||||
peer.acceptFrame(); // RST_STREAM
|
||||
peer.sendFrame().ping(true, 1, 0);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
connection.ping().roundTripTime(); // Ensure that the HEADERS has been received.
|
||||
try {
|
||||
stream.getResponseHeaders();
|
||||
@@ -933,7 +933,7 @@ public final class SpdyConnectionTest {
|
||||
@Test public void readSendsWindowUpdate() throws Exception {
|
||||
// Write the mocking script.
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
peer.sendFrame().data(false, 1, new byte[WINDOW_UPDATE_THRESHOLD]);
|
||||
peer.acceptFrame(); // WINDOW UPDATE
|
||||
@@ -943,8 +943,8 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// Play it back.
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
assertEquals(asByteStringList("a", "android"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
assertEquals(byteStringList("a", "android"), stream.getResponseHeaders());
|
||||
InputStream in = stream.getInputStream();
|
||||
int total = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
@@ -976,7 +976,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// Play it back.
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
OutputStream out = stream.getOutputStream();
|
||||
out.write(new byte[Settings.DEFAULT_INITIAL_WINDOW_SIZE]);
|
||||
interruptAfterDelay(500);
|
||||
@@ -997,14 +997,14 @@ public final class SpdyConnectionTest {
|
||||
@Test public void testTruncatedDataFrame() throws Exception {
|
||||
// write the mocking script
|
||||
peer.acceptFrame(); // SYN_STREAM
|
||||
peer.sendFrame().synReply(false, 1, asByteStringList("a", "android"));
|
||||
peer.sendFrame().synReply(false, 1, byteStringList("a", "android"));
|
||||
peer.sendTruncatedFrame(8 + 100).data(false, 1, new byte[1024]);
|
||||
peer.play();
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
assertEquals(asByteStringList("a", "android"), stream.getResponseHeaders());
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
assertEquals(byteStringList("a", "android"), stream.getResponseHeaders());
|
||||
InputStream in = stream.getInputStream();
|
||||
try {
|
||||
Util.readFully(in, new byte[101]);
|
||||
@@ -1035,7 +1035,7 @@ public final class SpdyConnectionTest {
|
||||
|
||||
// play it back
|
||||
SpdyConnection connection = new SpdyConnection.Builder(true, peer.openSocket()).build();
|
||||
SpdyStream stream = connection.newStream(asByteStringList("b", "banana"), true, true);
|
||||
SpdyStream stream = connection.newStream(byteStringList("b", "banana"), true, true);
|
||||
assertEquals("a", stream.getResponseHeaders().get(0).utf8());
|
||||
assertEquals(60, stream.getResponseHeaders().get(1).size());
|
||||
assertStreamData("robot", stream.getInputStream());
|
||||
|
||||
@@ -561,7 +561,7 @@ public final class DiskLruCache implements Closeable {
|
||||
*/
|
||||
private boolean journalRebuildRequired() {
|
||||
final int redundantOpCompactThreshold = 2000;
|
||||
return redundantOpCount >= redundantOpCompactThreshold //
|
||||
return redundantOpCount >= redundantOpCompactThreshold
|
||||
&& redundantOpCount >= lruEntries.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,14 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SpdyTransport implements Transport {
|
||||
private static final ByteString HEADER_METHOD = ByteString.encodeUtf8(":method");
|
||||
private static final ByteString HEADER_PATH = ByteString.encodeUtf8(":path");
|
||||
private static final ByteString HEADER_VERSION = ByteString.encodeUtf8(":version");
|
||||
private static final ByteString HEADER_HOST = ByteString.encodeUtf8(":host");
|
||||
private static final ByteString HEADER_AUTHORITY = ByteString.encodeUtf8(":authority");
|
||||
private static final ByteString HEADER_SCHEME = ByteString.encodeUtf8(":scheme");
|
||||
private static final ByteString NULL = ByteString.of((byte) 0x00);
|
||||
|
||||
private final HttpEngine httpEngine;
|
||||
private final SpdyConnection spdyConnection;
|
||||
private SpdyStream stream;
|
||||
@@ -85,21 +93,21 @@ public final class SpdyTransport implements Transport {
|
||||
Headers headers = request.headers();
|
||||
// TODO: make the known header names constants.
|
||||
List<ByteString> result = new ArrayList<ByteString>(headers.size() + 10);
|
||||
result.add(ByteString.encodeUtf8(":method"));
|
||||
result.add(HEADER_METHOD);
|
||||
result.add(ByteString.encodeUtf8(request.method()));
|
||||
result.add(ByteString.encodeUtf8(":path"));
|
||||
result.add(HEADER_PATH);
|
||||
result.add(ByteString.encodeUtf8(RequestLine.requestPath(request.url())));
|
||||
result.add(ByteString.encodeUtf8(":version"));
|
||||
result.add(HEADER_VERSION);
|
||||
result.add(ByteString.encodeUtf8(version));
|
||||
if (protocol.equals("spdy/3")) {
|
||||
result.add(ByteString.encodeUtf8(":host"));
|
||||
result.add(HEADER_HOST);
|
||||
} else if (protocol.equals("HTTP-draft-09/2.0")) {
|
||||
result.add(ByteString.encodeUtf8(":authority"));
|
||||
result.add(HEADER_AUTHORITY);
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
result.add(ByteString.encodeUtf8(HttpEngine.hostHeader(request.url())));
|
||||
result.add(ByteString.encodeUtf8(":scheme"));
|
||||
result.add(HEADER_SCHEME);
|
||||
result.add(ByteString.encodeUtf8(request.url().getProtocol()));
|
||||
|
||||
Set<ByteString> names = new LinkedHashSet<ByteString>();
|
||||
@@ -119,18 +127,19 @@ public final class SpdyTransport implements Transport {
|
||||
|| name.equals(":scheme")) {
|
||||
continue;
|
||||
}
|
||||
ByteString valueBytes = ByteString.encodeUtf8(value);
|
||||
|
||||
// If we haven't seen this name before, add the pair to the end of the list...
|
||||
if (names.add(ByteString.encodeUtf8(name))) {
|
||||
result.add(ByteString.encodeUtf8(name));
|
||||
result.add(ByteString.encodeUtf8(value));
|
||||
result.add(valueBytes);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...otherwise concatenate the existing values and this value.
|
||||
for (int j = 0; j < result.size(); j += 2) {
|
||||
if (result.get(j).utf8Equals(name)) {
|
||||
result.set(j + 1, ByteString.encodeUtf8(result.get(j + 1).utf8() + "\0" + value));
|
||||
result.set(j + 1, ByteString.concat(result.get(j + 1), NULL, valueBytes));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,20 +20,19 @@ import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.squareup.okhttp.internal.Util.asByteStringList;
|
||||
import static com.squareup.okhttp.internal.Util.byteStringList;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class HeadersTest {
|
||||
@Test public void parseNameValueBlock() throws IOException {
|
||||
List<ByteString> nameValueBlock = asByteStringList( //
|
||||
"cache-control", "no-cache, no-store", //
|
||||
"set-cookie", "Cookie1\u0000Cookie2", //
|
||||
":status", "200 OK", //
|
||||
List<ByteString> nameValueBlock = byteStringList(
|
||||
"cache-control", "no-cache, no-store",
|
||||
"set-cookie", "Cookie1\u0000Cookie2",
|
||||
":status", "200 OK",
|
||||
":version", "HTTP/1.1");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
@@ -57,9 +56,9 @@ public final class HeadersTest {
|
||||
}
|
||||
|
||||
@Test public void readNameValueBlockDropsForbiddenHeadersSpdy3() throws IOException {
|
||||
List<ByteString> nameValueBlock = asByteStringList( //
|
||||
":status", "200 OK", //
|
||||
":version", "HTTP/1.1", //
|
||||
List<ByteString> nameValueBlock = byteStringList(
|
||||
":status", "200 OK",
|
||||
":version", "HTTP/1.1",
|
||||
"connection", "close");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
@@ -71,9 +70,9 @@ public final class HeadersTest {
|
||||
}
|
||||
|
||||
@Test public void readNameValueBlockDropsForbiddenHeadersHttp2() throws IOException {
|
||||
List<ByteString> nameValueBlock = asByteStringList( //
|
||||
":status", "200 OK", //
|
||||
":version", "HTTP/1.1", //
|
||||
List<ByteString> nameValueBlock = byteStringList(
|
||||
":status", "200 OK",
|
||||
":version", "HTTP/1.1",
|
||||
"connection", "close");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
@@ -93,14 +92,14 @@ public final class HeadersTest {
|
||||
.header(":status", "200 OK")
|
||||
.build();
|
||||
List<ByteString> nameValueBlock = SpdyTransport.writeNameValueBlock(request, "spdy/3", "HTTP/1.1");
|
||||
List<ByteString> expected = asByteStringList( //
|
||||
":method", "GET", //
|
||||
":path", "/", //
|
||||
":version", "HTTP/1.1", //
|
||||
":host", "square.com", //
|
||||
":scheme", "http", //
|
||||
"cache-control", "no-cache, no-store", //
|
||||
"set-cookie", "Cookie1\u0000Cookie2", //
|
||||
List<ByteString> expected = byteStringList(
|
||||
":method", "GET",
|
||||
":path", "/",
|
||||
":version", "HTTP/1.1",
|
||||
":host", "square.com",
|
||||
":scheme", "http",
|
||||
"cache-control", "no-cache, no-store",
|
||||
"set-cookie", "Cookie1\u0000Cookie2",
|
||||
":status", "200 OK");
|
||||
assertEquals(expected, nameValueBlock);
|
||||
}
|
||||
@@ -111,11 +110,11 @@ public final class HeadersTest {
|
||||
.header("Connection", "close")
|
||||
.header("Transfer-Encoding", "chunked")
|
||||
.build();
|
||||
List<ByteString> expected = asByteStringList( //
|
||||
":method", "GET", //
|
||||
":path", "/", //
|
||||
":version", "HTTP/1.1", //
|
||||
":host", "square.com", //
|
||||
List<ByteString> expected = byteStringList(
|
||||
":method", "GET",
|
||||
":path", "/",
|
||||
":version", "HTTP/1.1",
|
||||
":host", "square.com",
|
||||
":scheme", "http");
|
||||
assertEquals(expected, SpdyTransport.writeNameValueBlock(request, "spdy/3", "HTTP/1.1"));
|
||||
}
|
||||
@@ -126,11 +125,11 @@ public final class HeadersTest {
|
||||
.header("Connection", "upgrade")
|
||||
.header("Upgrade", "websocket")
|
||||
.build();
|
||||
List<ByteString> expected = asByteStringList( //
|
||||
":method", "GET", //
|
||||
":path", "/", //
|
||||
":version", "HTTP/1.1", //
|
||||
":authority", "square.com", //
|
||||
List<ByteString> expected = byteStringList(
|
||||
":method", "GET",
|
||||
":path", "/",
|
||||
":version", "HTTP/1.1",
|
||||
":authority", "square.com",
|
||||
":scheme", "http");
|
||||
assertEquals(expected,
|
||||
SpdyTransport.writeNameValueBlock(request, "HTTP-draft-09/2.0", "HTTP/1.1"));
|
||||
|
||||
Reference in New Issue
Block a user