{"id":13716340,"url":"https://github.com/mhamann/micro-mw","last_synced_at":"2025-04-14T09:14:49.891Z","repository":{"id":33945006,"uuid":"163798310","full_name":"mhamann/micro-mw","owner":"mhamann","description":"a simple helper to add middleware to your zeit/micro or Now 2.0 functions","archived":false,"fork":false,"pushed_at":"2023-01-03T15:48:39.000Z","size":543,"stargazers_count":21,"open_issues_count":9,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-14T09:14:39.647Z","etag":null,"topics":["micro","nodejs","zeit-now"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/mhamann.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-02T05:36:18.000Z","updated_at":"2022-07-22T19:12:07.000Z","dependencies_parsed_at":"2023-01-15T03:31:25.751Z","dependency_job_id":null,"html_url":"https://github.com/mhamann/micro-mw","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhamann%2Fmicro-mw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhamann%2Fmicro-mw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhamann%2Fmicro-mw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhamann%2Fmicro-mw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhamann","download_url":"https://codeload.github.com/mhamann/micro-mw/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248852183,"owners_count":21171842,"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":["micro","nodejs","zeit-now"],"created_at":"2024-08-03T00:01:09.556Z","updated_at":"2025-04-14T09:14:49.866Z","avatar_url":"https://github.com/mhamann.png","language":"JavaScript","funding_links":[],"categories":["Modules","JavaScript"],"sub_categories":["Middlewares"],"readme":"[![Build Status](https://travis-ci.org/mhamann/micro-mw.svg?branch=master)](https://travis-ci.org/mhamann/micro-mw)\n\n# micro-mw\n\n\u003e a simple helper to add middleware to your zeit/micro or Now 2.0 functions.\n\nThis is a set of simple helpers to create and apply middleware to your functions \nusing either [Zeit](https://zeit.co/)'s [micro](https://github.com/zeit/micro) framework\nor Zeit Now 2.0 serverless functions.\n\nThe entire runtime is less than 100 lines long and depends only on `micro` itself.\n\n## Install\n\nInstall with [npm](https://www.npmjs.com/)\n\n```sh\n$ npm i micro-mw\n```\n\nmicro-mw requires Node.js v8.0.0 or higher.\n\n## Concepts and usage\n\nmicro-mw operates in similar fashion to that of other JS frameworks (e.g. Express, Hapi).\nIn this case, when writing request handlers, middleware needs to be applied to the target\nfunction via `applyMiddleware()`.\n\nThe most typical usage would looke something like:\n\n```js\nconst { applyMiddleware } = require('micro-mw');\n\nmodule.exports = applyMiddleware([ middlewareFn1, middlewareFn2 ], (req, res) =\u003e {\n  // Normal request / response handling logic here\n});\n```\n\n### Sets\nOften, the same middleware needs to be applied to most request handlers within an application\nor set of serverless functions. For those situations, middleware can be pre-registered as a\nlogical \"set\" and then applied to each function via `applyMiddleware()`.\n\nRegistering a set is as simple as giving it a name and passing in references to the middleware\nfunctions that need to be called.\n\n```js\nconst { createSet } = require('micro-mw');\n\ncreateSet('my-route-mw', [ middlewareFn1, middlewareFn2 ]);\n```\n\nThen just use the middleware like this:\n\n```js\nconst { applyMiddleware } = require('micro-mw');\n\nmodule.exports = applyMiddleware('my-route-mw', (req, res) =\u003e {\n  // Normal request / response handling logic here\n});\n```\n\n#### Default set / middleware\nIf you want to apply a set of middleware to all routes automatically (unless otherwise specified),\nyou can define a set of default middleware by using the special keyword `default`:\n\n```js\nconst { createSet } = require('micro-mw');\n\ncreateSet('default', [ middlewareFn1, middlewareFn2 ]);\n```\n\nThen, when creating a route handler, don't specify any middleware at all:\n\n```js\nconst { applyMiddleware } = require('micro-mw');\n\nmodule.exports = applyMiddleware((req, res) =\u003e {\n  // Normal request / response handling logic here\n});\n```\n\n#### Set references\nOften, the default middleware is enough for most functions, but occasionally, there\nis a need to include other middleware in the request flow. For example, you might\nwant to include the default authorization middleware on all requests, but only need\ndatabase init logic in certain places.\n\nIn this case, micro-mw allows references to pre-defined middleware sets anywhere that\na middleware function could be specified.\n\nHere are a couple of different ways this feature could be used:\n\n- Reference one set from another\n    ```\n    const { createSet } = require('micro-mw');\n    \n    createSet('auth', [ authUserMw, getProfileMw, checkScopesMw ]);\n    createSet('db', [ initDbMw ]);\n    \n    createSet('default', [ 'auth', 'db' ]);\n    ```\n\n- Chain sets together\n    ```\n    const { applyMiddleware } = require('micro-mw');\n    \n    module.exports = applyMiddleware([ 'db', 'auth', myCustomMwFn ], (req, res) =\u003e {\n      // Normal route logic\n    });\n    ```\n\nWhenever micro-mw encounters a string where a middleware function was expected, it\nwill automatically assume that it is a set reference. Order is important here, as\nthe referenced set will replace the string pointer in that exact location within\nthe array.\n\nIf a referenced set doesn't exist, a runtime error will occur and will be processed\nby the default error handler.\n\n## Error handling\nBy default, micro-mw will catch all sync and async errors that occur within a\nmiddleware or route handler and return a response to the client.\n\nTo override this, simply create a set called `errorHandler` and pass in one or\nmore middleware functions that will be triggered in the case that an error is\nthrown. Be sure to read [creating error middleware](#creating-error-middleware)\nprior to writing your custom error handlers.\n\nIf not overridden, the default error handler will look for the following properties\non the error object:\n\n- **err.statusCode**: The numeric HTTP status code to send to the client. *(default: 500)*\n- **err.body**: The content to set as the response body. This could be a string, object, etc.\n  If a body isn't provided, the value of `err.message` will be used instead.\n- **err.headers**: An optional JS object containing keys and values that should be added as\n  HTTP headers in the response.\n\nAdditionally, the error handler will output the status code, request method and path, and the \nerror stack trace to the logs via a call to `console.error`.\n\nYou can turn this off or provide your own logging function if desired. Simply override\nthe internal error handler like this:\n\n```js\nconst { createSet, errorHandler } = require('micro-mw');\n\ncreateSet('errorHandler', [ errorHandler({ logErrors: true, logger: myLoggerObj }) ]);\n```\n\n*Note: Any custom logging object must provide an `error` function, as the handler will\ncall it like: `logger.error(msg)`.*\n\n\n## Writing middleware\nWriting middleware that is consumable by micro-mw is really no different than writing\na normal request handler. micro-mw uses async/await in order to handle synchronous\nand asyncrhonous middleware in the same manner.\n\nA typical middleware function looks like this:\n\n```js\nasync function myMiddleware(req, res) {\n  // Do some action based on the request\n  let someObj = async requestPromise(url, { json: true });\n  req.someObj = someObj;\n}\n```\n\nThen use it per the patterns mentioned above. For example:\n\n```js\nconst { applyMiddleware } = require('micro-mw');\n\nmodule.exports = applyMiddleware([ myMiddleware ], (req, res) {\n  // Typical request handling\n});\n```\n\nThat's it!\n\nYou can, of course, do much more complicated things than this.\n\n### Creating error handling middleware\nError handling middleware is almost exactly like \"normal\" middleware, but make\nnote of a few key differences:\n\n- The thrown error will be passed into the middleware function as a third param,\n  i.e. `(req, res, err) =\u003e { ... }`\n\n- The error handler is responsible for sending a response to the client.\n\n- Error handlers should typically avoid throwing errors themselves, as that will\n  likely result in no response being sent to the client.\n\n### Halting request execution\nThere may be occasions during the lifecycle of a request, where middleware needs\nto send a response early. An example of this scenario might be when using CORS\nand responding to an `OPTIONS` request from a browser. In this case, the CORS\nmiddleware may send a response prior to all of the middleware or even the request\nhandler being run.\n\nIf the remaining middleware and handlers run, an exception may be thrown when an\nattempt to send another response occurs.\n\nThe `stopRequest` function is provided for a middleware function to signal that a\nresponse has been sent and that any remaining steps in the request should be canceled.\n\nConsider the following sample:\n\n```js\nconst { applyMiddleware, stopRequest } = require('micro-mw');\n\nfunction middlewareFn1(req, res) {\n  // Send a response early\n  ...\n  stopRequest(req);\n}\n\nmodule.exports = applyMiddleware([ middlewareFn1, middlewareFn2 ], (req, res) =\u003e {\n  // Normal request / response handling logic here\n});\n```\n\nIn this scenario, `middlewareFn1` will run, but by calling `stopRequest(req)`, the\nremaining handlers (i.e. `middlewareFn2` and the normal request/response handler)\nwill not be called.\n\n## Contributing\n\nPull requests and stars are always welcome. For bugs and feature requests, \n[please create an issue](https://github.com/mhamann/micro-mw/issues)\n\n## Author\n\n**Matt Hamann**\n\n* [github/mhamann](https://github.com/mhamann)\n* [twitter/mhamann](http://twitter.com/mhamann)\n\nThanks also to [Mathias Karstädt](https://github.com/webmatze) for some inspiration\nin his work on [micro-middleware](https://github.com/webmatze/micro-middleware).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhamann%2Fmicro-mw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhamann%2Fmicro-mw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhamann%2Fmicro-mw/lists"}