1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include <aws/http/private/h1_encoder.h>
7 
8 #include <aws/common/array_list.h>
9 #include <aws/io/logging.h>
10 #include <aws/testing/aws_test_harness.h>
11 
12 #include <aws/io/stream.h>
13 #include <ctype.h>
14 #include <stdio.h>
15 
16 #define H1_ENCODER_TEST_CASE(NAME)                                                                                     \
17     AWS_TEST_CASE(NAME, s_test_##NAME);                                                                                \
18     static int s_test_##NAME(struct aws_allocator *allocator, void *ctx)
19 
20 static const struct aws_http_header s_typical_request_headers[] = {
21     {
22         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
23         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("amazon.com"),
24     },
25 };
26 
27 static struct aws_logger s_logger;
28 
s_test_init(struct aws_allocator * allocator)29 static void s_test_init(struct aws_allocator *allocator) {
30     aws_http_library_init(allocator);
31 
32     struct aws_logger_standard_options logger_options = {
33         .level = AWS_LOG_LEVEL_TRACE,
34         .file = stderr,
35     };
36 
37     aws_logger_init_standard(&s_logger, allocator, &logger_options);
38     aws_logger_set(&s_logger);
39 }
40 
s_test_clean_up(void)41 static void s_test_clean_up(void) {
42     aws_http_library_clean_up();
43     aws_logger_clean_up(&s_logger);
44 }
45 
H1_ENCODER_TEST_CASE(h1_encoder_content_length_put_request_headers)46 H1_ENCODER_TEST_CASE(h1_encoder_content_length_put_request_headers) {
47     (void)ctx;
48     s_test_init(allocator);
49     struct aws_h1_encoder encoder;
50     aws_h1_encoder_init(&encoder, allocator);
51 
52     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
53     static const struct aws_byte_cursor body = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("write more tests");
54     struct aws_input_stream *body_stream = aws_input_stream_new_from_cursor(allocator, &body);
55 
56     struct aws_http_header headers[] = {
57         {
58             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Length"),
59             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("16"),
60         },
61     };
62 
63     struct aws_http_message *request = aws_http_message_new_request(allocator);
64     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
65     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
66     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
67     aws_http_message_set_body_stream(request, body_stream);
68 
69     struct aws_linked_list chunk_list;
70     aws_linked_list_init(&chunk_list);
71 
72     struct aws_h1_encoder_message encoder_message;
73     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
74 
75     ASSERT_FALSE(encoder_message.has_chunked_encoding_header);
76     ASSERT_FALSE(encoder_message.has_connection_close_header);
77     ASSERT_UINT_EQUALS(body.len, encoder_message.content_length);
78 
79     aws_input_stream_destroy(body_stream);
80     aws_http_message_destroy(request);
81     aws_h1_encoder_message_clean_up(&encoder_message);
82     aws_h1_encoder_clean_up(&encoder);
83     s_test_clean_up();
84     return AWS_OP_SUCCESS;
85 }
86 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_headers)87 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_headers) {
88     (void)ctx;
89     s_test_init(allocator);
90     struct aws_h1_encoder encoder;
91     aws_h1_encoder_init(&encoder, allocator);
92 
93     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
94 
95     struct aws_http_header headers[] = {
96         {
97             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
98             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
99         },
100     };
101 
102     struct aws_http_message *request = aws_http_message_new_request(allocator);
103     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
104     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
105     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
106 
107     struct aws_linked_list chunk_list;
108     aws_linked_list_init(&chunk_list);
109 
110     struct aws_h1_encoder_message encoder_message;
111     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
112 
113     ASSERT_TRUE(encoder_message.has_chunked_encoding_header);
114     ASSERT_FALSE(encoder_message.has_connection_close_header);
115     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
116 
117     aws_http_message_destroy(request);
118     aws_h1_encoder_message_clean_up(&encoder_message);
119     aws_h1_encoder_clean_up(&encoder);
120     s_test_clean_up();
121     return AWS_OP_SUCCESS;
122 }
123 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_multiple_te_headers)124 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_multiple_te_headers) {
125     (void)ctx;
126     s_test_init(allocator);
127     struct aws_h1_encoder encoder;
128     aws_h1_encoder_init(&encoder, allocator);
129 
130     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
131 
132     struct aws_http_header headers[] = {
133         {
134             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
135             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("gzip"),
136         },
137         {
138             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
139             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
140         },
141     };
142 
143     struct aws_http_message *request = aws_http_message_new_request(allocator);
144     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
145     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
146     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
147 
148     struct aws_linked_list chunk_list;
149     aws_linked_list_init(&chunk_list);
150 
151     struct aws_h1_encoder_message encoder_message;
152     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
153 
154     ASSERT_TRUE(encoder_message.has_chunked_encoding_header);
155     ASSERT_FALSE(encoder_message.has_connection_close_header);
156     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
157 
158     aws_http_message_destroy(request);
159     aws_h1_encoder_message_clean_up(&encoder_message);
160     aws_h1_encoder_clean_up(&encoder);
161     s_test_clean_up();
162     return AWS_OP_SUCCESS;
163 }
164 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_headers_case_insensitivity)165 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_put_request_headers_case_insensitivity) {
166     (void)ctx;
167     s_test_init(allocator);
168     struct aws_h1_encoder encoder;
169     aws_h1_encoder_init(&encoder, allocator);
170 
171     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
172 
173     struct aws_http_header headers[] = {
174         {
175             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("traNsfeR-EncODIng"),
176             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
177         },
178     };
179 
180     struct aws_http_message *request = aws_http_message_new_request(allocator);
181     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
182     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
183     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
184 
185     struct aws_linked_list chunk_list;
186     aws_linked_list_init(&chunk_list);
187 
188     struct aws_h1_encoder_message encoder_message;
189     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
190 
191     ASSERT_TRUE(encoder_message.has_chunked_encoding_header);
192     ASSERT_FALSE(encoder_message.has_connection_close_header);
193     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
194 
195     aws_http_message_destroy(request);
196     aws_h1_encoder_message_clean_up(&encoder_message);
197     aws_h1_encoder_clean_up(&encoder);
198     s_test_clean_up();
199     return AWS_OP_SUCCESS;
200 }
201 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_not_chunked_put_request_headers)202 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_not_chunked_put_request_headers) {
203     (void)ctx;
204     s_test_init(allocator);
205     struct aws_h1_encoder encoder;
206     aws_h1_encoder_init(&encoder, allocator);
207 
208     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
209     static const struct aws_byte_cursor body = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("write more tests");
210     struct aws_input_stream *body_stream = aws_input_stream_new_from_cursor(allocator, &body);
211 
212     struct aws_http_header headers[] = {
213         {
214             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
215             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("gzip"),
216         },
217     };
218 
219     struct aws_http_message *request = aws_http_message_new_request(allocator);
220     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
221     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
222     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
223     aws_http_message_set_body_stream(request, body_stream);
224 
225     struct aws_linked_list chunk_list;
226     aws_linked_list_init(&chunk_list);
227 
228     struct aws_h1_encoder_message encoder_message;
229     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
230 
231     ASSERT_FALSE(encoder_message.has_chunked_encoding_header);
232     ASSERT_FALSE(encoder_message.has_connection_close_header);
233     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
234 
235     aws_input_stream_destroy(body_stream);
236     aws_http_message_destroy(request);
237     aws_h1_encoder_message_clean_up(&encoder_message);
238     aws_h1_encoder_clean_up(&encoder);
239     s_test_clean_up();
240     return AWS_OP_SUCCESS;
241 }
242 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_set_body_stream_errors)243 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_set_body_stream_errors) {
244     (void)ctx;
245     s_test_init(allocator);
246     struct aws_h1_encoder encoder;
247     aws_h1_encoder_init(&encoder, allocator);
248 
249     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
250     static const struct aws_byte_cursor body = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("write more tests");
251     struct aws_input_stream *body_stream = aws_input_stream_new_from_cursor(allocator, &body);
252 
253     struct aws_http_header headers[] = {
254         {
255             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
256             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
257         },
258     };
259 
260     struct aws_http_message *request = aws_http_message_new_request(allocator);
261     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
262     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
263     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
264     /* Setting the body stream should cause an error */
265     aws_http_message_set_body_stream(request, body_stream);
266 
267     struct aws_linked_list chunk_list;
268     aws_linked_list_init(&chunk_list);
269 
270     struct aws_h1_encoder_message encoder_message;
271     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
272 
273     ASSERT_FALSE(encoder_message.has_chunked_encoding_header);
274     ASSERT_FALSE(encoder_message.has_connection_close_header);
275     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
276 
277     aws_input_stream_destroy(body_stream);
278     aws_http_message_destroy(request);
279     aws_h1_encoder_message_clean_up(&encoder_message);
280     aws_h1_encoder_clean_up(&encoder);
281     s_test_clean_up();
282     return AWS_OP_SUCCESS;
283 }
284 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_not_ending_in_chunked_put_request_headers)285 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_not_ending_in_chunked_put_request_headers) {
286     (void)ctx;
287     s_test_init(allocator);
288     struct aws_h1_encoder encoder;
289     aws_h1_encoder_init(&encoder, allocator);
290 
291     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
292 
293     struct aws_http_header headers[] = {
294         {
295             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
296             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
297         },
298         {
299             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
300             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("gzip"),
301         },
302     };
303 
304     struct aws_http_message *request = aws_http_message_new_request(allocator);
305     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
306     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
307     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
308 
309     struct aws_linked_list chunk_list;
310     aws_linked_list_init(&chunk_list);
311 
312     struct aws_h1_encoder_message encoder_message;
313     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
314 
315     ASSERT_FALSE(encoder_message.has_chunked_encoding_header);
316     ASSERT_FALSE(encoder_message.has_connection_close_header);
317     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
318 
319     aws_http_message_destroy(request);
320     aws_h1_encoder_message_clean_up(&encoder_message);
321     aws_h1_encoder_clean_up(&encoder);
322     s_test_clean_up();
323     return AWS_OP_SUCCESS;
324 }
325 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_multiple_put_request_headers)326 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_multiple_put_request_headers) {
327     (void)ctx;
328     s_test_init(allocator);
329     struct aws_h1_encoder encoder;
330     aws_h1_encoder_init(&encoder, allocator);
331 
332     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
333 
334     struct aws_http_header headers[] = {
335         {
336             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
337             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("gzip, chunked"),
338         },
339     };
340 
341     struct aws_http_message *request = aws_http_message_new_request(allocator);
342     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
343     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
344     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
345 
346     struct aws_linked_list chunk_list;
347     aws_linked_list_init(&chunk_list);
348 
349     struct aws_h1_encoder_message encoder_message;
350     aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list);
351 
352     ASSERT_TRUE(encoder_message.has_chunked_encoding_header);
353     ASSERT_FALSE(encoder_message.has_connection_close_header);
354     ASSERT_UINT_EQUALS(0, encoder_message.content_length);
355 
356     aws_http_message_destroy(request);
357     aws_h1_encoder_message_clean_up(&encoder_message);
358     aws_h1_encoder_clean_up(&encoder);
359     s_test_clean_up();
360     return AWS_OP_SUCCESS;
361 }
362 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_and_content_length_put_request_headers)363 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_and_content_length_put_request_headers) {
364     (void)ctx;
365     s_test_init(allocator);
366     struct aws_h1_encoder encoder;
367     aws_h1_encoder_init(&encoder, allocator);
368 
369     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
370     static const struct aws_byte_cursor body = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("write more tests");
371     struct aws_input_stream *body_stream = aws_input_stream_new_from_cursor(allocator, &body);
372 
373     struct aws_http_header headers[] = {
374         {
375             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
376             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked"),
377         },
378         {
379             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Length"),
380             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("16"),
381         },
382     };
383 
384     struct aws_http_message *request = aws_http_message_new_request(allocator);
385     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
386     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
387     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
388 
389     struct aws_linked_list chunk_list;
390     aws_linked_list_init(&chunk_list);
391 
392     struct aws_h1_encoder_message encoder_message;
393 
394     /* Per RFC 2656 (https://tools.ietf.org/html/rfc2616#section-4.4), if both the Content-Length and Transfer-Encoding
395      * header are defined, the client should not send the request. */
396     ASSERT_INT_EQUALS(
397         AWS_OP_ERR, aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list));
398 
399     aws_input_stream_destroy(body_stream);
400     aws_http_message_destroy(request);
401     aws_h1_encoder_message_clean_up(&encoder_message);
402     aws_h1_encoder_clean_up(&encoder);
403     s_test_clean_up();
404     return AWS_OP_SUCCESS;
405 }
406 
H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_not_final_encoding_put_request_headers)407 H1_ENCODER_TEST_CASE(h1_encoder_transfer_encoding_chunked_not_final_encoding_put_request_headers) {
408     (void)ctx;
409     s_test_init(allocator);
410     struct aws_h1_encoder encoder;
411     aws_h1_encoder_init(&encoder, allocator);
412 
413     /* request to send - we won't actually send it, we want to validate headers are set correctly. */
414 
415     struct aws_http_header headers[] = {
416         {
417             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Transfer-Encoding"),
418             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("chunked;gzip"), /* must end with chunked */
419         },
420     };
421 
422     struct aws_http_message *request = aws_http_message_new_request(allocator);
423     ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("PUT")));
424     ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
425     aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers));
426 
427     struct aws_linked_list chunk_list;
428     aws_linked_list_init(&chunk_list);
429 
430     struct aws_h1_encoder_message encoder_message;
431 
432     /* Per RFC 2656 (https://tools.ietf.org/html/rfc2616#section-4.4), if both the Content-Length and Transfer-Encoding
433      * header are defined, the client should not send the request. */
434     ASSERT_INT_EQUALS(
435         AWS_OP_ERR, aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list));
436 
437     aws_http_message_destroy(request);
438     aws_h1_encoder_message_clean_up(&encoder_message);
439     aws_h1_encoder_clean_up(&encoder);
440     s_test_clean_up();
441     return AWS_OP_SUCCESS;
442 }
443 
s_test_bad_request(struct aws_allocator * allocator,const char * method,const char * path,const struct aws_http_header * header_array,size_t header_count,int expected_error)444 static int s_test_bad_request(
445     struct aws_allocator *allocator,
446     const char *method,
447     const char *path,
448     const struct aws_http_header *header_array,
449     size_t header_count,
450     int expected_error) {
451 
452     s_test_init(allocator);
453 
454     struct aws_http_message *request = aws_http_message_new_request(allocator);
455     ASSERT_NOT_NULL(request);
456     if (method) {
457         ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str(method)));
458     }
459     if (path) {
460         ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str(path)));
461     }
462     if (header_array) {
463         ASSERT_SUCCESS(aws_http_message_add_header_array(request, header_array, header_count));
464     }
465 
466     struct aws_linked_list chunk_list;
467     aws_linked_list_init(&chunk_list);
468 
469     struct aws_h1_encoder_message encoder_message;
470 
471     ASSERT_ERROR(
472         expected_error, aws_h1_encoder_message_init_from_request(&encoder_message, allocator, request, &chunk_list));
473 
474     aws_http_message_destroy(request);
475     aws_h1_encoder_message_clean_up(&encoder_message);
476     s_test_clean_up();
477     return AWS_OP_SUCCESS;
478 }
479 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_method)480 H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_method) {
481     (void)ctx;
482     return s_test_bad_request(
483         allocator,
484         "G@T" /*method*/,
485         "/" /*path*/,
486         s_typical_request_headers /*header_array*/,
487         AWS_ARRAY_SIZE(s_typical_request_headers) /*header_count*/,
488         AWS_ERROR_HTTP_INVALID_METHOD /*expected_error*/);
489 }
490 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_missing_method)491 H1_ENCODER_TEST_CASE(h1_encoder_rejects_missing_method) {
492     (void)ctx;
493     return s_test_bad_request(
494         allocator,
495         NULL /*method*/,
496         "/" /*path*/,
497         s_typical_request_headers /*header_array*/,
498         AWS_ARRAY_SIZE(s_typical_request_headers) /*header_count*/,
499         AWS_ERROR_HTTP_INVALID_METHOD /*expected_error*/);
500 }
501 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_path)502 H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_path) {
503     (void)ctx;
504     return s_test_bad_request(
505         allocator,
506         "GET" /*method*/,
507         "/\r\n/index.html" /*path*/,
508         s_typical_request_headers /*header_array*/,
509         AWS_ARRAY_SIZE(s_typical_request_headers) /*header_count*/,
510         AWS_ERROR_HTTP_INVALID_PATH /*expected_error*/);
511 }
512 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_missing_path)513 H1_ENCODER_TEST_CASE(h1_encoder_rejects_missing_path) {
514     (void)ctx;
515     return s_test_bad_request(
516         allocator,
517         "GET" /*method*/,
518         NULL /*path*/,
519         s_typical_request_headers /*header_array*/,
520         AWS_ARRAY_SIZE(s_typical_request_headers) /*header_count*/,
521         AWS_ERROR_HTTP_INVALID_PATH /*expected_error*/);
522 }
523 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_header_name)524 H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_header_name) {
525     (void)ctx;
526     const struct aws_http_header headers[] = {
527         {
528             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
529             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("amazon.com"),
530         },
531         {
532             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Line-\r\n-Folds"),
533             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("bad header name"),
534         },
535     };
536 
537     return s_test_bad_request(
538         allocator,
539         "GET" /*method*/,
540         "/" /*path*/,
541         headers /*header_array*/,
542         AWS_ARRAY_SIZE(headers) /*header_count*/,
543         AWS_ERROR_HTTP_INVALID_HEADER_NAME /*expected_error*/);
544 }
545 
H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_header_value)546 H1_ENCODER_TEST_CASE(h1_encoder_rejects_bad_header_value) {
547     (void)ctx;
548     const struct aws_http_header headers[] = {
549         {
550             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
551             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("amazon.com"),
552         },
553         {
554             .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("X-Line-Folds-Are-Bad-Mkay"),
555             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("item1,\r\n item2"),
556         },
557     };
558 
559     return s_test_bad_request(
560         allocator,
561         "GET" /*method*/,
562         "/" /*path*/,
563         headers /*header_array*/,
564         AWS_ARRAY_SIZE(headers) /*header_count*/,
565         AWS_ERROR_HTTP_INVALID_HEADER_VALUE /*expected_error*/);
566 }
567