1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/network/public/cpp/header_util.h"
6 
7 #include "base/strings/string_piece.h"
8 #include "base/strings/string_util.h"
9 #include "net/http/http_request_headers.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 
12 namespace network {
13 
TEST(HeaderUtilTest,IsRequestHeaderSafe)14 TEST(HeaderUtilTest, IsRequestHeaderSafe) {
15   const struct HeaderKeyValuePair {
16     const char* key;
17     const char* value;
18     bool is_safe;
19   } kHeaders[] = {
20       {"foo", "bar", true},
21 
22       {net::HttpRequestHeaders::kContentLength, "42", false},
23       {net::HttpRequestHeaders::kHost, "foo.test", false},
24       {"Trailer", "header-names", false},
25       {"Upgrade", "websocket", false},
26       {"Upgrade", "webbedsocket", false},
27       {"hOsT", "foo.test", false},
28 
29       {net::HttpRequestHeaders::kConnection, "Upgrade", false},
30       {net::HttpRequestHeaders::kConnection, "Close", true},
31       {net::HttpRequestHeaders::kTransferEncoding, "Chunked", false},
32       {net::HttpRequestHeaders::kTransferEncoding, "Chunky", false},
33       {"cOnNeCtIoN", "uPgRaDe", false},
34 
35       {net::HttpRequestHeaders::kProxyAuthorization,
36        "Basic Zm9vOmJhcg==", false},
37       {"Proxy-Foo", "bar", false},
38       {"PrOxY-FoO", "bar", false},
39 
40       {"dnt", "1", true},
41   };
42 
43   for (const auto& header : kHeaders) {
44     SCOPED_TRACE(header.key);
45     SCOPED_TRACE(header.value);
46     EXPECT_EQ(header.is_safe, IsRequestHeaderSafe(header.key, header.value));
47   }
48 }
49 
TEST(HeaderUtilTest,AreRequestHeadersSafe)50 TEST(HeaderUtilTest, AreRequestHeadersSafe) {
51   const struct HeaderKeyValuePair {
52     const char* key;
53     const char* value;
54     bool is_safe;
55   } kHeaders[] = {
56       {"foo", "bar", true},
57 
58       {net::HttpRequestHeaders::kContentLength, "42", false},
59       {net::HttpRequestHeaders::kHost, "foo.test", false},
60       {"hOsT", "foo.test", false},
61       {"Trailer", "header-names", false},
62       {"Te", "deflate", false},
63       {"Upgrade", "websocket", false},
64       {"Upgrade", "webbedsocket", false},
65       {"Cookie2", "tastiness=5", false},
66       {"Keep-Alive", "timeout=5, max=1000", false},
67       {net::HttpRequestHeaders::kTransferEncoding, "gzip", false},
68 
69       {net::HttpRequestHeaders::kConnection, "Upgrade", false},
70       {net::HttpRequestHeaders::kConnection, "Close", true},
71       {net::HttpRequestHeaders::kTransferEncoding, "Chunked", false},
72       {net::HttpRequestHeaders::kTransferEncoding, "Chunky", false},
73       {"cOnNeCtIoN", "uPgRaDe", false},
74 
75       {net::HttpRequestHeaders::kProxyAuthorization,
76        "Basic Zm9vOmJhcg==", false},
77       {"Proxy-Foo", "bar", false},
78       {"PrOxY-FoO", "bar", false},
79 
80       {"dnt", "1", true},
81   };
82 
83   // Check each header in isolation, and all combinations of two header
84   // key/value pairs that have different keys.
85   for (const auto& header1 : kHeaders) {
86     net::HttpRequestHeaders request_headers1;
87     request_headers1.SetHeader(header1.key, header1.value);
88     EXPECT_EQ(header1.is_safe, AreRequestHeadersSafe(request_headers1));
89 
90     for (const auto& header2 : kHeaders) {
91       if (base::EqualsCaseInsensitiveASCII(header1.key, header2.key))
92         continue;
93       SCOPED_TRACE(header1.key);
94       SCOPED_TRACE(header1.value);
95       SCOPED_TRACE(header2.key);
96       SCOPED_TRACE(header2.value);
97 
98       net::HttpRequestHeaders request_headers2;
99       request_headers2.SetHeader(header1.key, header1.value);
100       request_headers2.SetHeader(header2.key, header2.value);
101       EXPECT_EQ(header1.is_safe && header2.is_safe,
102                 AreRequestHeadersSafe(request_headers2));
103     }
104   }
105 }
106 
107 }  // namespace network
108