@@ -2260,30 +2260,33 @@ static struct aws_input_stream_vtable s_slow_stream_vtable = {
2260
2260
.get_length = s_slow_stream_get_length ,
2261
2261
};
2262
2262
2263
+ static void s_slow_body_sender_init (struct slow_body_sender * body_sender ) {
2264
+ /* set up request whose body won't send immediately */
2265
+ struct aws_input_stream empty_stream_base ;
2266
+ AWS_ZERO_STRUCT (empty_stream_base );
2267
+ body_sender -> base = empty_stream_base ;
2268
+ body_sender -> status .is_end_of_stream = false;
2269
+ body_sender -> status .is_valid = true;
2270
+ struct aws_byte_cursor body = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("write more tests" );
2271
+ body_sender -> cursor = body ;
2272
+ body_sender -> delay_ticks = 5 ;
2273
+ body_sender -> bytes_per_tick = 1 ;
2274
+
2275
+ body_sender -> base .vtable = & s_slow_stream_vtable ;
2276
+ aws_ref_count_init (
2277
+ & body_sender -> base .ref_count , & body_sender , (aws_simple_completion_callback * )s_slow_stream_destroy );
2278
+ }
2279
+
2263
2280
/* It should be fine to receive a response before the request has finished sending */
2264
2281
H1_CLIENT_TEST_CASE (h1_client_response_arrives_before_request_done_sending_is_ok ) {
2265
2282
(void )ctx ;
2266
2283
struct tester tester ;
2267
2284
ASSERT_SUCCESS (s_tester_init (& tester , allocator ));
2268
2285
2269
2286
/* set up request whose body won't send immediately */
2270
- struct aws_input_stream empty_stream_base ;
2271
- AWS_ZERO_STRUCT (empty_stream_base );
2272
- struct slow_body_sender body_sender = {
2273
- .base = empty_stream_base ,
2274
- .status =
2275
- {
2276
- .is_end_of_stream = false,
2277
- .is_valid = true,
2278
- },
2279
- .cursor = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("write more tests" ),
2280
- .delay_ticks = 5 ,
2281
- .bytes_per_tick = 1 ,
2282
- };
2283
- body_sender .base .vtable = & s_slow_stream_vtable ;
2284
- aws_ref_count_init (
2285
- & body_sender .base .ref_count , & body_sender , (aws_simple_completion_callback * )s_slow_stream_destroy );
2286
-
2287
+ struct slow_body_sender body_sender ;
2288
+ AWS_ZERO_STRUCT (body_sender );
2289
+ s_slow_body_sender_init (& body_sender );
2287
2290
struct aws_input_stream * body_stream = & body_sender .base ;
2288
2291
2289
2292
struct aws_http_header headers [] = {
@@ -4156,3 +4159,127 @@ H1_CLIENT_TEST_CASE(h1_client_switching_protocols_requires_downstream_handler) {
4156
4159
ASSERT_SUCCESS (s_tester_clean_up (& tester ));
4157
4160
return AWS_OP_SUCCESS ;
4158
4161
}
4162
+
4163
+ H1_CLIENT_TEST_CASE (h1_client_connection_close_before_request_finishes ) {
4164
+ (void )ctx ;
4165
+ struct tester tester ;
4166
+ ASSERT_SUCCESS (s_tester_init (& tester , allocator ));
4167
+
4168
+ /* set up request whose body won't send immediately */
4169
+ struct slow_body_sender body_sender ;
4170
+ AWS_ZERO_STRUCT (body_sender );
4171
+ s_slow_body_sender_init (& body_sender );
4172
+ struct aws_input_stream * body_stream = & body_sender .base ;
4173
+
4174
+ struct aws_http_header headers [] = {
4175
+ {
4176
+ .name = aws_byte_cursor_from_c_str ("Content-Length" ),
4177
+ .value = aws_byte_cursor_from_c_str ("16" ),
4178
+ },
4179
+ };
4180
+
4181
+ struct aws_http_message * request = aws_http_message_new_request (allocator );
4182
+ ASSERT_NOT_NULL (request );
4183
+ ASSERT_SUCCESS (aws_http_message_set_request_method (request , aws_byte_cursor_from_c_str ("PUT" )));
4184
+ ASSERT_SUCCESS (aws_http_message_set_request_path (request , aws_byte_cursor_from_c_str ("/plan.txt" )));
4185
+ ASSERT_SUCCESS (aws_http_message_add_header_array (request , headers , AWS_ARRAY_SIZE (headers )));
4186
+ aws_http_message_set_body_stream (request , body_stream );
4187
+
4188
+ struct client_stream_tester stream_tester ;
4189
+ ASSERT_SUCCESS (s_stream_tester_init (& stream_tester , & tester , request ));
4190
+
4191
+ /* send head of request */
4192
+ testing_channel_run_currently_queued_tasks (& tester .testing_channel );
4193
+
4194
+ /* Ensure the request can be destroyed after request is sent */
4195
+ aws_http_message_destroy (request );
4196
+ aws_input_stream_release (body_stream );
4197
+
4198
+ /* send close connection response */
4199
+ ASSERT_SUCCESS (testing_channel_push_read_str (
4200
+ & tester .testing_channel ,
4201
+ "HTTP/1.1 404 Not Found\r\n"
4202
+ "Date: Fri, 01 Mar 2019 17:18:55 GMT\r\n"
4203
+ "\r\n" ));
4204
+
4205
+ testing_channel_run_currently_queued_tasks (& tester .testing_channel );
4206
+
4207
+ aws_channel_shutdown (tester .testing_channel .channel , AWS_ERROR_SUCCESS );
4208
+ /* Wait for channel to finish shutdown */
4209
+ testing_channel_drain_queued_tasks (& tester .testing_channel );
4210
+ /* check result, should not receive any body */
4211
+ const char * expected = "PUT /plan.txt HTTP/1.1\r\n"
4212
+ "Content-Length: 16\r\n"
4213
+ "\r\n" ;
4214
+ ASSERT_SUCCESS (testing_channel_check_written_messages_str (& tester .testing_channel , allocator , expected ));
4215
+
4216
+ ASSERT_TRUE (stream_tester .complete );
4217
+ ASSERT_INT_EQUALS (AWS_ERROR_SUCCESS , stream_tester .on_complete_error_code );
4218
+
4219
+ /* clean up */
4220
+ client_stream_tester_clean_up (& stream_tester );
4221
+ ASSERT_SUCCESS (s_tester_clean_up (& tester ));
4222
+ return AWS_OP_SUCCESS ;
4223
+ }
4224
+
4225
+ /* When response has `connection: close` any further request body should not be sent. */
4226
+ H1_CLIENT_TEST_CASE (h1_client_response_close_connection_before_request_finishes ) {
4227
+ (void )ctx ;
4228
+ struct tester tester ;
4229
+ ASSERT_SUCCESS (s_tester_init (& tester , allocator ));
4230
+
4231
+ /* set up request whose body won't send immediately */
4232
+ struct slow_body_sender body_sender ;
4233
+ AWS_ZERO_STRUCT (body_sender );
4234
+ s_slow_body_sender_init (& body_sender );
4235
+ struct aws_input_stream * body_stream = & body_sender .base ;
4236
+
4237
+ struct aws_http_header headers [] = {
4238
+ {
4239
+ .name = aws_byte_cursor_from_c_str ("Content-Length" ),
4240
+ .value = aws_byte_cursor_from_c_str ("16" ),
4241
+ },
4242
+ };
4243
+
4244
+ struct aws_http_message * request = aws_http_message_new_request (allocator );
4245
+ ASSERT_NOT_NULL (request );
4246
+ ASSERT_SUCCESS (aws_http_message_set_request_method (request , aws_byte_cursor_from_c_str ("PUT" )));
4247
+ ASSERT_SUCCESS (aws_http_message_set_request_path (request , aws_byte_cursor_from_c_str ("/plan.txt" )));
4248
+ ASSERT_SUCCESS (aws_http_message_add_header_array (request , headers , AWS_ARRAY_SIZE (headers )));
4249
+ aws_http_message_set_body_stream (request , body_stream );
4250
+
4251
+ struct client_stream_tester stream_tester ;
4252
+ ASSERT_SUCCESS (s_stream_tester_init (& stream_tester , & tester , request ));
4253
+
4254
+ /* send head of request */
4255
+ testing_channel_run_currently_queued_tasks (& tester .testing_channel );
4256
+
4257
+ /* Ensure the request can be destroyed after request is sent */
4258
+ aws_http_message_destroy (request );
4259
+ aws_input_stream_release (body_stream );
4260
+
4261
+ /* send close connection response */
4262
+ ASSERT_SUCCESS (testing_channel_push_read_str (
4263
+ & tester .testing_channel ,
4264
+ "HTTP/1.1 404 Not Found\r\n"
4265
+ "Date: Fri, 01 Mar 2019 17:18:55 GMT\r\n"
4266
+ "Connection: close\r\n"
4267
+ "\r\n" ));
4268
+
4269
+ testing_channel_drain_queued_tasks (& tester .testing_channel );
4270
+ /* check result, should not receive any body */
4271
+ const char * expected = "PUT /plan.txt HTTP/1.1\r\n"
4272
+ "Content-Length: 16\r\n"
4273
+ "\r\n" ;
4274
+ ASSERT_SUCCESS (testing_channel_check_written_messages_str (& tester .testing_channel , allocator , expected ));
4275
+ /* Check if the testing channel has shut down. */
4276
+ ASSERT_TRUE (testing_channel_is_shutdown_completed (& tester .testing_channel ));
4277
+
4278
+ ASSERT_TRUE (stream_tester .complete );
4279
+ ASSERT_INT_EQUALS (AWS_ERROR_SUCCESS , stream_tester .on_complete_error_code );
4280
+
4281
+ /* clean up */
4282
+ client_stream_tester_clean_up (& stream_tester );
4283
+ ASSERT_SUCCESS (s_tester_clean_up (& tester ));
4284
+ return AWS_OP_SUCCESS ;
4285
+ }
0 commit comments