44 */
55
66#include "aws/s3/private/s3_util.h"
7+ #include "aws/s3/private/s3_client_impl.h"
78#include <aws/auth/credentials.h>
89#include <aws/common/string.h>
910#include <aws/common/xml_parser.h>
1011#include <aws/http/request_response.h>
1112#include <aws/s3/s3.h>
1213#include <aws/s3/s3_client.h>
1314
15+ const struct aws_byte_cursor g_s3_client_version = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL (AWS_S3_CLIENT_VERSION );
1416const struct aws_byte_cursor g_s3_service_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("s3" );
1517const struct aws_byte_cursor g_host_header_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("Host" );
1618const struct aws_byte_cursor g_range_header_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("Range" );
@@ -23,6 +25,10 @@ const struct aws_byte_cursor g_acl_header_name = AWS_BYTE_CUR_INIT_FROM_STRING_L
2325const struct aws_byte_cursor g_post_method = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("POST" );
2426const struct aws_byte_cursor g_delete_method = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("DELETE" );
2527
28+ const struct aws_byte_cursor g_user_agent_header_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("User-Agent" );
29+ const struct aws_byte_cursor g_user_agent_header_product_name =
30+ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("CRTS3NativeClient" );
31+
2632const uint32_t g_s3_max_num_upload_parts = 10000 ;
2733const size_t g_s3_min_upload_part_size = MB_TO_BYTES (5 );
2834
@@ -249,3 +255,56 @@ int aws_last_error_or_unknown() {
249255
250256 return error ;
251257}
258+
259+ void aws_s3_add_user_agent_header (struct aws_allocator * allocator , struct aws_http_message * message ) {
260+ AWS_PRECONDITION (allocator );
261+ AWS_PRECONDITION (message );
262+
263+ const struct aws_byte_cursor space_delimeter = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL (" " );
264+ const struct aws_byte_cursor forward_slash = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL ("/" );
265+
266+ const size_t user_agent_product_version_length =
267+ g_user_agent_header_product_name .len + forward_slash .len + g_s3_client_version .len ;
268+
269+ struct aws_http_headers * headers = aws_http_message_get_headers (message );
270+ AWS_ASSERT (headers != NULL );
271+
272+ struct aws_byte_cursor current_user_agent_header ;
273+ AWS_ZERO_STRUCT (current_user_agent_header );
274+
275+ struct aws_byte_buf user_agent_buffer ;
276+ AWS_ZERO_STRUCT (user_agent_buffer );
277+
278+ if (!aws_http_headers_get (headers , g_user_agent_header_name , & current_user_agent_header )) {
279+ /* If the header was found, then create a buffer with the total size we'll need, and append the curent user
280+ * agent header with a trailing space. */
281+ aws_byte_buf_init (
282+ & user_agent_buffer ,
283+ allocator ,
284+ current_user_agent_header .len + space_delimeter .len + user_agent_product_version_length );
285+
286+ aws_byte_buf_append_dynamic (& user_agent_buffer , & current_user_agent_header );
287+
288+ aws_byte_buf_append_dynamic (& user_agent_buffer , & space_delimeter );
289+
290+ } else {
291+ AWS_ASSERT (aws_last_error () == AWS_ERROR_HTTP_HEADER_NOT_FOUND );
292+
293+ /* If the header was not found, then create a buffer with just the size of the user agent string that is about
294+ * to be appended to the buffer. */
295+ aws_byte_buf_init (& user_agent_buffer , allocator , user_agent_product_version_length );
296+ }
297+
298+ /* Append the client's user-agent string. */
299+ {
300+ aws_byte_buf_append_dynamic (& user_agent_buffer , & g_user_agent_header_product_name );
301+ aws_byte_buf_append_dynamic (& user_agent_buffer , & forward_slash );
302+ aws_byte_buf_append_dynamic (& user_agent_buffer , & g_s3_client_version );
303+ }
304+
305+ /* Apply the updated header. */
306+ aws_http_headers_set (headers , g_user_agent_header_name , aws_byte_cursor_from_buf (& user_agent_buffer ));
307+
308+ /* Clean up the scratch buffer. */
309+ aws_byte_buf_clean_up (& user_agent_buffer );
310+ }
0 commit comments