static int s_append_canonical_query_string()

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, &param_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, &param, i)) {
            goto cleanup;
        }

        if (s_append_canonical_query_param(&param, 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;
}