13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2012 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage com.squareup.okhttp.internal.http;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Headers;
193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Protocol;
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Request;
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Response;
223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.spdy.Header;
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException;
243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.List;
253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Test;
263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static com.squareup.okhttp.internal.Util.headerEntries;
283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertEquals;
293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertNull;
303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class HeadersTest {
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void parseNameValueBlock() throws IOException {
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> headerBlock = headerEntries(
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "cache-control", "no-cache, no-store",
353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "set-cookie", "Cookie1\u0000Cookie2",
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":status", "200 OK",
373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":version", "HTTP/1.1");
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder().url("http://square.com/").build();
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Response response =
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SpdyTransport.readNameValueBlock(headerBlock, Protocol.SPDY_3).request(request).build();
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Headers headers = response.headers();
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(4, headers.size());
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("HTTP/1.1 200 OK", response.statusLine());
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("no-cache, no-store", headers.get("cache-control"));
453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("Cookie2", headers.get("set-cookie"));
463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(Protocol.SPDY_3.name.utf8(), headers.get(OkHeaders.SELECTED_PROTOCOL));
473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0));
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(0));
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("cache-control", headers.name(1));
503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("no-cache, no-store", headers.value(1));
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("set-cookie", headers.name(2));
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("Cookie1", headers.value(2));
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("set-cookie", headers.name(3));
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("Cookie2", headers.value(3));
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertNull(headers.get(":status"));
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertNull(headers.get(":version"));
573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void readNameValueBlockDropsForbiddenHeadersSpdy3() throws IOException {
603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> headerBlock = headerEntries(
613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":status", "200 OK",
623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":version", "HTTP/1.1",
633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "connection", "close");
643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder().url("http://square.com/").build();
653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Response response =
663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SpdyTransport.readNameValueBlock(headerBlock, Protocol.SPDY_3).request(request).build();
673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Headers headers = response.headers();
683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(1, headers.size());
693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0));
703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(0));
713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void readNameValueBlockDropsForbiddenHeadersHttp2() throws IOException {
743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> headerBlock = headerEntries(
753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":status", "200 OK",
763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":version", "HTTP/1.1",
773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "connection", "close");
783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder().url("http://square.com/").build();
793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Response response = SpdyTransport.readNameValueBlock(headerBlock, Protocol.HTTP_2)
803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .request(request).build();
813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Headers headers = response.headers();
823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(1, headers.size());
833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(0));
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(Protocol.HTTP_2.name.utf8(), headers.value(0));
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void toNameValueBlock() {
883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url("http://square.com/")
903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("cache-control", "no-cache, no-store")
913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("set-cookie", "Cookie1")
923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("set-cookie", "Cookie2")
933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header(":status", "200 OK")
943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> headerBlock =
963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1");
973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> expected = headerEntries(
983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":method", "GET",
993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":path", "/",
1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":version", "HTTP/1.1",
1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":host", "square.com",
1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":scheme", "http",
1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "cache-control", "no-cache, no-store",
1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        "set-cookie", "Cookie1\u0000Cookie2",
1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":status", "200 OK");
1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(expected, headerBlock);
1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void toNameValueBlockDropsForbiddenHeadersSpdy3() {
1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url("http://square.com/")
1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("Connection", "close")
1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("Transfer-Encoding", "chunked")
1143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> expected = headerEntries(
1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":method", "GET",
1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":path", "/",
1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":version", "HTTP/1.1",
1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":host", "square.com",
1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":scheme", "http");
1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(expected, SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1"));
1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void toNameValueBlockDropsForbiddenHeadersHttp2() {
1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url("http://square.com/")
1273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("Connection", "upgrade")
1283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("Upgrade", "websocket")
1293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
1303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Header> expected = headerEntries(
1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":method", "GET",
1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":path", "/",
1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":authority", "square.com",
1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        ":scheme", "http");
1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(expected,
1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SpdyTransport.writeNameValueBlock(request, Protocol.HTTP_2, "HTTP/1.1"));
1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
139