static int s_get_config_from_js_config()

in source/auth.c [313:539]


static int s_get_config_from_js_config(
    napi_env env,
    struct aws_signing_config_aws *config,
    napi_value js_config,
    struct aws_byte_buf *region_buf,
    struct aws_byte_buf *service_buf,
    struct aws_byte_buf *signed_body_value_buf,
    struct signer_sign_request_state *state,
    struct aws_allocator *allocator) {

    config->config_type = AWS_SIGNING_CONFIG_AWS;
    int result = AWS_OP_SUCCESS;

    napi_value current_value = NULL;
    /* Get algorithm */
    if (s_get_named_property(env, js_config, "algorithm", napi_number, &current_value)) {
        int32_t algorithm_int = 0;
        napi_get_value_int32(env, current_value, &algorithm_int);
        if (algorithm_int < 0) {
            napi_throw_error(env, NULL, "Signing algorithm value out of acceptable range");
            result = AWS_OP_ERR;
            goto done;
        }

        config->algorithm = (enum aws_signing_algorithm)algorithm_int;
    }

    /* Get signature type */
    if (s_get_named_property(env, js_config, "signature_type", napi_number, &current_value)) {
        int32_t signature_type_int = 0;
        napi_get_value_int32(env, current_value, &signature_type_int);
        if (signature_type_int < 0) {
            napi_throw_error(env, NULL, "Signing signature type value out of acceptable range");
            result = AWS_OP_ERR;
            goto done;
        }

        config->signature_type = (enum aws_signature_type)signature_type_int;
    }

    /* Get provider */
    if (!s_get_named_property(env, js_config, "provider", napi_object, &current_value) ||
        NULL == (config->credentials_provider = aws_napi_credentials_provider_unwrap(env, current_value))) {

        napi_throw_type_error(env, NULL, "Credentials Provider is required");
        result = AWS_OP_ERR;
        goto done;
    }

    /* Get region */
    if (!s_get_named_property(env, js_config, "region", napi_string, &current_value)) {
        napi_throw_type_error(env, NULL, "Region string is required");
        result = AWS_OP_ERR;
        goto done;
    }
    if (aws_byte_buf_init_from_napi(region_buf, env, current_value)) {
        napi_throw_error(env, NULL, "Failed to build region buffer");
        result = AWS_OP_ERR;
        goto done;
    }
    config->region = aws_byte_cursor_from_buf(region_buf);

    /* Get service */
    if (s_get_named_property(env, js_config, "service", napi_string, &current_value)) {
        if (aws_byte_buf_init_from_napi(service_buf, env, current_value)) {
            napi_throw_error(env, NULL, "Failed to build service buffer");
            result = AWS_OP_ERR;
            goto done;
        }

        config->service = aws_byte_cursor_from_buf(service_buf);
    }

    /* Get date */
    /* #TODO eventually check for napi_date type (node v11) */
    if (s_get_named_property(env, js_config, "date", napi_object, &current_value)) {
        napi_value prototype = NULL;
        AWS_NAPI_CALL(env, napi_get_prototype(env, current_value, &prototype), {
            napi_throw_type_error(env, NULL, "Date param must be a Date object");
            result = AWS_OP_ERR;
            goto done;
        });

        napi_value valueOfFn = NULL;
        AWS_NAPI_CALL(env, napi_get_named_property(env, prototype, "getTime", &valueOfFn), {
            napi_throw_type_error(env, NULL, "Date param must be a Date object");
            result = AWS_OP_ERR;
            goto done;
        });

        napi_value node_result = NULL;
        AWS_NAPI_CALL(env, napi_call_function(env, current_value, valueOfFn, 0, NULL, &node_result), {
            napi_throw_type_error(env, NULL, "Date param must be a Date object");
            result = AWS_OP_ERR;
            goto done;
        });

        int64_t ms_since_epoch = 0;
        AWS_NAPI_CALL(env, napi_get_value_int64(env, node_result, &ms_since_epoch), {
            napi_throw_type_error(env, NULL, "Date param must be a Date object");
            result = AWS_OP_ERR;
            goto done;
        });

        aws_date_time_init_epoch_millis(&config->date, (uint64_t)ms_since_epoch);
    } else {
        aws_date_time_init_now(&config->date);
    }

    /* Get param blacklist */
    if (s_get_named_property(env, js_config, "header_blacklist", napi_object, &current_value)) {
        bool is_array = false;
        AWS_NAPI_CALL(env, napi_is_array(env, current_value, &is_array), {
            napi_throw_error(env, NULL, "Failed to check if header blacklist is an array");
            result = AWS_OP_ERR;
            goto done;
        });

        if (!is_array) {
            napi_throw_type_error(env, NULL, "header blacklist must be an array of strings");
            result = AWS_OP_ERR;
            goto done;
        }

        uint32_t blacklist_length = 0;
        AWS_NAPI_CALL(env, napi_get_array_length(env, current_value, &blacklist_length), {
            napi_throw_error(env, NULL, "Failed to get the length of node_header_blacklist");
            result = AWS_OP_ERR;
            goto done;
        });

        /* Initialize the string array */
        int err = aws_array_list_init_dynamic(
            &state->header_blacklist, allocator, blacklist_length, sizeof(struct aws_string *));
        if (err == AWS_OP_ERR) {
            aws_napi_throw_last_error(env);
            result = AWS_OP_ERR;
            goto done;
        }

        /* Start copying the strings */
        for (uint32_t i = 0; i < blacklist_length; ++i) {
            napi_value header = NULL;
            AWS_NAPI_CALL(env, napi_get_element(env, current_value, i, &header), {
                napi_throw_error(env, NULL, "Failed to get element from param blacklist");
                result = AWS_OP_ERR;
                goto done;
            });

            struct aws_string *header_name = aws_string_new_from_napi(env, header);
            if (!header_name) {
                napi_throw_error(env, NULL, "header blacklist must be array of strings");
                result = AWS_OP_ERR;
                goto done;
            }

            if (aws_array_list_push_back(&state->header_blacklist, &header_name)) {
                aws_string_destroy(header_name);
                aws_napi_throw_last_error(env);
                result = AWS_OP_ERR;
                goto done;
            }
        }

        config->should_sign_header = s_should_sign_header;
        config->should_sign_header_ud = state;
    }

    /* Get bools */
    if (s_get_named_property(env, js_config, "use_double_uri_encode", napi_boolean, &current_value)) {
        bool property_value = true;
        napi_get_value_bool(env, current_value, &property_value);
        config->flags.use_double_uri_encode = property_value;
    } else {
        config->flags.use_double_uri_encode = true;
    }

    if (s_get_named_property(env, js_config, "should_normalize_uri_path", napi_boolean, &current_value)) {
        bool property_value = true;
        napi_get_value_bool(env, current_value, &property_value);
        config->flags.should_normalize_uri_path = property_value;
    } else {
        config->flags.should_normalize_uri_path = true;
    }

    if (s_get_named_property(env, js_config, "omit_session_token", napi_boolean, &current_value)) {
        bool property_value = true;
        napi_get_value_bool(env, current_value, &property_value);
        config->flags.omit_session_token = property_value;
    } else {
        config->flags.omit_session_token = false;
    }

    /* Get signed body value */
    if (s_get_named_property(env, js_config, "signed_body_value", napi_string, &current_value)) {
        if (aws_byte_buf_init_from_napi(signed_body_value_buf, env, current_value)) {
            napi_throw_error(env, NULL, "Failed to build signed_body_value buffer");
            result = AWS_OP_ERR;
            goto done;
        }
        config->signed_body_value = aws_byte_cursor_from_buf(signed_body_value_buf);
    }

    /* Get signed body header */
    if (s_get_named_property(env, js_config, "signed_body_header", napi_number, &current_value)) {
        int32_t signed_body_header = 0;
        napi_get_value_int32(env, current_value, &signed_body_header);
        config->signed_body_header = (enum aws_signed_body_header_type)signed_body_header;
    } else {
        config->signed_body_header = AWS_SBHT_NONE;
    }

    /* Get expiration time */
    if (s_get_named_property(env, js_config, "expiration_in_seconds", napi_number, &current_value)) {
        int64_t expiration_in_seconds = 0;
        napi_get_value_int64(env, current_value, &expiration_in_seconds);
        if (expiration_in_seconds < 0) {
            napi_throw_error(env, NULL, "Signing expiration time in seconds must be non-negative");
            result = AWS_OP_ERR;
            goto done;
        }
        config->expiration_in_seconds = (uint64_t)expiration_in_seconds;
    }

done:
    return result;
}