{"id":21557376,"url":"https://github.com/dbartholomae/lambda-middleware","last_synced_at":"2025-05-15T18:08:21.550Z","repository":{"id":40546248,"uuid":"236245107","full_name":"dbartholomae/lambda-middleware","owner":"dbartholomae","description":"A collection of middleware for AWS lambda functions.","archived":false,"fork":false,"pushed_at":"2024-10-16T20:48:20.000Z","size":1419,"stargazers_count":154,"open_issues_count":1,"forks_count":18,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-30T10:11:45.844Z","etag":null,"topics":["aws","hacktoberfest","lambda","lambda-middleware","middleware"],"latest_commit_sha":null,"homepage":"https://dbartholomae.github.io/lambda-middleware/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbartholomae.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"dbartholomae"}},"created_at":"2020-01-25T23:41:28.000Z","updated_at":"2025-03-13T20:51:16.000Z","dependencies_parsed_at":"2024-10-29T15:55:02.521Z","dependency_job_id":null,"html_url":"https://github.com/dbartholomae/lambda-middleware","commit_stats":{"total_commits":292,"total_committers":8,"mean_commits":36.5,"dds":0.136986301369863,"last_synced_commit":"91a7ec519906c8ea0edfe7362d4e1425e64df8cd"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbartholomae%2Flambda-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbartholomae%2Flambda-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbartholomae%2Flambda-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbartholomae%2Flambda-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbartholomae","download_url":"https://codeload.github.com/dbartholomae/lambda-middleware/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253534795,"owners_count":21923544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","hacktoberfest","lambda","lambda-middleware","middleware"],"created_at":"2024-11-24T08:12:06.783Z","updated_at":"2025-05-15T18:08:21.524Z","avatar_url":"https://github.com/dbartholomae.png","language":"TypeScript","funding_links":["https://github.com/sponsors/dbartholomae"],"categories":[],"sub_categories":[],"readme":"![@lambda-middleware](assets/lambda-middleware-logo.png)\n\n[![open issues](https://img.shields.io/github/issues-raw/dbartholomae/lambda-middleware.svg)](https://github.com/dbartholomae/lambda-middleware/issues)\n[![debug](https://img.shields.io/badge/debug-blue.svg)](https://github.com/visionmedia/debug#readme)\n[![build status](https://github.com/dbartholomae/lambda-middleware/workflows/.github/workflows/build.yml/badge.svg?branch=main)](https://github.com/dbartholomae/lambda-middleware/actions?query=workflow%3A.github%2Fworkflows%2Fbuild.yml)\n[![codecov](https://codecov.io/gh/dbartholomae/lambda-middleware/branch/main/graph/badge.svg)](https://codecov.io/gh/dbartholomae/lambda-middleware)\n[![CLA assistant](https://cla-assistant.io/readme/badge/dbartholomae/lambda-middleware)](https://cla-assistant.io/dbartholomae/lambda-middleware)\n\nThis monorepo is a collection of middleware for AWS lambda functions.\n\n## Middlewares\n\n* [@lambda-middleware/class-validator](packages/class-validator): A validation middleware for AWS http lambda functions\n  based on class-validator. [![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fclass-validator.svg)](https://npmjs.org/package/@lambda-middleware/class-validator)\n* [@lambda-middleware/compose](packages/compose): A compose function for functional lambda middleware. [![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fcompose.svg)](https://npmjs.org/package/@lambda-middleware/compose)\n* [@lambda-middleware/http-error-handler](packages/http-error-handler): An error handler middleware for AWS http lambda\n  functions.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fhttp-error-handler.svg)](https://npmjs.org/package/@lambda-middleware/http-error-handler)\n* [@lambda-middleware/ie-no-open](packages/ie-no-open): A middleware for adding the download options no-open header to\n  AWS lambdas.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fie-no-open.svg)](https://npmjs.org/package/@lambda-middleware/ie-no-open)\n* [@lambda-middleware/json-serializer](packages/json-serializer): A middleware for AWS http lambda functions to\n  serialize JSON responses.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fjson-serializer.svg)](https://npmjs.org/package/@lambda-middleware/json-serializer)\n* [@lambda-middleware/json-deserializer](packages/json-deserializer): A middleware for AWS http lambda functions to\n  deserialize JSON request bodies.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fjson-deserializer.svg)](https://npmjs.org/package/@lambda-middleware/json-deserializer)\n* [@lambda-middleware/jwt-auth](packages/jwt-auth): A middleware for AWS http lambda functions to verify JWT auth\n  tokens inspired by express-jwt.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fjwt-auth.svg)](https://npmjs.org/package/@lambda-middleware/jwt-auth)\n* [@lambda-middleware/middy-adaptor](packages/middy-adaptor): An adaptor to use middy middleware as functional\n  middleware.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fmiddy-adaptor.svg)](https://npmjs.org/package/@lambda-middleware/middy-adaptor)\n* [@lambda-middleware/no-sniff](packages/no-sniff): A middleware for adding the content type options no-sniff header\n  to AWS lambdas.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fno-sniff.svg)](https://npmjs.org/package/@lambda-middleware/no-sniff)\n* [@lambda-middleware/http-header-normalizer](packages/http-header-normalizer): Middleware for AWS lambdas that\n  normalizes headers to lower-case.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fhttp-header-normalizer.svg)](https://npmjs.org/package/@lambda-middleware/http-header-normalizer)\n* [@lambda-middleware/do-not-wait](packages/do-not-wait): AWS lambda middleware to prevent Lambda from timing out\n  because of processes running after returning a value.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fdo-not-wait.svg)](https://npmjs.org/package/@lambda-middleware/do-not-wait)\n* [@lambda-middleware/cors](packages/cors): AWS lambda middleware for automatically adding CORS headers.[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fcors.svg)](https://npmjs.org/package/@lambda-middleware/cors)\n\n## Other packages\n\nFurthermore there is utility collection available at [@lambda-middleware/utils](packages/utils).[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Futils.svg)](https://npmjs.org/package/@lambda-middleware/utils)\n\n## Usage\n\nEach middleware is a higher-order function that can be wrapped around the handler function.\n\n```typescript\nexport const handler = someMiddleware()(() =\u003e {\n  return {\n    body: '',\n    statusCode: 200\n  }\n})\n```\n\nEach middleware is build as\n```typescript\n(options) =\u003e (handler) =\u003e (event, context) =\u003e Response\n```\n\nThis means that middleware can be composed and piped like any other function with only one parameter (the handler).\nThis library contains [a helper for composing](packages/compose), but [any](https://lodash.com/docs/4.17.15#flowRight)\n[other](https://ramdajs.com/docs/#compose) [implementation](https://github.com/tc39/proposal-pipeline-operator) should\nwork as well.\n\n```typescript\nexport const handler = compose(\n  someMiddleware(),\n  someOtherMiddleware(),\n  aThirdMiddleware()\n)(() =\u003e {\n  return {\n    body: '',\n    statusCode: 200\n  }\n})\n```\n\nThere's a [known issue with TypeScript](https://github.com/microsoft/TypeScript/issues/29904) that pipe and compose functions cannot\ninfer types correctly if the innermost function is generic (in this case the last argument to `compose`).\nIf you use TypeScript in strict mode, you can instead use the `composeHandler` function exported from `@lambda-middleware/compose`:\n\n```typescript\nexport const handler = composeHandler(\n  someMiddleware(),\n  someOtherMiddleware(),\n  aThirdMiddleware(),\n  () =\u003e {\n    return {\n      body: '',\n      statusCode: 200\n    }\n  }\n)\n```\n\nComposing middleware is equivalent to calling it nested:\n```typescript\nexport const handler =\n  someMiddleware()(\n    someOtherMiddleware()(\n      aThirdMiddleware()(() =\u003e {\n        return {\n          body: '',\n          statusCode: 200\n        }\n      })\n    )\n  )\n```\n\nThe order of composition can be relevant. When using a helper to do the composition, check, in which order the functions\nare applied. Most of the time TypeScript should be able to warn you, if the order is wrong.\n\nImagine middleware as an onion around your function: The outermost middleware will get called first before the handler\nstarts, and last after the handler finishes or throws an error. In our example above the order in which middleware gets\nexecuted therefore would be:\n```\nsomeMiddleware\n  someOtherMiddleware\n    aThirdMiddleware\n      the handler\n    aThirdMiddleware\n  someOtherMiddleware\nsomeMiddleware\n```\nThis means that middleware which transforms the input for the handler will be executed top to bottom, while middleware\nthat transforms the response will be called bottom to top.\n\n## Writing your own middleware\n\nIf you want to write your own middleware, check the existing examples and feel free to borrow some of the tests for\ninspiration. The general idea for a middleware is the following:\n```typescript\nconst myMiddleware = (optionsForMyMiddleware) =\u003e (handler) =\u003e async (event, context) =\u003e {\n  try {\n    const modifiedEvent = doSomethingBeforeCallingTheHandler(event)\n    const response = await handler(modifiedEvent, context)\n    const modifiedResponse = doSomethingAfterCallingTheHandler(response)\n    return modifiedResponse\n  } catch (error) {\n    const modifiedError = doSomethingInCaseOfAnError(error)\n    throw modifiedError\n  }\n}\n```\nUsually the same middleware should not need to do something before the handler, after the handler and on error.\nCreating separated middlewares for these cases keeps them more versatile. But cases that require multiple steps are\nsupported as well.\n\nSince the middlewares only uses function composition, TypeScript can offer extensive typing support to let you know\nhow the middleware changed. When adding your own middleware it is recommended to use generics to avoid losing type\ninformation.\n\nInstead of\n```typescript\nconst bodyParser = () =\u003e\n  (handler: PromiseHandler\u003cOmit\u003cAPIGatewayProxyEvent, body\u003e \u0026 { body: object}, APIGatewayProxyResult\u003e): PromiseHandler\u003cAPIGatewayProxyEvent, APIGatewayProxyResult\u003e =\u003e\n  async (event: E, context: Context) =\u003e {\n  return handler({ ...event, body: JSON.parse(event.body) }, context)\n}\n```\nuse\n```typescript\nconst bodyParser = () =\u003e\n  \u003cE extends APIGatewayProxyEvent\u003e(handler: PromiseHandler\u003cOmit\u003cE, body\u003e \u0026 { body: object}, APIGatewayProxyResult\u003e): PromiseHandler\u003cE, APIGatewayProxyResult\u003e =\u003e\n  async (event: E, context: Context) =\u003e {\n  return handler({ ...event, body: JSON.parse(event.body) }, context)\n}\n```\nso that if multiple middlewares change the event, the resulting type will have all changes and not just the latest.\n\n## Contributing\n\nIf you want to contribute to the project, please read our [contributing guidelines](CONTRIBUTING.md) first.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbartholomae%2Flambda-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbartholomae%2Flambda-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbartholomae%2Flambda-middleware/lists"}