From b02098ecf8ebaa83353579d873ae2fcd54f4b635 Mon Sep 17 00:00:00 2001 From: Dengke Date: Fri, 8 Nov 2024 09:48:06 -0800 Subject: [PATCH] will it break? --- include/aws/s3/private/s3_client_impl.h | 4 ++ include/aws/s3/private/s3_request.h | 3 ++ source/s3_client.c | 1 + source/s3_meta_request.c | 50 ++++++++++++++----------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/aws/s3/private/s3_client_impl.h b/include/aws/s3/private/s3_client_impl.h index d90dad112..597f8add8 100644 --- a/include/aws/s3/private/s3_client_impl.h +++ b/include/aws/s3/private/s3_client_impl.h @@ -169,6 +169,10 @@ struct aws_s3_client_vtable { struct aws_parallel_input_stream *( *parallel_input_stream_new_from_file)(struct aws_allocator *allocator, struct aws_byte_cursor file_name); + + struct aws_http_stream *(*http_connection_make_request)( + struct aws_http_connection *client_connection, + const struct aws_http_make_request_options *options); }; struct aws_s3_upload_part_timeout_stats { diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index c132246fc..dab05323d 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -212,6 +212,9 @@ struct aws_s3_request { /* The metrics for the request telemetry */ struct aws_s3_request_metrics *metrics; + + /* The request is required to have the unsigned payload */ + uint32_t require_streaming_unsigned_payload_header : 1; } send_data; /* When true, response headers from the request will be stored in the request's response_headers variable. */ diff --git a/source/s3_client.c b/source/s3_client.c index c1f2fcf75..9caac24d5 100644 --- a/source/s3_client.c +++ b/source/s3_client.c @@ -141,6 +141,7 @@ static struct aws_s3_client_vtable s_s3_client_default_vtable = { .endpoint_shutdown_callback = s_s3_client_endpoint_shutdown_callback, .finish_destroy = s_s3_client_finish_destroy_default, .parallel_input_stream_new_from_file = aws_parallel_input_stream_new_from_file, + .http_connection_make_request = aws_http_connection_make_request, }; void aws_s3_set_dns_ttl(size_t ttl) { diff --git a/source/s3_meta_request.c b/source/s3_meta_request.c index a78034c4c..9360dbbfd 100644 --- a/source/s3_meta_request.c +++ b/source/s3_meta_request.c @@ -864,7 +864,7 @@ static void s_get_original_credentials_callback(struct aws_credentials *credenti } } -static int s_meta_request_resolve_signing_config( +static void s_meta_request_resolve_signing_config( struct aws_signing_config_aws *out_signing_config, struct aws_s3_request *request, struct aws_s3_meta_request *meta_request) { @@ -897,7 +897,12 @@ static int s_meta_request_resolve_signing_config( &out_signing_config->signed_body_value, &g_aws_signed_body_value_streaming_unsigned_payload_trailer)) { out_signing_config->signed_body_value = g_aws_signed_body_value_unsigned_payload; } - return AWS_OP_SUCCESS; + + /** + * In case of the signing was skipped for anonymous credentials, or presigned URL. + */ + request->send_data.require_streaming_unsigned_payload_header = aws_byte_cursor_eq( + &out_signing_config->signed_body_value, &g_aws_signed_body_value_streaming_unsigned_payload_trailer); } void aws_s3_meta_request_sign_request_default_impl( @@ -915,19 +920,19 @@ void aws_s3_meta_request_sign_request_default_impl( struct aws_signing_config_aws signing_config; - if (s_meta_request_resolve_signing_config(&signing_config, request, meta_request)) { - AWS_LOGF_DEBUG( + s_meta_request_resolve_signing_config(&signing_config, request, meta_request); + + request->send_data.signable = aws_signable_new_http_request(meta_request->allocator, request->send_data.message); + if (request->send_data.signable == NULL) { + AWS_LOGF_ERROR( AWS_LS_S3_META_REQUEST, - "id=%p: No signing config present. Not signing request %p.", + "id=%p: Could not allocate signable for request %p", (void *)meta_request, (void *)request); - on_signing_complete(NULL, AWS_ERROR_SUCCESS, user_data); + on_signing_complete(NULL, aws_last_error_or_unknown(), user_data); return; } - - request->send_data.signable = aws_signable_new_http_request(meta_request->allocator, request->send_data.message); - AWS_LOGF_TRACE( AWS_LS_S3_META_REQUEST, "id=%p Created signable %p for request %p with message %p", @@ -936,17 +941,6 @@ void aws_s3_meta_request_sign_request_default_impl( (void *)request, (void *)request->send_data.message); - if (request->send_data.signable == NULL) { - AWS_LOGF_ERROR( - AWS_LS_S3_META_REQUEST, - "id=%p: Could not allocate signable for request %p", - (void *)meta_request, - (void *)request); - - on_signing_complete(NULL, aws_last_error_or_unknown(), user_data); - return; - } - if (signing_config.algorithm == AWS_SIGNING_ALGORITHM_V4_S3EXPRESS && !disable_s3_express_signing) { /* Fetch credentials from S3 Express provider. */ struct aws_get_s3express_credentials_user_data *context = @@ -1074,6 +1068,17 @@ static void s_s3_meta_request_request_on_signed( aws_error_str(error_code)); } + /** + * Add the x-amz-content-sha256 header to support trailing checksum. + */ + if (request->send_data.require_streaming_unsigned_payload_header) { + struct aws_http_header trailer_content_sha256_header = { + .name = aws_byte_cursor_from_c_str("x-amz-content-sha256"), + .value = g_aws_signed_body_value_streaming_unsigned_payload_trailer, + }; + aws_http_message_add_header(request->send_data.message, trailer_content_sha256_header); + } + s_s3_prepare_request_payload_callback_and_destroy(payload, error_code); } @@ -1082,6 +1087,8 @@ void aws_s3_meta_request_send_request(struct aws_s3_meta_request *meta_request, AWS_PRECONDITION(connection); AWS_PRECONDITION(connection->http_connection); + struct aws_s3_client *client = meta_request->client; + AWS_PRECONDITION(client); struct aws_s3_request *request = connection->request; AWS_PRECONDITION(request); @@ -1104,7 +1111,8 @@ void aws_s3_meta_request_send_request(struct aws_s3_meta_request *meta_request, request->upload_timeout_ms = (size_t)options.response_first_byte_timeout_ms; } - struct aws_http_stream *stream = aws_http_connection_make_request(connection->http_connection, &options); + struct aws_http_stream *stream = + client->vtable->http_connection_make_request(connection->http_connection, &options); if (stream == NULL) { AWS_LOGF_ERROR(