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/strings/str_format.h"
27
28 #include <grpc/grpc.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.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 GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], nullptr) ==
58 GRPC_ERROR_NONE);
59 grpc_slice_unref(slices[i]);
60 }
61 GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE);
62
63 GPR_ASSERT(GRPC_HTTP_REQUEST == parser.type);
64 GPR_ASSERT(0 == strcmp(expect_method, request.method));
65 GPR_ASSERT(0 == strcmp(expect_path, request.path));
66 GPR_ASSERT(expect_version == request.version);
67
68 if (expect_body != nullptr) {
69 GPR_ASSERT(strlen(expect_body) == request.body_length);
70 GPR_ASSERT(0 == memcmp(expect_body, request.body, request.body_length));
71 } else {
72 GPR_ASSERT(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 GPR_ASSERT(i < request.hdr_count);
83 expect_value = va_arg(args, char*);
84 GPR_ASSERT(expect_value);
85 GPR_ASSERT(0 == strcmp(expect_key, request.hdrs[i].key));
86 GPR_ASSERT(0 == strcmp(expect_value, request.hdrs[i].value));
87 i++;
88 }
89 va_end(args);
90 GPR_ASSERT(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 GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], nullptr) ==
116 GRPC_ERROR_NONE);
117 grpc_slice_unref(slices[i]);
118 }
119 GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE);
120
121 GPR_ASSERT(GRPC_HTTP_RESPONSE == parser.type);
122 GPR_ASSERT(expect_status == response.status);
123 if (expect_body != nullptr) {
124 GPR_ASSERT(strlen(expect_body) == response.body_length);
125 GPR_ASSERT(0 == memcmp(expect_body, response.body, response.body_length));
126 } else {
127 GPR_ASSERT(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 GPR_ASSERT(i < response.hdr_count);
138 expect_value = va_arg(args, char*);
139 GPR_ASSERT(expect_value);
140 GPR_ASSERT(0 == strcmp(expect_key, response.hdrs[i].key));
141 GPR_ASSERT(0 == strcmp(expect_value, response.hdrs[i].value));
142 i++;
143 }
144 va_end(args);
145 GPR_ASSERT(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* error = GRPC_ERROR_NONE;
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 (GRPC_ERROR_NONE == error) {
170 error = grpc_http_parser_parse(&parser, slices[i], nullptr);
171 }
172 grpc_slice_unref(slices[i]);
173 }
174 if (GRPC_ERROR_NONE == error) {
175 error = grpc_http_parser_eof(&parser);
176 }
177 GPR_ASSERT(error != GRPC_ERROR_NONE);
178 GRPC_ERROR_UNREF(error);
179
180 grpc_http_response_destroy(&response);
181 grpc_http_parser_destroy(&parser);
182 gpr_free(slices);
183 }
184
test_request_fails(grpc_slice_split_mode split_mode,const char * request_text)185 static void test_request_fails(grpc_slice_split_mode split_mode,
186 const char* request_text) {
187 grpc_http_parser parser;
188 grpc_slice input_slice = grpc_slice_from_copied_string(request_text);
189 size_t num_slices;
190 size_t i;
191 grpc_slice* slices;
192 grpc_error* error = GRPC_ERROR_NONE;
193 grpc_http_request request;
194 memset(&request, 0, sizeof(request));
195
196 grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices);
197 grpc_slice_unref(input_slice);
198
199 grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request);
200
201 for (i = 0; i < num_slices; i++) {
202 if (error == GRPC_ERROR_NONE) {
203 error = grpc_http_parser_parse(&parser, slices[i], nullptr);
204 }
205 grpc_slice_unref(slices[i]);
206 }
207 if (error == GRPC_ERROR_NONE) {
208 error = grpc_http_parser_eof(&parser);
209 }
210 GPR_ASSERT(error != GRPC_ERROR_NONE);
211 GRPC_ERROR_UNREF(error);
212
213 grpc_http_request_destroy(&request);
214 grpc_http_parser_destroy(&parser);
215 gpr_free(slices);
216 }
217
main(int argc,char ** argv)218 int main(int argc, char** argv) {
219 size_t i;
220 const grpc_slice_split_mode split_modes[] = {GRPC_SLICE_SPLIT_IDENTITY,
221 GRPC_SLICE_SPLIT_ONE_BYTE};
222
223 grpc::testing::TestEnvironment env(argc, argv);
224 grpc_init();
225
226 for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) {
227 test_succeeds(split_modes[i],
228 "HTTP/1.0 200 OK\r\n"
229 "xyz: abc\r\n"
230 "\r\n"
231 "hello world!",
232 200, "hello world!", "xyz", "abc", NULL);
233 test_succeeds(split_modes[i],
234 "HTTP/1.0 404 Not Found\r\n"
235 "\r\n",
236 404, nullptr, NULL);
237 test_succeeds(split_modes[i],
238 "HTTP/1.1 200 OK\r\n"
239 "xyz: abc\r\n"
240 "\r\n"
241 "hello world!",
242 200, "hello world!", "xyz", "abc", NULL);
243 test_succeeds(split_modes[i],
244 "HTTP/1.1 200 OK\n"
245 "\n"
246 "abc",
247 200, "abc", NULL);
248 test_request_succeeds(split_modes[i],
249 "GET / HTTP/1.0\r\n"
250 "\r\n",
251 "GET", GRPC_HTTP_HTTP10, "/", nullptr, NULL);
252 test_request_succeeds(split_modes[i],
253 "GET / HTTP/1.0\r\n"
254 "\r\n"
255 "xyz",
256 "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
257 test_request_succeeds(split_modes[i],
258 "GET / HTTP/1.1\r\n"
259 "\r\n"
260 "xyz",
261 "GET", GRPC_HTTP_HTTP11, "/", "xyz", NULL);
262 test_request_succeeds(split_modes[i],
263 "GET / HTTP/2.0\r\n"
264 "\r\n"
265 "xyz",
266 "GET", GRPC_HTTP_HTTP20, "/", "xyz", NULL);
267 test_request_succeeds(split_modes[i],
268 "GET / HTTP/1.0\r\n"
269 "xyz: abc\r\n"
270 "\r\n"
271 "xyz",
272 "GET", GRPC_HTTP_HTTP10, "/", "xyz", "xyz", "abc",
273 NULL);
274 test_request_succeeds(split_modes[i],
275 "GET / HTTP/1.0\n"
276 "\n"
277 "xyz",
278 "GET", GRPC_HTTP_HTTP10, "/", "xyz", NULL);
279 test_fails(split_modes[i], "HTTP/1.0\r\n");
280 test_fails(split_modes[i], "HTTP/1.2\r\n");
281 test_fails(split_modes[i], "HTTP/1.0 000 XYX\r\n");
282 test_fails(split_modes[i], "HTTP/1.0 200 OK\n");
283 test_fails(split_modes[i], "HTTP/1.0 200 OK\r\n");
284 test_fails(split_modes[i], "HTTP/1.0 200 OK\r\nFoo x\r\n");
285 test_fails(split_modes[i],
286 "HTTP/1.0 200 OK\r\n"
287 "xyz: abc\r\n"
288 " def\r\n"
289 "\r\n"
290 "hello world!");
291 test_request_fails(split_modes[i], "GET\r\n");
292 test_request_fails(split_modes[i], "GET /\r\n");
293 test_request_fails(split_modes[i], "GET / HTTP/0.0\r\n");
294 test_request_fails(split_modes[i], "GET / ____/1.0\r\n");
295 test_request_fails(split_modes[i], "GET / HTTP/1.2\r\n");
296 test_request_fails(split_modes[i], "GET / HTTP/1.0\n");
297
298 char* tmp1 =
299 static_cast<char*>(gpr_malloc(2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH));
300 memset(tmp1, 'a', 2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1);
301 tmp1[2 * GRPC_HTTP_PARSER_MAX_HEADER_LENGTH - 1] = 0;
302 std::string tmp2 =
303 absl::StrFormat("HTTP/1.0 200 OK\r\nxyz: %s\r\n\r\n", tmp1);
304 gpr_free(tmp1);
305 test_fails(split_modes[i], tmp2.c_str());
306 }
307
308 grpc_shutdown();
309 return 0;
310 }
311