310 lines
12 KiB
JavaScript
310 lines
12 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// src/index.ts
|
|
var src_exports = {};
|
|
__export(src_exports, {
|
|
ChecksumAlgorithm: () => ChecksumAlgorithm,
|
|
ChecksumLocation: () => ChecksumLocation,
|
|
DEFAULT_CHECKSUM_ALGORITHM: () => DEFAULT_CHECKSUM_ALGORITHM,
|
|
S3_EXPRESS_DEFAULT_CHECKSUM_ALGORITHM: () => S3_EXPRESS_DEFAULT_CHECKSUM_ALGORITHM,
|
|
flexibleChecksumsMiddleware: () => flexibleChecksumsMiddleware,
|
|
flexibleChecksumsMiddlewareOptions: () => flexibleChecksumsMiddlewareOptions,
|
|
getFlexibleChecksumsPlugin: () => getFlexibleChecksumsPlugin
|
|
});
|
|
module.exports = __toCommonJS(src_exports);
|
|
|
|
// src/constants.ts
|
|
var ChecksumAlgorithm = /* @__PURE__ */ ((ChecksumAlgorithm3) => {
|
|
ChecksumAlgorithm3["MD5"] = "MD5";
|
|
ChecksumAlgorithm3["CRC32"] = "CRC32";
|
|
ChecksumAlgorithm3["CRC32C"] = "CRC32C";
|
|
ChecksumAlgorithm3["SHA1"] = "SHA1";
|
|
ChecksumAlgorithm3["SHA256"] = "SHA256";
|
|
return ChecksumAlgorithm3;
|
|
})(ChecksumAlgorithm || {});
|
|
var ChecksumLocation = /* @__PURE__ */ ((ChecksumLocation2) => {
|
|
ChecksumLocation2["HEADER"] = "header";
|
|
ChecksumLocation2["TRAILER"] = "trailer";
|
|
return ChecksumLocation2;
|
|
})(ChecksumLocation || {});
|
|
var DEFAULT_CHECKSUM_ALGORITHM = "MD5" /* MD5 */;
|
|
var S3_EXPRESS_DEFAULT_CHECKSUM_ALGORITHM = "CRC32" /* CRC32 */;
|
|
|
|
// src/flexibleChecksumsMiddleware.ts
|
|
var import_protocol_http = require("@smithy/protocol-http");
|
|
|
|
// src/types.ts
|
|
var CLIENT_SUPPORTED_ALGORITHMS = [
|
|
"CRC32" /* CRC32 */,
|
|
"CRC32C" /* CRC32C */,
|
|
"SHA1" /* SHA1 */,
|
|
"SHA256" /* SHA256 */
|
|
];
|
|
var PRIORITY_ORDER_ALGORITHMS = [
|
|
"CRC32" /* CRC32 */,
|
|
"CRC32C" /* CRC32C */,
|
|
"SHA1" /* SHA1 */,
|
|
"SHA256" /* SHA256 */
|
|
];
|
|
|
|
// src/getChecksumAlgorithmForRequest.ts
|
|
var getChecksumAlgorithmForRequest = /* @__PURE__ */ __name((input, { requestChecksumRequired, requestAlgorithmMember }, isS3Express) => {
|
|
const defaultAlgorithm = isS3Express ? S3_EXPRESS_DEFAULT_CHECKSUM_ALGORITHM : DEFAULT_CHECKSUM_ALGORITHM;
|
|
if (!requestAlgorithmMember || !input[requestAlgorithmMember]) {
|
|
return requestChecksumRequired ? defaultAlgorithm : void 0;
|
|
}
|
|
const checksumAlgorithm = input[requestAlgorithmMember];
|
|
if (!CLIENT_SUPPORTED_ALGORITHMS.includes(checksumAlgorithm)) {
|
|
throw new Error(
|
|
`The checksum algorithm "${checksumAlgorithm}" is not supported by the client. Select one of ${CLIENT_SUPPORTED_ALGORITHMS}.`
|
|
);
|
|
}
|
|
return checksumAlgorithm;
|
|
}, "getChecksumAlgorithmForRequest");
|
|
|
|
// src/getChecksumLocationName.ts
|
|
var getChecksumLocationName = /* @__PURE__ */ __name((algorithm) => algorithm === "MD5" /* MD5 */ ? "content-md5" : `x-amz-checksum-${algorithm.toLowerCase()}`, "getChecksumLocationName");
|
|
|
|
// src/hasHeader.ts
|
|
var hasHeader = /* @__PURE__ */ __name((header, headers) => {
|
|
const soughtHeader = header.toLowerCase();
|
|
for (const headerName of Object.keys(headers)) {
|
|
if (soughtHeader === headerName.toLowerCase()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}, "hasHeader");
|
|
|
|
// src/isStreaming.ts
|
|
var import_is_array_buffer = require("@smithy/is-array-buffer");
|
|
var isStreaming = /* @__PURE__ */ __name((body) => body !== void 0 && typeof body !== "string" && !ArrayBuffer.isView(body) && !(0, import_is_array_buffer.isArrayBuffer)(body), "isStreaming");
|
|
|
|
// src/selectChecksumAlgorithmFunction.ts
|
|
var import_crc32 = require("@aws-crypto/crc32");
|
|
var import_crc32c = require("@aws-crypto/crc32c");
|
|
var selectChecksumAlgorithmFunction = /* @__PURE__ */ __name((checksumAlgorithm, config) => ({
|
|
["MD5" /* MD5 */]: config.md5,
|
|
["CRC32" /* CRC32 */]: import_crc32.AwsCrc32,
|
|
["CRC32C" /* CRC32C */]: import_crc32c.AwsCrc32c,
|
|
["SHA1" /* SHA1 */]: config.sha1,
|
|
["SHA256" /* SHA256 */]: config.sha256
|
|
})[checksumAlgorithm], "selectChecksumAlgorithmFunction");
|
|
|
|
// src/stringHasher.ts
|
|
var import_util_utf8 = require("@smithy/util-utf8");
|
|
var stringHasher = /* @__PURE__ */ __name((checksumAlgorithmFn, body) => {
|
|
const hash = new checksumAlgorithmFn();
|
|
hash.update((0, import_util_utf8.toUint8Array)(body || ""));
|
|
return hash.digest();
|
|
}, "stringHasher");
|
|
|
|
// src/flexibleChecksumsMiddleware.ts
|
|
var flexibleChecksumsMiddlewareOptions = {
|
|
name: "flexibleChecksumsMiddleware",
|
|
step: "build",
|
|
tags: ["BODY_CHECKSUM"],
|
|
override: true
|
|
};
|
|
var flexibleChecksumsMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => {
|
|
if (!import_protocol_http.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 = getChecksumAlgorithmForRequest(
|
|
input,
|
|
{
|
|
requestChecksumRequired,
|
|
requestAlgorithmMember
|
|
},
|
|
!!context.isS3ExpressBucket
|
|
);
|
|
let updatedBody = requestBody;
|
|
let updatedHeaders = headers;
|
|
if (checksumAlgorithm) {
|
|
const checksumLocationName = getChecksumLocationName(checksumAlgorithm);
|
|
const checksumAlgorithmFn = selectChecksumAlgorithmFunction(checksumAlgorithm, config);
|
|
if (isStreaming(requestBody)) {
|
|
const { getAwsChunkedEncodingStream, bodyLengthChecker } = config;
|
|
updatedBody = getAwsChunkedEncodingStream(requestBody, {
|
|
base64Encoder,
|
|
bodyLengthChecker,
|
|
checksumLocationName,
|
|
checksumAlgorithmFn,
|
|
streamHasher
|
|
});
|
|
updatedHeaders = {
|
|
...headers,
|
|
"content-encoding": headers["content-encoding"] ? `${headers["content-encoding"]},aws-chunked` : "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 (!hasHeader(checksumLocationName, headers)) {
|
|
const rawChecksum = await stringHasher(checksumAlgorithmFn, requestBody);
|
|
updatedHeaders = {
|
|
...headers,
|
|
[checksumLocationName]: base64Encoder(rawChecksum)
|
|
};
|
|
}
|
|
}
|
|
const result = await next({
|
|
...args,
|
|
request: {
|
|
...request,
|
|
headers: updatedHeaders,
|
|
body: updatedBody
|
|
}
|
|
});
|
|
return result;
|
|
}, "flexibleChecksumsMiddleware");
|
|
|
|
// src/flexibleChecksumsResponseMiddleware.ts
|
|
|
|
|
|
// src/getChecksumAlgorithmListForResponse.ts
|
|
var getChecksumAlgorithmListForResponse = /* @__PURE__ */ __name((responseAlgorithms = []) => {
|
|
const validChecksumAlgorithms = [];
|
|
for (const algorithm of PRIORITY_ORDER_ALGORITHMS) {
|
|
if (!responseAlgorithms.includes(algorithm) || !CLIENT_SUPPORTED_ALGORITHMS.includes(algorithm)) {
|
|
continue;
|
|
}
|
|
validChecksumAlgorithms.push(algorithm);
|
|
}
|
|
return validChecksumAlgorithms;
|
|
}, "getChecksumAlgorithmListForResponse");
|
|
|
|
// src/isChecksumWithPartNumber.ts
|
|
var isChecksumWithPartNumber = /* @__PURE__ */ __name((checksum) => {
|
|
const lastHyphenIndex = checksum.lastIndexOf("-");
|
|
if (lastHyphenIndex !== -1) {
|
|
const numberPart = checksum.slice(lastHyphenIndex + 1);
|
|
if (!numberPart.startsWith("0")) {
|
|
const number = parseInt(numberPart, 10);
|
|
if (!isNaN(number) && number >= 1 && number <= 1e4) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}, "isChecksumWithPartNumber");
|
|
|
|
// src/flexibleChecksumsResponseMiddleware.ts
|
|
var import_create_read_stream_on_buffer = require("./streams/create-read-stream-on-buffer");
|
|
|
|
// src/getChecksum.ts
|
|
var getChecksum = /* @__PURE__ */ __name(async (body, { streamHasher, checksumAlgorithmFn, base64Encoder }) => {
|
|
const digest = isStreaming(body) ? streamHasher(checksumAlgorithmFn, body) : stringHasher(checksumAlgorithmFn, body);
|
|
return base64Encoder(await digest);
|
|
}, "getChecksum");
|
|
|
|
// src/validateChecksumFromResponse.ts
|
|
var validateChecksumFromResponse = /* @__PURE__ */ __name(async (response, { config, responseAlgorithms }) => {
|
|
const checksumAlgorithms = getChecksumAlgorithmListForResponse(responseAlgorithms);
|
|
const { body: responseBody, headers: responseHeaders } = response;
|
|
for (const algorithm of checksumAlgorithms) {
|
|
const responseHeader = getChecksumLocationName(algorithm);
|
|
const checksumFromResponse = responseHeaders[responseHeader];
|
|
if (checksumFromResponse) {
|
|
const checksumAlgorithmFn = selectChecksumAlgorithmFunction(algorithm, config);
|
|
const { streamHasher, base64Encoder } = config;
|
|
const checksum = await getChecksum(responseBody, { streamHasher, checksumAlgorithmFn, base64Encoder });
|
|
if (checksum === checksumFromResponse) {
|
|
break;
|
|
}
|
|
throw new Error(
|
|
`Checksum mismatch: expected "${checksum}" but received "${checksumFromResponse}" in response header "${responseHeader}".`
|
|
);
|
|
}
|
|
}
|
|
}, "validateChecksumFromResponse");
|
|
|
|
// src/flexibleChecksumsResponseMiddleware.ts
|
|
var flexibleChecksumsResponseMiddlewareOptions = {
|
|
name: "flexibleChecksumsResponseMiddleware",
|
|
toMiddleware: "deserializerMiddleware",
|
|
relation: "after",
|
|
tags: ["BODY_CHECKSUM"],
|
|
override: true
|
|
};
|
|
var flexibleChecksumsResponseMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => {
|
|
if (!import_protocol_http.HttpRequest.isInstance(args.request)) {
|
|
return next(args);
|
|
}
|
|
const input = args.input;
|
|
const result = await next(args);
|
|
const response = result.response;
|
|
let collectedStream = void 0;
|
|
const { requestValidationModeMember, responseAlgorithms } = middlewareConfig;
|
|
if (requestValidationModeMember && input[requestValidationModeMember] === "ENABLED") {
|
|
const { clientName, commandName } = context;
|
|
const isS3WholeObjectMultipartGetResponseChecksum = clientName === "S3Client" && commandName === "GetObjectCommand" && getChecksumAlgorithmListForResponse(responseAlgorithms).every((algorithm) => {
|
|
const responseHeader = getChecksumLocationName(algorithm);
|
|
const checksumFromResponse = response.headers[responseHeader];
|
|
return !checksumFromResponse || isChecksumWithPartNumber(checksumFromResponse);
|
|
});
|
|
if (isS3WholeObjectMultipartGetResponseChecksum) {
|
|
return result;
|
|
}
|
|
const isStreamingBody = isStreaming(response.body);
|
|
if (isStreamingBody) {
|
|
collectedStream = await config.streamCollector(response.body);
|
|
response.body = (0, import_create_read_stream_on_buffer.createReadStreamOnBuffer)(collectedStream);
|
|
}
|
|
await validateChecksumFromResponse(result.response, {
|
|
config,
|
|
responseAlgorithms
|
|
});
|
|
if (isStreamingBody && collectedStream) {
|
|
response.body = (0, import_create_read_stream_on_buffer.createReadStreamOnBuffer)(collectedStream);
|
|
}
|
|
}
|
|
return result;
|
|
}, "flexibleChecksumsResponseMiddleware");
|
|
|
|
// src/getFlexibleChecksumsPlugin.ts
|
|
var getFlexibleChecksumsPlugin = /* @__PURE__ */ __name((config, middlewareConfig) => ({
|
|
applyToStack: (clientStack) => {
|
|
clientStack.add(flexibleChecksumsMiddleware(config, middlewareConfig), flexibleChecksumsMiddlewareOptions);
|
|
clientStack.addRelativeTo(
|
|
flexibleChecksumsResponseMiddleware(config, middlewareConfig),
|
|
flexibleChecksumsResponseMiddlewareOptions
|
|
);
|
|
}
|
|
}), "getFlexibleChecksumsPlugin");
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
|
|
0 && (module.exports = {
|
|
ChecksumAlgorithm,
|
|
ChecksumLocation,
|
|
DEFAULT_CHECKSUM_ALGORITHM,
|
|
S3_EXPRESS_DEFAULT_CHECKSUM_ALGORITHM,
|
|
flexibleChecksumsMiddlewareOptions,
|
|
flexibleChecksumsMiddleware,
|
|
getFlexibleChecksumsPlugin
|
|
});
|
|
|