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