1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include "src/core/lib/http/parser.h"
20
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include <string>
25
26 #include "absl/status/status.h"
27 #include "absl/strings/str_format.h"
28 #include "gtest/gtest.h"
29
30 #include <grpc/support/alloc.h>
31
32 #include "src/core/lib/gpr/useful.h"
33 #include "test/core/util/slice_splitter.h"
34 #include "test/core/util/test_config.h"
35
test_request_succeeds(grpc_slice_split_mode split_mode,const char * request_text,const char * expect_method,grpc_http_version expect_version,const char * expect_path,const char * expect_body,...)36 static void test_request_succeeds(grpc_slice_split_mode split_mode,
37 const char* request_text,
38 const char* expect_method,
39 grpc_http_version expect_version,
40 const char* expect_path,
41 const char* expect_body, ...) {
42 grpc_http_parser parser;
43 grpc_slice input_slice = grpc_slice_from_copied_string(request_text);
44 size_t num_slices;
45 size_t i;
46 grpc_slice* slices;
47 va_list args;
48 grpc_http_request request;
49 memset(&request, 0, sizeof(request));
50
51 grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
52 grpc_slice_unref(input_slice);
53
54 grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
55
56 for (i = 0; i < num_slices; i++) {
57 ASSERT_EQ(grpc_http_parser_parse(&parser, slices[i], nullptr),
58 absl::OkStatus());
59 grpc_slice_unref(slices[i]);
60 }
61 ASSERT_EQ(grpc_http_parser_eof(&parser), absl::OkStatus());
62
63 ASSERT_EQ(GRPC_HTTP_REQUEST, parser.type);
64 ASSERT_STREQ(expect_method, request.method);
65 ASSERT_STREQ(expect_path, request.path);
66 ASSERT_EQ(expect_version, request.version);
67
68 if (expect_body != nullptr) {
69 ASSERT_EQ(strlen(expect_body), request.body_length);
70 ASSERT_EQ(0, memcmp(expect_body, request.body, request.body_length));
71 } else {
72 ASSERT_EQ(request.body_length, 0);
73 }
74
75 va_start(args, expect_body);
76 i = 0;
77 for (;;) {
78 char* expect_key;
79 char* expect_value;
80 expect_key = va_arg(args, char*);
81 if (!expect_key) break;
82 ASSERT_LT(i, request.hdr_count);
83 expect_value = va_arg(args, char*);
84 ASSERT_TRUE(expect_value);
85 ASSERT_STREQ(expect_key, request.hdrs[i].key);
86 ASSERT_STREQ(expect_value, request.hdrs[i].value);
87 i++;
88 }
89 va_end(args);
90 ASSERT_EQ(i, request.hdr_count);
91
92 grpc_http_request_destroy(&request);
93 grpc_http_parser_destroy(&parser);
94 gpr_free(slices);
95 }
96
test_succeeds(grpc_slice_split_mode split_mode,const char * response_text,int expect_status,const char * expect_body,...)97 static void test_succeeds(grpc_slice_split_mode split_mode,
98 const char* response_text, int expect_status,
99 const char* expect_body, ...) {
100 grpc_http_parser parser;
101 grpc_slice input_slice = grpc_slice_from_copied_string(response_text);
102 size_t num_slices;
103 size_t i;
104 grpc_slice* slices;
105 va_list args;
106 grpc_http_response response;
107 response = {};
108
109 grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
110 grpc_slice_unref(input_slice);
111
112 grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
113
114 for (i = 0; i < num_slices; i++) {
115 ASSERT_EQ(grpc_http_parser_parse(&parser, slices[i], nullptr),
116 absl::OkStatus());
117 grpc_slice_unref(slices[i]);
118 }
119 ASSERT_EQ(grpc_http_parser_eof(&parser), absl::OkStatus());
120
121 ASSERT_EQ(GRPC_HTTP_RESPONSE, parser.type);
122 ASSERT_EQ(expect_status, response.status);
123 if (expect_body != nullptr) {
124 ASSERT_EQ(strlen(expect_body), response.body_length);
125 ASSERT_EQ(0, memcmp(expect_body, response.body, response.body_length));
126 } else {
127 ASSERT_EQ(response.body_length, 0);
128 }
129
130 va_start(args, expect_body);
131 i = 0;
132 for (;;) {
133 char* expect_key;
134 char* expect_value;
135 expect_key = va_arg(args, char*);
136 if (!expect_key) break;
137 ASSERT_LT(i, response.hdr_count);
138 expect_value = va_arg(args, char*);
139 ASSERT_TRUE(expect_value);
140 ASSERT_STREQ(expect_key, response.hdrs[i].key);
141 ASSERT_STREQ(expect_value, response.hdrs[i].value);
142 i++;
143 }
144 va_end(args);
145 ASSERT_EQ(i, response.hdr_count);
146
147 grpc_http_response_destroy(&response);
148 grpc_http_parser_destroy(&parser);
149 gpr_free(slices);
150 }
151
test_fails(grpc_slice_split_mode split_mode,const char * response_text)152 static void test_fails(grpc_slice_split_mode split_mode,
153 const char* response_text) {
154 grpc_http_parser parser;
155 grpc_slice input_slice = grpc_slice_from_copied_string(response_text);
156 size_t num_slices;
157 size_t i;
158 grpc_slice* slices;
159 grpc_error_handle error;
160 grpc_http_response response;
161 response = {};
162
163 grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
164 grpc_slice_unref(input_slice);
165
166 grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
167
168 for (i = 0; i < num_slices; i++) {
169 if (absl::OkStatus() == error) {
170 error = grpc_http_parser_parse(&parser, slices[i], nullptr);
171 }
172 grpc_slice_unref(slices[i]);
173 }
174 if (absl::OkStatus() == error) {
175 error = grpc_http_parser_eof(&parser);
176 }
177 ASSERT_FALSE(error.ok());
178
179 grpc_http_response_destroy(&response);
180 grpc_http_parser_destroy(&parser);
181 gpr_free(slices);
182 }
183
test_request_fails(grpc_slice_split_mode split_mode,const char * request_text)184 static void test_request_fails(grpc_slice_split_mode split_mode,
185 const char* request_text) {
186 grpc_http_parser parser;
187 grpc_slice input_slice = grpc_slice_from_copied_string(request_text);
188 size_t num_slices;
189 size_t i;
190 grpc_slice* slices;
191 grpc_error_handle error;
192 grpc_http_request request;
193 memset(&request, 0, sizeof(request));
194
195 grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
196 grpc_slice_unref(input_slice);
197
198 grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
199
200 for (i = 0; i < num_slices; i++) {
201 if (error.ok()) {
202 error = grpc_http_parser_parse(&parser, slices[i], nullptr);
203 }
204 grpc_slice_unref(slices[i]);
205 }
206 if (error.ok()) {
207 error = grpc_http_parser_eof(&parser);
208 }
209 ASSERT_FALSE(error.ok());
210
211 grpc_http_request_destroy(&request);
212 grpc_http_parser_destroy(&parser);
213 gpr_free(slices);
214 }
215
TEST(ParserTest,MainTest)216 TEST(ParserTest, MainTest) {
217 size_t i;
218 const grpc_slice_split_mode split_modes[] = {GRPC_SLICE_SPLIT_IDENTITY,
219 GRPC_SLICE_SPLIT_ONE_BYTE};
220 for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) {
221 test_succeeds(split_modes[i],
222 "HTTP/1.0 200 OK\r\n"
223 "xyz: abc\r\n"
224 "\r\n"
225 "hello world!",
226 200, "hello world!", "xyz", "abc", NULL);
227 test_succeeds(split_modes[i],
228 "HTTP/1.0 404 Not Found\r\n"
229 "\r\n",
230 404, nullptr, NULL);
231 test_succeeds(split_modes[i],
232 "HTTP/1.1 200 OK\r\n"
233 "xyz: abc\r\n"
234 "\r\n"
235 "hello world!",
236 200, "hello world!", "xyz", "abc", NULL);
237 test_succeeds(split_modes[i],
238 "HTTP/1.1 200 OK\n"
239 "\n"
240 "abc",
241 200, "abc", NULL);
242 test_succeeds(split_modes[i],
243 "HTTP/1.1 200 OK\r\n"
244 "Transfer-Encoding: chunked\r\n"
245 "\r\n"
246 "4\r\n"
247 "This\r\n"
248 "16;param1;param2\r\n"
249 " is a chunked encoding\r\n"
250 "1D\r\n"
251 " example.\r\nNo params handled.\r\n"
252 "0\r\n"
253 "\r\n",
254 200,
255 "This is a chunked encoding example.\r\nNo params handled.",
256 "Transfer-Encoding", "chunked", NULL);
257 test_succeeds(split_modes[i],
258 "HTTP/1.1 200 OK\r\n"
259 "Transfer-Encoding: chunked\r\n"
260 "\r\n"
261 "e\r\n"
262 "HTTP Trailers \r\n"
263 "13\r\n"
264 "are also supported.\r\n"
265 "0\r\n"
266 "abc: xyz\r\n"
267 "\r\n",
268 200, "HTTP Trailers are also supported.", "Transfer-Encoding",
269 "chunked", "abc", "xyz", NULL);
270 test_request_succeeds(split_modes[i],
271 "GET / HTTP/1.0\r\n"
272 "\r\n",
273 "GET", GRPC_HTTP_HTTP10, "/", nullptr, NULL);
274 test_request_succeeds(split_modes[i],
275 "GET / HTTP/1.0\r\n"
276 "\r\n"
277 "xyz",
278 "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
279 test_request_succeeds(split_modes[i],
280 "GET / HTTP/1.1\r\n"
281 "\r\n"
282 "xyz",
283 "GET", GRPC_HTTP_HTTP11, "/", "xyz", NULL);
284 test_request_succeeds(split_modes[i],
285 "GET / HTTP/2.0\r\n"
286 "\r\n"
287 "xyz",
288 "GET", GRPC_HTTP_HTTP20, "/", "xyz", NULL);
289 test_request_succeeds(split_modes[i],
290 "GET / HTTP/1.0\r\n"
291 "xyz: abc\r\n"
292 "\r\n"
293 "xyz",
294 "GET", GRPC_HTTP_HTTP10, "/", "xyz", "xyz", "abc",
295 NULL);
296 test_request_succeeds(split_modes[i],
297 "GET / HTTP/1.0\n"
298 "\n"
299 "xyz",
300 "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
301 test_fails(split_modes[i], "HTTP/1.0\r\n");
302 test_fails(split_modes[i], "HTTP/1.2\r\n");
303 test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n");
304 test_fails(split_modes[i], "HTTP/1.0 200 OK\n");
305 test_fails(split_modes[i], "HTTP/1.0 200 OK\r\n");
306 test_fails(split_modes[i], "HTTP/1.0 200 OK\r\nFoo x\r\n");
307 test_fails(split_modes[i],
308 "HTTP/1.0 200 OK\r\n"
309 "xyz: abc\r\n"
310 " def\r\n"
311 "\r\n"
312 "hello world!");
313 test_request_fails(split_modes[i], "GET\r\n");
314 test_request_fails(split_modes[i], "GET /\r\n");
315 test_request_fails(split_modes[i], "GET / HTTP/0.0\r\n");
316 test_request_fails(split_modes[i], "GET / ____/1.0\r\n");
317 test_request_fails(split_modes[i], "GET / HTTP/1.2\r\n");
318 test_request_fails(split_modes[i], "GET / HTTP/1.0\n");
319
320 char* tmp1 =
321 static_cast<char*>(gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH));
322 memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1);
323 tmp1[2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1] = 0;
324 std::string tmp2 =
325 absl::StrFormat("HTTP/1.0 200 OK\r\nxyz: %s\r\n\r\n", tmp1);
326 gpr_free(tmp1);
327 test_fails(split_modes[i], tmp2.c_str());
328 }
329 }
330
main(int argc,char ** argv)331 int main(int argc, char** argv) {
332 grpc::testing::TestEnvironment env(&argc, argv);
333 ::testing::InitGoogleTest(&argc, argv);
334 grpc::testing::TestGrpcScope grpc_scope;
335 return RUN_ALL_TESTS();
336 }
337