@Test public void parseNameValueBlock() throws IOException { List<Header> headerBlock = headerEntries( "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 = SpdyTransport.readNameValueBlock(headerBlock, Protocol.SPDY_3).request(request).build(); Headers headers = response.headers(); assertEquals(4, headers.size()); assertEquals("HTTP/1.1 200 OK", response.statusLine()); assertEquals("no-cache, no-store", headers.get("cache-control")); assertEquals("Cookie2", headers.get("set-cookie")); assertEquals(Protocol.SPDY_3.name.utf8(), headers.get(OkHeaders.SELECTED_PROTOCOL)); assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0)); assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(0)); assertEquals("cache-control", headers.name(1)); assertEquals("no-cache, no-store", headers.value(1)); assertEquals("set-cookie", headers.name(2)); assertEquals("Cookie1", headers.value(2)); assertEquals("set-cookie", headers.name(3)); assertEquals("Cookie2", headers.value(3)); assertNull(headers.get(":status")); assertNull(headers.get(":version")); }
@Test public void toNameValueBlock() { Request request = new Request.Builder() .url("http://square.com/") .header("cache-control", "no-cache, no-store") .addHeader("set-cookie", "Cookie1") .addHeader("set-cookie", "Cookie2") .header(":status", "200 OK") .build(); List<Header> headerBlock = SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1"); List<Header> expected = headerEntries( ":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, headerBlock); }
private void pushPromises(SpdyStream stream, List<PushPromise> promises) throws IOException { for (PushPromise pushPromise : promises) { List<Header> pushedHeaders = new ArrayList<Header>(); pushedHeaders.add(new Header(stream.getConnection().getProtocol() == Protocol.SPDY_3 ? Header.TARGET_HOST : Header.TARGET_AUTHORITY, getUrl(pushPromise.getPath()).getHost())); pushedHeaders.add(new Header(Header.TARGET_METHOD, pushPromise.getMethod())); pushedHeaders.add(new Header(Header.TARGET_PATH, pushPromise.getPath())); for (int i = 0, size = pushPromise.getHeaders().size(); i < size; i++) { String header = pushPromise.getHeaders().get(i); String[] headerParts = header.split(":", 2); if (headerParts.length != 2) { throw new AssertionError("Unexpected header: " + header); } pushedHeaders.add(new Header(headerParts[0], headerParts[1].trim())); } String requestLine = pushPromise.getMethod() + ' ' + pushPromise.getPath() + " HTTP/1.1"; List<Integer> chunkSizes = Collections.emptyList(); // No chunked encoding for SPDY. requestQueue.add(new RecordedRequest(requestLine, pushPromise.getHeaders(), chunkSizes, 0, Util.EMPTY_BYTE_ARRAY, sequenceNumber.getAndIncrement(), socket)); byte[] pushedBody = pushPromise.getResponse().getBody(); SpdyStream pushedStream = stream.getConnection().pushStream(stream.getId(), pushedHeaders, pushedBody.length > 0); writeResponse(pushedStream, pushPromise.getResponse()); } }
public static List<Header> headerEntries(String... elements) { List<Header> result = new ArrayList<>(elements.length / 2); for (int i = 0; i < elements.length; i += 2) { result.add(new Header(elements[i], elements[i + 1])); } return result; }
public static List<Header> headerEntries(String... elements) { List<Header> result = new ArrayList<Header>(elements.length / 2); for (int i = 0; i < elements.length; i += 2) { result.add(new Header(elements[i], elements[i + 1])); } return result; }
@Test public void readNameValueBlockDropsForbiddenHeadersSpdy3() throws IOException { List<Header> headerBlock = headerEntries( ":status", "200 OK", ":version", "HTTP/1.1", "connection", "close"); Request request = new Request.Builder().url("http://square.com/").build(); Response response = SpdyTransport.readNameValueBlock(headerBlock, Protocol.SPDY_3).request(request).build(); Headers headers = response.headers(); assertEquals(1, headers.size()); assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0)); assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(0)); }
@Test public void readNameValueBlockDropsForbiddenHeadersHttp2() throws IOException { List<Header> headerBlock = headerEntries( ":status", "200 OK", ":version", "HTTP/1.1", "connection", "close"); Request request = new Request.Builder().url("http://square.com/").build(); Response response = SpdyTransport.readNameValueBlock(headerBlock, Protocol.HTTP_2) .request(request).build(); Headers headers = response.headers(); assertEquals(1, headers.size()); assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0)); assertEquals(Protocol.HTTP_2.name.utf8(), headers.value(0)); }
@Test public void toNameValueBlockDropsForbiddenHeadersSpdy3() { Request request = new Request.Builder() .url("http://square.com/") .header("Connection", "close") .header("Transfer-Encoding", "chunked") .build(); List<Header> expected = headerEntries( ":method", "GET", ":path", "/", ":version", "HTTP/1.1", ":host", "square.com", ":scheme", "http"); assertEquals(expected, SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1")); }
@Test public void toNameValueBlockDropsForbiddenHeadersHttp2() { Request request = new Request.Builder() .url("http://square.com/") .header("Connection", "upgrade") .header("Upgrade", "websocket") .build(); List<Header> expected = headerEntries( ":method", "GET", ":path", "/", ":authority", "square.com", ":scheme", "http"); assertEquals(expected, SpdyTransport.writeNameValueBlock(request, Protocol.HTTP_2, "HTTP/1.1")); }
public final Response.Builder readResponseHeaders() throws IOException { List localList = this.stream.getResponseHeaders(); Protocol localProtocol = this.spdyConnection.protocol; Object localObject1 = null; Object localObject2 = "HTTP/1.1"; Headers.Builder localBuilder = new Headers.Builder(); localBuilder.set(OkHeaders.SELECTED_PROTOCOL, localProtocol.toString()); int i = localList.size(); int j = 0; while (j < i) { ByteString localByteString = ((Header)localList.get(j)).name; String str = ((Header)localList.get(j)).value.utf8(); Object localObject3 = localObject2; int k = 0; if (k < str.length()) { int m = str.indexOf(0, k); if (m == -1) { m = str.length(); } Object localObject4 = str.substring(k, m); if (localByteString.equals(Header.RESPONSE_STATUS)) {} for (;;) { int n = m + 1; localObject1 = localObject4; k = n; break; if (localByteString.equals(Header.VERSION)) { localObject3 = localObject4; localObject4 = localObject1; } else { if (!isProhibitedHeader(localProtocol, localByteString)) { localBuilder.add(localByteString.utf8(), (String)localObject4); } localObject4 = localObject1; } } } j++; localObject2 = localObject3; } if (localObject1 == null) { throw new ProtocolException("Expected ':status' header not present"); } StatusLine localStatusLine = StatusLine.parse((String)localObject2 + " " + localObject1); Response.Builder localBuilder1 = new Response.Builder(); localBuilder1.protocol = localProtocol; localBuilder1.code = localStatusLine.code; localBuilder1.message = localStatusLine.message; return localBuilder1.headers(localBuilder.build()); }
/** * Returns a list of alternating names and values containing a SPDY request. * Names are all lowercase. No names are repeated. If any name has multiple * values, they are concatenated using "\0" as a delimiter. */ public static List<Header> writeNameValueBlock(Request request, Protocol protocol, String version) { Headers headers = request.headers(); List<Header> result = new ArrayList<>(headers.size() + 10); result.add(new Header(TARGET_METHOD, request.method())); result.add(new Header(TARGET_PATH, RequestLine.requestPath(request.url()))); String host = HttpEngine.hostHeader(request.url()); if (Protocol.SPDY_3 == protocol) { result.add(new Header(VERSION, version)); result.add(new Header(TARGET_HOST, host)); } else if (Protocol.HTTP_2 == protocol) { result.add(new Header(TARGET_AUTHORITY, host)); // Optional in HTTP/2 } else { throw new AssertionError(); } result.add(new Header(TARGET_SCHEME, request.url().getProtocol())); Set<ByteString> names = new LinkedHashSet<ByteString>(); for (int i = 0; i < headers.size(); i++) { // header names must be lowercase. ByteString name = ByteString.encodeUtf8(headers.name(i).toLowerCase(Locale.US)); String value = headers.value(i); // Drop headers that are forbidden when layering HTTP over SPDY. if (isProhibitedHeader(protocol, name)) continue; // They shouldn't be set, but if they are, drop them. We've already written them! if (name.equals(TARGET_METHOD) || name.equals(TARGET_PATH) || name.equals(TARGET_SCHEME) || name.equals(TARGET_AUTHORITY) || name.equals(TARGET_HOST) || name.equals(VERSION)) { continue; } // If we haven't seen this name before, add the pair to the end of the list... if (names.add(name)) { result.add(new Header(name, value)); continue; } // ...otherwise concatenate the existing values and this value. for (int j = 0; j < result.size(); j++) { if (result.get(j).name.equals(name)) { String concatenated = joinOnNull(result.get(j).value.utf8(), value); result.set(j, new Header(name, concatenated)); break; } } } return result; }
/** * Returns a list of alternating names and values containing a SPDY request. * Names are all lowercase. No names are repeated. If any name has multiple * values, they are concatenated using "\0" as a delimiter. */ public static List<Header> writeNameValueBlock(Request request, Protocol protocol, String version) { Headers headers = request.headers(); // TODO: make the known header names constants. List<Header> result = new ArrayList<Header>(headers.size() + 10); result.add(new Header(TARGET_METHOD, request.method())); result.add(new Header(TARGET_PATH, RequestLine.requestPath(request.url()))); String host = HttpEngine.hostHeader(request.url()); if (Protocol.SPDY_3 == protocol) { result.add(new Header(VERSION, version)); result.add(new Header(TARGET_HOST, host)); } else if (Protocol.HTTP_2 == protocol) { result.add(new Header(TARGET_AUTHORITY, host)); } else { throw new AssertionError(); } result.add(new Header(TARGET_SCHEME, request.url().getProtocol())); Set<ByteString> names = new LinkedHashSet<ByteString>(); for (int i = 0; i < headers.size(); i++) { // header names must be lowercase. ByteString name = ByteString.encodeUtf8(headers.name(i).toLowerCase(Locale.US)); String value = headers.value(i); // Drop headers that are forbidden when layering HTTP over SPDY. if (isProhibitedHeader(protocol, name)) continue; // They shouldn't be set, but if they are, drop them. We've already written them! if (name.equals(TARGET_METHOD) || name.equals(TARGET_PATH) || name.equals(TARGET_SCHEME) || name.equals(TARGET_AUTHORITY) || name.equals(TARGET_HOST) || name.equals(VERSION)) { continue; } // If we haven't seen this name before, add the pair to the end of the list... if (names.add(name)) { result.add(new Header(name, value)); continue; } // ...otherwise concatenate the existing values and this value. for (int j = 0; j < result.size(); j++) { if (result.get(j).name.equals(name)) { String concatenated = joinOnNull(result.get(j).value.utf8(), value); result.set(j, new Header(name, concatenated)); break; } } } return result; }