"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.flexibleChecksumsMiddleware = void 0;
const protocol_http_1 = require("@aws-sdk/protocol-http");
const getChecksumAlgorithmForRequest_1 = require("./getChecksumAlgorithmForRequest");
const getChecksumLocationName_1 = require("./getChecksumLocationName");
const hasHeader_1 = require("./hasHeader");
const isStreaming_1 = require("./isStreaming");
const selectChecksumAlgorithmFunction_1 = require("./selectChecksumAlgorithmFunction");
const stringHasher_1 = require("./stringHasher");
const validateChecksumFromResponse_1 = require("./validateChecksumFromResponse");
const flexibleChecksumsMiddleware = (config, middlewareConfig) => (next) => async (args) => {
    if (!protocol_http_1.HttpRequest.isInstance(args.request)) {
        return next(args);
    }
    const { request } = args;
    const { body: requestBody, headers } = request;
    const { base64Encoder, streamHasher } = config;
    const { input, requestChecksumRequired, requestAlgorithmMember } = middlewareConfig;
    const checksumAlgorithm = (0, getChecksumAlgorithmForRequest_1.getChecksumAlgorithmForRequest)(input, {
        requestChecksumRequired,
        requestAlgorithmMember,
    });
    let updatedBody = requestBody;
    let updatedHeaders = headers;
    if (checksumAlgorithm) {
        const checksumLocationName = (0, getChecksumLocationName_1.getChecksumLocationName)(checksumAlgorithm);
        const checksumAlgorithmFn = (0, selectChecksumAlgorithmFunction_1.selectChecksumAlgorithmFunction)(checksumAlgorithm, config);
        if ((0, isStreaming_1.isStreaming)(requestBody)) {
            const { getAwsChunkedEncodingStream, bodyLengthChecker } = config;
            updatedBody = getAwsChunkedEncodingStream(requestBody, {
                base64Encoder,
                bodyLengthChecker,
                checksumLocationName,
                checksumAlgorithmFn,
                streamHasher,
            });
            updatedHeaders = {
                ...headers,
                "content-encoding": "aws-chunked",
                "transfer-encoding": "chunked",
                "x-amz-decoded-content-length": headers["content-length"],
                "x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER",
                "x-amz-trailer": checksumLocationName,
            };
            delete updatedHeaders["content-length"];
        }
        else if (!(0, hasHeader_1.hasHeader)(checksumLocationName, headers)) {
            const rawChecksum = await (0, stringHasher_1.stringHasher)(checksumAlgorithmFn, requestBody);
            updatedHeaders = {
                ...headers,
                [checksumLocationName]: base64Encoder(rawChecksum),
            };
        }
    }
    const result = await next({
        ...args,
        request: {
            ...request,
            headers: updatedHeaders,
            body: updatedBody,
        },
    });
    const { requestValidationModeMember, responseAlgorithms } = middlewareConfig;
    if (requestValidationModeMember && input[requestValidationModeMember] === "ENABLED") {
        (0, validateChecksumFromResponse_1.validateChecksumFromResponse)(result.response, {
            config,
            responseAlgorithms,
        });
    }
    return result;
};
exports.flexibleChecksumsMiddleware = flexibleChecksumsMiddleware;
