|
| 1 | +import { |
| 2 | + TRACER_KEY, |
| 3 | + METRICS_KEY, |
| 4 | + LOGGER_KEY, |
| 5 | + IDEMPOTENCY_KEY, |
| 6 | +} from './constants'; |
| 7 | +import type { MiddyLikeRequest, CleanupFunction } from '../types/middy'; |
| 8 | + |
| 9 | +// Typeguard to assert that an object is of Function type |
| 10 | +const isFunction = (obj: unknown): obj is CleanupFunction => { |
| 11 | + return typeof obj === 'function'; |
| 12 | +}; |
| 13 | + |
| 14 | +/** |
| 15 | + * Function used to cleanup Powertools for AWS resources when a Middy |
| 16 | + * middleware [returns early](https://middy.js.org/docs/intro/early-interrupt) |
| 17 | + * and terminates the middleware chain. |
| 18 | + * |
| 19 | + * When a middleware returns early, all the middleware lifecycle functions |
| 20 | + * that come after it are not executed. This means that if a middleware |
| 21 | + * was relying on certain logic to be run during the `after` or `onError` |
| 22 | + * lifecycle functions, that logic will not be executed. |
| 23 | + * |
| 24 | + * This is the case for the middlewares that are part of Powertools for AWS |
| 25 | + * which rely on these lifecycle functions to perform cleanup operations |
| 26 | + * like closing the current segment in the tracer or flushing any stored |
| 27 | + * metrics. |
| 28 | + * |
| 29 | + * When authoring a middleware that might return early, you can use this |
| 30 | + * function to cleanup Powertools resources. This function will check if |
| 31 | + * any cleanup function is present in the `request.internal` object and |
| 32 | + * execute it. |
| 33 | + * |
| 34 | + * @example |
| 35 | + * ```typescript |
| 36 | + * import middy from '@middy/core'; |
| 37 | + * import { cleanupMiddlewares } from '@aws-lambda-powertools/commons/lib/middleware'; |
| 38 | + * |
| 39 | + * // Example middleware that returns early |
| 40 | + * const myCustomMiddleware = (): middy.MiddlewareObj => { |
| 41 | + * const before = async (request: middy.Request): Promise<undefined | string> => { |
| 42 | + * // If the request is a GET, return early (as an example) |
| 43 | + * if (request.event.httpMethod === 'GET') { |
| 44 | + * // Cleanup Powertools resources |
| 45 | + * await cleanupMiddlewares(request); |
| 46 | + * // Then return early |
| 47 | + * return 'GET method not supported'; |
| 48 | + * } |
| 49 | + * }; |
| 50 | + * |
| 51 | + * return { |
| 52 | + * before, |
| 53 | + * }; |
| 54 | + * }; |
| 55 | + * ``` |
| 56 | + * |
| 57 | + * @param request - The Middy request object |
| 58 | + * @param options - An optional object that can be used to pass options to the function |
| 59 | + */ |
| 60 | +const cleanupMiddlewares = async (request: MiddyLikeRequest): Promise<void> => { |
| 61 | + const cleanupFunctionNames = [ |
| 62 | + TRACER_KEY, |
| 63 | + METRICS_KEY, |
| 64 | + LOGGER_KEY, |
| 65 | + IDEMPOTENCY_KEY, |
| 66 | + ]; |
| 67 | + for (const functionName of cleanupFunctionNames) { |
| 68 | + if (Object(request.internal).hasOwnProperty(functionName)) { |
| 69 | + const functionReference = request.internal[functionName]; |
| 70 | + if (isFunction(functionReference)) { |
| 71 | + await functionReference(request); |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | +}; |
| 76 | + |
| 77 | +export { cleanupMiddlewares }; |
0 commit comments