xref: /aosp_15_r20/external/cronet/net/url_request/redirect_util_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
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 "net/url_request/redirect_util.h"
6 
7 #include <string>
8 
9 #include "net/http/http_request_headers.h"
10 #include "net/url_request/redirect_info.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "url/gurl.h"
13 
14 namespace net {
15 namespace {
16 
TEST(RedirectUtilTest,UpdateHttpRequest)17 TEST(RedirectUtilTest, UpdateHttpRequest) {
18   const GURL original_url("https://www.example.com/test.php");
19   const char kContentLengthValue[] = "100";
20   const char kContentTypeValue[] = "text/plain; charset=utf-8";
21   const char kContentEncoding[] = "Content-Encoding";
22   const char kContentEncodingValue[] = "gzip";
23   const char kContentLanguage[] = "Content-Language";
24   const char kContentLanguageValue[] = "tlh";
25   const char kContentLocation[] = "Content-Location";
26   const char kContentLocationValue[] = "https://somewhere.test/";
27   const char kCustomHeader[] = "Custom-Header-For-Test";
28   const char kCustomHeaderValue[] = "custom header value";
29 
30   struct TestCase {
31     const char* original_method;
32     const char* new_method;
33     const char* new_url;
34     const struct {
35       const char* name;
36       const char* value;
37     } modified_headers[2];
38     bool expected_should_clear_upload;
39     // nullptr if the origin header should not exist
40     const char* expected_origin_header;
41   };
42   const TestCase kTests[] = {
43       {
44           "POST" /* original_method */,
45           "POST" /* new_method */,
46           "https://www.example.com/redirected.php" /* new_url */,
47           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
48           false /* expected_should_clear_upload */,
49           "https://origin.example.com" /* expected_origin_header */
50       },
51       {
52           "POST" /* original_method */,
53           "GET" /* new_method */,
54           "https://www.example.com/redirected.php" /* new_url */,
55           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
56           true /* expected_should_clear_upload */,
57           nullptr /* expected_origin_header */
58       },
59       {
60           "POST" /* original_method */,
61           "POST" /* new_method */,
62           "https://other.example.com/redirected.php" /* new_url */,
63           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
64           false /* expected_should_clear_upload */,
65           "null" /* expected_origin_header */
66       },
67       {
68           "POST" /* original_method */,
69           "GET" /* new_method */,
70           "https://other.example.com/redirected.php" /* new_url */,
71           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
72           true /* expected_should_clear_upload */,
73           nullptr /* expected_origin_header */
74       },
75       {
76           "PUT" /* original_method */,
77           "GET" /* new_method */,
78           "https://www.example.com/redirected.php" /* new_url */,
79           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
80           true /* expected_should_clear_upload */,
81           nullptr /* expected_origin_header */
82       },
83       {
84           "FOOT" /* original_method */,
85           "GET" /* new_method */,
86           "https://www.example.com/redirected.php" /* new_url */,
87           {{"Header1", "Value1"}, {"Header2", "Value2"}} /* modified_headers */,
88           true /* expected_should_clear_upload */,
89           nullptr /* expected_origin_header */
90       },
91   };
92 
93   for (const auto& test : kTests) {
94     SCOPED_TRACE(::testing::Message()
95                  << "original_method: " << test.original_method
96                  << " new_method: " << test.new_method
97                  << " new_url: " << test.new_url);
98     RedirectInfo redirect_info;
99     redirect_info.new_method = test.new_method;
100     redirect_info.new_url = GURL(test.new_url);
101 
102     net::HttpRequestHeaders modified_headers;
103     for (const auto& headers : test.modified_headers) {
104       ASSERT_TRUE(!!headers.name);  // Currently all test case has this.
105       modified_headers.SetHeader(headers.name, headers.value);
106     }
107     std::string expected_modified_header1, expected_modified_header2;
108     modified_headers.GetHeader("Header1", &expected_modified_header1);
109     modified_headers.GetHeader("Header2", &expected_modified_header2);
110 
111     HttpRequestHeaders request_headers;
112     request_headers.SetHeader(HttpRequestHeaders::kOrigin,
113                               "https://origin.example.com");
114     request_headers.SetHeader(HttpRequestHeaders::kContentLength,
115                               kContentLengthValue);
116     request_headers.SetHeader(HttpRequestHeaders::kContentType,
117                               kContentTypeValue);
118     request_headers.SetHeader(kContentEncoding, kContentEncodingValue);
119     request_headers.SetHeader(kContentLanguage, kContentLanguageValue);
120     request_headers.SetHeader(kContentLocation, kContentLocationValue);
121     request_headers.SetHeader(kCustomHeader, kCustomHeaderValue);
122     request_headers.SetHeader("Header1", "Initial-Value1");
123 
124     bool should_clear_upload = !test.expected_should_clear_upload;
125 
126     RedirectUtil::UpdateHttpRequest(
127         original_url, test.original_method, redirect_info,
128         std::nullopt /* removed_headers */, modified_headers, &request_headers,
129         &should_clear_upload);
130     EXPECT_EQ(test.expected_should_clear_upload, should_clear_upload);
131 
132     std::string content_length;
133     EXPECT_EQ(!test.expected_should_clear_upload,
134               request_headers.GetHeader(HttpRequestHeaders::kContentLength,
135                                         &content_length));
136     std::string content_type;
137     EXPECT_EQ(!test.expected_should_clear_upload,
138               request_headers.GetHeader(HttpRequestHeaders::kContentType,
139                                         &content_type));
140     std::string content_encoding;
141     EXPECT_EQ(!test.expected_should_clear_upload,
142               request_headers.GetHeader(kContentEncoding, &content_encoding));
143     std::string content_language;
144     EXPECT_EQ(!test.expected_should_clear_upload,
145               request_headers.GetHeader(kContentLanguage, &content_language));
146     std::string content_location;
147     EXPECT_EQ(!test.expected_should_clear_upload,
148               request_headers.GetHeader(kContentLocation, &content_location));
149     if (!test.expected_should_clear_upload) {
150       EXPECT_EQ(kContentLengthValue, content_length);
151       EXPECT_EQ(kContentTypeValue, content_type);
152       EXPECT_EQ(kContentEncodingValue, content_encoding);
153       EXPECT_EQ(kContentLanguageValue, content_language);
154       EXPECT_EQ(kContentLocationValue, content_location);
155     }
156 
157     std::string custom_header;
158     EXPECT_TRUE(request_headers.GetHeader(kCustomHeader, &custom_header));
159     EXPECT_EQ(kCustomHeaderValue, custom_header);
160 
161     std::string origin_header_value;
162     EXPECT_EQ(test.expected_origin_header != nullptr,
163               request_headers.GetHeader(HttpRequestHeaders::kOrigin,
164                                         &origin_header_value));
165     if (test.expected_origin_header) {
166       EXPECT_EQ(test.expected_origin_header, origin_header_value);
167     }
168 
169     std::string modified_header1, modified_header2;
170     EXPECT_TRUE(request_headers.GetHeader("Header1", &modified_header1));
171     EXPECT_EQ(expected_modified_header1, modified_header1);
172     EXPECT_TRUE(request_headers.GetHeader("Header2", &modified_header2));
173     EXPECT_EQ(expected_modified_header2, modified_header2);
174   }
175 }
176 
TEST(RedirectUtilTest,RemovedHeaders)177 TEST(RedirectUtilTest, RemovedHeaders) {
178   struct TestCase {
179     std::vector<const char*> initial_headers;
180     std::vector<const char*> modified_headers;
181     std::vector<const char*> removed_headers;
182     std::vector<const char*> final_headers;
183   };
184   const TestCase kTests[] = {
185       // Remove no headers (empty vector).
186       {
187           {},  // Initial headers
188           {},  // Modified headers
189           {},  // Removed headers
190           {},  // Final headers
191       },
192       // Remove an existing header.
193       {
194           {"A:0"},  // Initial headers
195           {},       // Modified headers
196           {"A"},    // Removed headers
197           {},       // Final headers
198       },
199       // Remove a missing header.
200       {
201           {},     // Initial headers
202           {},     // Modified headers
203           {"A"},  // Removed headers
204           {},     // Final headers
205       },
206       // Remove two different headers.
207       {
208           {"A:0", "B:0"},  // Initial headers
209           {},              // Modified headers
210           {"A", "B"},      // Removed headers
211           {},              // Final headers
212       },
213       // Remove two times the same headers.
214       {
215           {"A:0"},     // Initial headers
216           {},          // Modified headers
217           {"A", "A"},  // Removed headers
218           {},          // Final headers
219       },
220       // Remove an existing header that is also modified.
221       {
222           {"A:0"},  // Initial headers
223           {"A:1"},  // Modified headers
224           {"A"},    // Removed headers
225           {"A:1"},  // Final headers
226       },
227       // Some headers are removed, some aren't.
228       {
229           {"A:0", "B:0"},  // Initial headers
230           {},              // Modified headers
231           {"A"},           // Removed headers
232           {"B:0"},         // Final headers
233       },
234   };
235 
236   for (const auto& test : kTests) {
237     HttpRequestHeaders initial_headers, modified_headers, final_headers;
238     std::vector<std::string> removed_headers;
239     for (const char* header : test.initial_headers)
240       initial_headers.AddHeaderFromString(header);
241     for (const char* header : test.modified_headers)
242       modified_headers.AddHeaderFromString(header);
243     for (const char* header : test.removed_headers)
244       removed_headers.push_back(header);
245     for (const char* header : test.final_headers)
246       final_headers.AddHeaderFromString(header);
247     bool should_clear_upload(false);  // unused.
248 
249     RedirectUtil::UpdateHttpRequest(GURL(),         // original_url
250                                     std::string(),  // original_method
251                                     RedirectInfo(), removed_headers,
252                                     modified_headers, &initial_headers,
253                                     &should_clear_upload);
254 
255     // The initial_headers have been updated and should match the expected final
256     // headers.
257     EXPECT_EQ(initial_headers.ToString(), final_headers.ToString());
258   }
259 }
260 
261 // Test with removed_headers = std::nullopt.
TEST(RedirectUtilTest,RemovedHeadersNullOpt)262 TEST(RedirectUtilTest, RemovedHeadersNullOpt) {
263   HttpRequestHeaders initial_headers, final_headers;
264   initial_headers.SetHeader("A", "0");
265   final_headers.SetHeader("A", "0");
266   std::optional<std::vector<std::string>> removed_headers(std::nullopt);
267   std::optional<HttpRequestHeaders> modified_headers(std::in_place);
268   bool should_clear_upload(false);  // unused.
269 
270   RedirectUtil::UpdateHttpRequest(GURL(),         // original_url
271                                   std::string(),  // original_method
272                                   RedirectInfo(), removed_headers,
273                                   modified_headers, &initial_headers,
274                                   &should_clear_upload);
275 
276   // The initial_headers have been updated and should match the expected final
277   // headers.
278   EXPECT_EQ(initial_headers.ToString(), final_headers.ToString());
279 }
280 
281 // Test with modified_headers = std::nullopt.
TEST(RedirectUtilTest,ModifyHeadersNullopt)282 TEST(RedirectUtilTest, ModifyHeadersNullopt) {
283   HttpRequestHeaders initial_headers, final_headers;
284   initial_headers.SetHeader("A", "0");
285   final_headers.SetHeader("A", "0");
286   std::optional<std::vector<std::string>> removed_headers(std::in_place);
287   std::optional<HttpRequestHeaders> modified_headers(std::nullopt);
288   bool should_clear_upload(false);  // unused.
289 
290   RedirectUtil::UpdateHttpRequest(GURL(),         // original_url
291                                   std::string(),  // original_method
292                                   RedirectInfo(), removed_headers,
293                                   modified_headers, &initial_headers,
294                                   &should_clear_upload);
295 
296   // The initial_headers have been updated and should match the expected final
297   // headers.
298   EXPECT_EQ(initial_headers.ToString(), final_headers.ToString());
299 }
300 
301 }  // namespace
302 }  // namespace net
303