UNPKG

serverless-spy

Version:

CDK-based library for writing elegant integration tests on AWS serverless architecture and an additional web console to monitor events in real time.

68 lines (67 loc) 2.5 kB
import { HttpResponse } from "@smithy/protocol-http"; import { headStream, splitStream } from "@smithy/util-stream"; const THROW_IF_EMPTY_BODY = { CopyObjectCommand: true, UploadPartCopyCommand: true, CompleteMultipartUploadCommand: true, }; const MAX_BYTES_TO_INSPECT = 3000; export const throw200ExceptionsMiddleware = (config) => (next, context) => async (args) => { const result = await next(args); const { response } = result; if (!HttpResponse.isInstance(response)) { return result; } const { statusCode, body: sourceBody } = response; if (statusCode < 200 || statusCode >= 300) { return result; } const isSplittableStream = typeof sourceBody?.stream === "function" || typeof sourceBody?.pipe === "function" || typeof sourceBody?.tee === "function"; if (!isSplittableStream) { return result; } let bodyCopy = sourceBody; let body = sourceBody; if (sourceBody && typeof sourceBody === "object" && !(sourceBody instanceof Uint8Array)) { [bodyCopy, body] = await splitStream(sourceBody); } response.body = body; const bodyBytes = await collectBody(bodyCopy, { streamCollector: async (stream) => { return headStream(stream, MAX_BYTES_TO_INSPECT); }, }); if (typeof bodyCopy?.destroy === "function") { bodyCopy.destroy(); } const bodyStringTail = config.utf8Encoder(bodyBytes.subarray(bodyBytes.length - 16)); if (bodyBytes.length === 0 && THROW_IF_EMPTY_BODY[context.commandName]) { const err = new Error("S3 aborted request"); err.name = "InternalError"; throw err; } if (bodyStringTail && bodyStringTail.endsWith("</Error>")) { response.statusCode = 400; } return result; }; const collectBody = (streamBody = new Uint8Array(), context) => { if (streamBody instanceof Uint8Array) { return Promise.resolve(streamBody); } return context.streamCollector(streamBody) || Promise.resolve(new Uint8Array()); }; export const throw200ExceptionsMiddlewareOptions = { relation: "after", toMiddleware: "deserializerMiddleware", tags: ["THROW_200_EXCEPTIONS", "S3"], name: "throw200ExceptionsMiddleware", override: true, }; export const getThrow200ExceptionsPlugin = (config) => ({ applyToStack: (clientStack) => { clientStack.addRelativeTo(throw200ExceptionsMiddleware(config), throw200ExceptionsMiddlewareOptions); }, });