in source/aws_signing.c [961:1066]
static int s_append_canonical_query_string(struct aws_uri *uri, struct aws_signing_state_aws *state) {
struct aws_allocator *allocator = state->allocator;
struct aws_byte_buf *canonical_request_buffer = &state->canonical_request;
int result = AWS_OP_ERR;
struct aws_array_list query_params;
AWS_ZERO_STRUCT(query_params);
struct aws_array_list temp_strings;
AWS_ZERO_STRUCT(temp_strings);
/* Determine max number of query parameters.
* If none, skip to end of function */
size_t max_param_count = 0;
struct aws_uri_param param_i;
AWS_ZERO_STRUCT(param_i);
while (aws_uri_query_string_next_param(uri, ¶m_i)) {
++max_param_count;
}
if (state->config.signature_type == AWS_ST_HTTP_REQUEST_QUERY_PARAMS) {
max_param_count += MAX_AUTHORIZATION_QUERY_PARAM_COUNT;
}
if (max_param_count == 0) {
goto finish;
}
/* Allocate storage for mutable list of query params */
if (aws_array_list_init_dynamic(&query_params, allocator, max_param_count, sizeof(struct aws_uri_param))) {
goto cleanup;
}
/* Allocate storage for both the decoded, and re-encoded, key and value strings */
if (aws_array_list_init_dynamic(
&temp_strings, state->allocator, max_param_count * 4, sizeof(struct aws_string *))) {
goto cleanup;
}
/* Get existing query params */
if (aws_uri_query_string_params(uri, &query_params)) {
goto cleanup;
}
/* Remove URI-encoding */
if (s_transform_query_params(state, &query_params, &temp_strings, aws_byte_buf_append_decoding_uri)) {
goto cleanup;
}
/* Validate existing query params */
if (s_validate_query_params(&query_params)) {
goto cleanup;
}
/* Add authorization query params */
if (s_add_authorization_query_params(state, &query_params)) {
goto cleanup;
}
/* Apply canonical URI-encoding to the query params */
if (s_transform_query_params(state, &query_params, &temp_strings, aws_byte_buf_append_encoding_uri_param)) {
goto cleanup;
}
const size_t param_count = aws_array_list_length(&query_params);
/* Sort the encoded params and append to canonical request */
qsort(query_params.data, param_count, sizeof(struct aws_uri_param), s_canonical_query_param_comparator);
for (size_t i = 0; i < param_count; ++i) {
struct aws_uri_param param;
AWS_ZERO_STRUCT(param);
if (aws_array_list_get_at(&query_params, ¶m, i)) {
goto cleanup;
}
if (s_append_canonical_query_param(¶m, canonical_request_buffer)) {
goto cleanup;
}
if (i + 1 < param_count) {
if (aws_byte_buf_append_byte_dynamic(canonical_request_buffer, '&')) {
goto cleanup;
}
}
}
finish:
if (aws_byte_buf_append_byte_dynamic(canonical_request_buffer, '\n')) {
goto cleanup;
}
result = AWS_OP_SUCCESS;
cleanup:
aws_array_list_clean_up(&query_params);
if (aws_array_list_is_valid(&temp_strings)) {
const size_t string_count = aws_array_list_length(&temp_strings);
for (size_t i = 0; i < string_count; ++i) {
struct aws_string *string = NULL;
aws_array_list_get_at(&temp_strings, &string, i);
aws_string_destroy(string);
}
aws_array_list_clean_up(&temp_strings);
}
return result;
}