From 379e4ff19987539fdf8fe397a4b948e327ea7600 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Mon, 6 Jan 2014 20:54:48 -0800 Subject: [PATCH] feedback from #413 and a few optimizations on hpack. --- .../okhttp/internal/spdy/SpdyServer.java | 11 +- .../squareup/okhttp/internal/ByteString.java | 14 ++ .../com/squareup/okhttp/internal/Util.java | 8 +- .../okhttp/internal/spdy/FrameReader.java | 6 +- .../okhttp/internal/spdy/HpackDraft05.java | 40 +++--- .../okhttp/internal/ByteStringTest.java | 10 ++ .../internal/spdy/HpackDraft05Test.java | 42 +++--- .../internal/spdy/Http20Draft09Test.java | 10 +- .../internal/spdy/SpdyConnectionTest.java | 126 +++++++++--------- .../okhttp/internal/DiskLruCache.java | 2 +- .../okhttp/internal/http/SpdyTransport.java | 25 ++-- .../okhttp/internal/http/HeadersTest.java | 59 ++++---- 12 files changed, 193 insertions(+), 160 deletions(-) diff --git a/mockwebserver/src/main/java/com/squareup/okhttp/internal/spdy/SpdyServer.java b/mockwebserver/src/main/java/com/squareup/okhttp/internal/spdy/SpdyServer.java index 5a1b0a7ec..9b3d4c11d 100644 --- a/mockwebserver/src/main/java/com/squareup/okhttp/internal/spdy/SpdyServer.java +++ b/mockwebserver/src/main/java/com/squareup/okhttp/internal/spdy/SpdyServer.java @@ -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 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 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) { diff --git a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/ByteString.java b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/ByteString.java index 6cbdfb611..b6a688e3d 100644 --- a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/ByteString.java +++ b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/ByteString.java @@ -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. } diff --git a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/Util.java b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/Util.java index b160bb6e7..c5bb07eaa 100644 --- a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/Util.java +++ b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/Util.java @@ -393,11 +393,11 @@ public final class Util { }; } - public static List asByteStringList(String... strings) { - List out = new ArrayList(strings.length); + public static List byteStringList(String... strings) { + List result = new ArrayList(strings.length); for (String string : strings) { - out.add(ByteString.encodeUtf8(string)); + result.add(ByteString.encodeUtf8(string)); } - return out; + return result; } } diff --git a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/FrameReader.java b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/FrameReader.java index 046580cc8..a2228601a 100644 --- a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/FrameReader.java +++ b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/FrameReader.java @@ -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 nameValueBlock, HeadersMode headersMode); diff --git a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft05.java b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft05.java index 30ab507b3..ef98fe95e 100644 --- a/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft05.java +++ b/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/spdy/HpackDraft05.java @@ -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 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 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 headerTable = new ArrayList(); // TODO: default capacity? + final List headerTable = new ArrayList(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; } diff --git a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/ByteStringTest.java b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/ByteStringTest.java index ab142f0a1..95b91d176 100644 --- a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/ByteStringTest.java +++ b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/ByteStringTest.java @@ -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)); } diff --git a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft05Test.java b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft05Test.java index f600423c1..4b8fef9f4 100644 --- a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft05Test.java +++ b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/HpackDraft05Test.java @@ -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 sentHeaders = asByteStringList("foo", new String(tooLarge)); + final List 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 sentHeaders = asByteStringList("name", "value"); + List sentHeaders = byteStringList("name", "value"); hpackWriter.writeHeaders(sentHeaders); ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); HpackDraft05.Reader reader = new HpackDraft05.Reader(new DataInputStream(bytesIn)); diff --git a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft09Test.java b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft09Test.java index 6f58032aa..4c750712c 100644 --- a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft09Test.java +++ b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/Http20Draft09Test.java @@ -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 sentHeaders = asByteStringList("name", "value"); + final List 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); } }); diff --git a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/SpdyConnectionTest.java b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/SpdyConnectionTest.java index 6490bc863..8d263885b 100644 --- a/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/SpdyConnectionTest.java +++ b/okhttp-protocols/src/test/java/com/squareup/okhttp/internal/spdy/SpdyConnectionTest.java @@ -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()); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/DiskLruCache.java b/okhttp/src/main/java/com/squareup/okhttp/internal/DiskLruCache.java index a73472c45..69f3c3156 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/DiskLruCache.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/DiskLruCache.java @@ -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(); } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java index 2962b1ccb..6004f238d 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java @@ -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 result = new ArrayList(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 names = new LinkedHashSet(); @@ -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; } } diff --git a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java index 2387b3bde..238a199a0 100644 --- a/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java +++ b/okhttp/src/test/java/com/squareup/okhttp/internal/http/HeadersTest.java @@ -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 nameValueBlock = asByteStringList( // - "cache-control", "no-cache, no-store", // - "set-cookie", "Cookie1\u0000Cookie2", // - ":status", "200 OK", // + List 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 nameValueBlock = asByteStringList( // - ":status", "200 OK", // - ":version", "HTTP/1.1", // + List 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 nameValueBlock = asByteStringList( // - ":status", "200 OK", // - ":version", "HTTP/1.1", // + List 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 nameValueBlock = SpdyTransport.writeNameValueBlock(request, "spdy/3", "HTTP/1.1"); - List 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 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 expected = asByteStringList( // - ":method", "GET", // - ":path", "/", // - ":version", "HTTP/1.1", // - ":host", "square.com", // + List 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 expected = asByteStringList( // - ":method", "GET", // - ":path", "/", // - ":version", "HTTP/1.1", // - ":authority", "square.com", // + List 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"));