xref: /aosp_15_r20/external/cronet/net/test/embedded_test_server/http_request_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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/test/embedded_test_server/http_request.h"
6 
7 #include <memory>
8 
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 namespace net::test_server {
12 
TEST(HttpRequestTest,ParseRequest)13 TEST(HttpRequestTest, ParseRequest) {
14   HttpRequestParser parser;
15 
16   // Process request in chunks to check if the parser deals with border cases.
17   // Also, check multi-line headers as well as multiple requests in the same
18   // chunk. This basically should cover all the simplest border cases.
19   parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
20   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
21   parser.ProcessChunk("Host: localhost:1234\r\n");
22   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
23   parser.ProcessChunk("Multi-line-header: abcd\r\n");
24   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
25   parser.ProcessChunk(" efgh\r\n");
26   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
27   parser.ProcessChunk(" ijkl\r\n");
28   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
29   parser.ProcessChunk("Content-Length: 10\r\n\r\n");
30   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
31   // Content data and another request in the same chunk (possible in http/1.1).
32   parser.ProcessChunk("1234567890GET /another.html HTTP/1.1\r\n\r\n");
33   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
34 
35   // Fetch the first request and validate it.
36   {
37     std::unique_ptr<HttpRequest> request = parser.GetRequest();
38     EXPECT_EQ("/foobar.html", request->relative_url);
39     EXPECT_EQ("POST", request->method_string);
40     EXPECT_EQ(METHOD_POST, request->method);
41     EXPECT_EQ("1234567890", request->content);
42     ASSERT_EQ(3u, request->headers.size());
43 
44     EXPECT_EQ(1u, request->headers.count("Host"));
45     EXPECT_EQ(1u, request->headers.count("Multi-line-header"));
46     EXPECT_EQ(1u, request->headers.count("Content-Length"));
47 
48     const char kExpectedAllHeaders[] =
49         "POST /foobar.html HTTP/1.1\r\n"
50         "Host: localhost:1234\r\n"
51         "Multi-line-header: abcd\r\n"
52         " efgh\r\n"
53         " ijkl\r\n"
54         "Content-Length: 10\r\n";
55     EXPECT_EQ(kExpectedAllHeaders, request->all_headers);
56     EXPECT_EQ("localhost:1234", request->headers["Host"]);
57     EXPECT_EQ("abcd efgh ijkl", request->headers["Multi-line-header"]);
58     EXPECT_EQ("10", request->headers["Content-Length"]);
59   }
60 
61   // No other request available yet since we do not support multiple requests
62   // per connection.
63   EXPECT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
64 }
65 
TEST(HttpRequestTest,ParseRequestWithEmptyBody)66 TEST(HttpRequestTest, ParseRequestWithEmptyBody) {
67   HttpRequestParser parser;
68 
69   parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
70   parser.ProcessChunk("Content-Length: 0\r\n\r\n");
71   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
72 
73   std::unique_ptr<HttpRequest> request = parser.GetRequest();
74   EXPECT_EQ("", request->content);
75   EXPECT_TRUE(request->has_content);
76   EXPECT_EQ(1u, request->headers.count("Content-Length"));
77   EXPECT_EQ("0", request->headers["Content-Length"]);
78 }
79 
TEST(HttpRequestTest,ParseRequestWithChunkedBody)80 TEST(HttpRequestTest, ParseRequestWithChunkedBody) {
81   HttpRequestParser parser;
82 
83   parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
84   parser.ProcessChunk("Transfer-Encoding: chunked\r\n\r\n");
85   parser.ProcessChunk("5\r\nhello\r\n");
86   parser.ProcessChunk("1\r\n \r\n");
87   parser.ProcessChunk("5\r\nworld\r\n");
88   parser.ProcessChunk("0\r\n\r\n");
89   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
90 
91   std::unique_ptr<HttpRequest> request = parser.GetRequest();
92   EXPECT_EQ("hello world", request->content);
93   EXPECT_TRUE(request->has_content);
94   EXPECT_EQ(1u, request->headers.count("Transfer-Encoding"));
95   EXPECT_EQ("chunked", request->headers["Transfer-Encoding"]);
96 }
97 
TEST(HttpRequestTest,ParseRequestWithChunkedBodySlow)98 TEST(HttpRequestTest, ParseRequestWithChunkedBodySlow) {
99   HttpRequestParser parser;
100 
101   parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
102   parser.ProcessChunk("Transfer-Encoding: chunked\r\n\r\n");
103   std::string chunked_body = "5\r\nhello\r\n0\r\n\r\n";
104 
105   // Send one character at a time, and make the parser parse the request.
106   for (size_t i = 0; i < chunked_body.size(); i++) {
107     parser.ProcessChunk(chunked_body.substr(i, 1));
108     // Except for the last pass, ParseRequest() should give WAITING.
109     if (i != chunked_body.size() - 1) {
110       ASSERT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
111     }
112   }
113   // All chunked data has been sent, the last ParseRequest should give ACCEPTED.
114   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
115   std::unique_ptr<HttpRequest> request = parser.GetRequest();
116   EXPECT_EQ("hello", request->content);
117   EXPECT_TRUE(request->has_content);
118   EXPECT_EQ(1u, request->headers.count("Transfer-Encoding"));
119   EXPECT_EQ("chunked", request->headers["Transfer-Encoding"]);
120 }
121 
TEST(HttpRequestTest,ParseRequestWithoutBody)122 TEST(HttpRequestTest, ParseRequestWithoutBody) {
123   HttpRequestParser parser;
124 
125   parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n\r\n");
126   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
127 
128   std::unique_ptr<HttpRequest> request = parser.GetRequest();
129   EXPECT_EQ("", request->content);
130   EXPECT_FALSE(request->has_content);
131 }
132 
TEST(HttpRequestTest,ParseGet)133 TEST(HttpRequestTest, ParseGet) {
134   HttpRequestParser parser;
135 
136   parser.ProcessChunk("GET /foobar.html HTTP/1.1\r\n\r\n");
137   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
138 
139   std::unique_ptr<HttpRequest> request = parser.GetRequest();
140   EXPECT_EQ("/foobar.html", request->relative_url);
141   EXPECT_EQ("GET", request->method_string);
142   EXPECT_EQ(METHOD_GET, request->method);
143   EXPECT_EQ("", request->content);
144   EXPECT_FALSE(request->has_content);
145 }
146 
TEST(HttpRequestTest,ParseConnect)147 TEST(HttpRequestTest, ParseConnect) {
148   HttpRequestParser parser;
149 
150   parser.ProcessChunk("CONNECT example.com:443 HTTP/1.1\r\n\r\n");
151   ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
152 
153   std::unique_ptr<HttpRequest> request = parser.GetRequest();
154   EXPECT_EQ("example.com:443", request->relative_url);
155   EXPECT_EQ("CONNECT", request->method_string);
156   EXPECT_EQ(METHOD_CONNECT, request->method);
157   EXPECT_EQ("", request->content);
158   EXPECT_FALSE(request->has_content);
159 }
160 
TEST(HttpRequestTest,GetURL)161 TEST(HttpRequestTest, GetURL) {
162   HttpRequest request;
163   request.relative_url = "/foobar.html?q=foo";
164   request.base_url = GURL("https://127.0.0.1:8080");
165   EXPECT_EQ("https://127.0.0.1:8080/foobar.html?q=foo",
166             request.GetURL().spec());
167 }
168 
TEST(HttpRequestTest,GetURLFallback)169 TEST(HttpRequestTest, GetURLFallback) {
170   HttpRequest request;
171   request.relative_url = "/foobar.html?q=foo";
172   EXPECT_EQ("http://localhost/foobar.html?q=foo", request.GetURL().spec());
173 }
174 
175 }  // namespace net::test_server
176