{"_id":"express-throttle","_rev":"14-80b237c56b8b4e0214a86d27f2e95f82","name":"express-throttle","description":"Request throttling middleware for Express","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.0":{"name":"express-throttle","version":"0.1.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tape test/*.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"1c0442a5e7269c0666b6675a491761b4d8b3e59d","_id":"express-throttle@0.1.0","_shasum":"2f0aeea6bba15963d4c5189273e8debbf8040c2a","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"2f0aeea6bba15963d4c5189273e8debbf8040c2a","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-0.1.0.tgz","integrity":"sha512-1LjKtE24mKrg5QFCg+yF0lK8fQbPYF2cjDCHkcZsEOssMFfmPwFkJBuLNRXPQkPTAW08/q7JYZt03uMj0tKWpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGo5dDy1ktzpz5qgBNNVL3OFXJT8xL1SlJ04QPCImpEwAiBBpU+KrcFAAwUr2aJ/fld7S92hhQIj6M3KBP/t7WuGgg=="}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/express-throttle-0.1.0.tgz_1467797760630_0.0908931065350771"}},"1.0.0":{"name":"express-throttle","version":"1.0.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tape test/*.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"24af0fb675efca49782b547cb66e638b73ee697b","_id":"express-throttle@1.0.0","_shasum":"c7c1b2412b664e86fb6afb0bd23c52184ce0f352","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"c7c1b2412b664e86fb6afb0bd23c52184ce0f352","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.0.0.tgz","integrity":"sha512-ufONhTx4y5kEw4p1SMPw8fOWd3aASfk6Evn845tJubWne312iMp+XXrb/WI5fRUuLYjTYsPq4qmFNBQvMFwCoA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDv0E+m+kjamXf5C87cjwIGQ3n44EUt8+Wbh+jBSRVZlAIhAN3S44ooOL50wdXOmqVuzLKQMG29blcKwQ+6EpnSeZ/n"}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/express-throttle-1.0.0.tgz_1467881056850_0.3680907948873937"}},"1.0.1":{"name":"express-throttle","version":"1.0.1","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tape test/*.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"425946d1685e6549ebfdb2e3568318f74e8009d3","_id":"express-throttle@1.0.1","_shasum":"e7dd2afe0895c6dc9d261940671d86f220313b93","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"e7dd2afe0895c6dc9d261940671d86f220313b93","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.0.1.tgz","integrity":"sha512-Ilg98mvOY0IJ5wDpM+J6nvdgKwFDPcQ5c0MbbI79kr5HyDwqULafzGpUxLumxU2ihdRp5lk2NBDP0LvoGFMluQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZ/vHOcvBkYQ8coDR6wxpRF+1d0hQpZkzz5HUubVxT1wIhAP380u4STtxdZcYgBYGW9bqUQDwcVnzg6TERHm/Ci/xn"}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/express-throttle-1.0.1.tgz_1467882166281_0.8052803182508796"}},"1.1.0":{"name":"express-throttle","version":"1.1.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"istanbul cover test/throttle.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","istanbul":"^0.4.4","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"27209a0a26a92cb2a22cf2bba13b6f78eda7ee24","_id":"express-throttle@1.1.0","_shasum":"dbbbd4b1969bc302c84ce68c9d8444b6cdf1d0dd","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"dbbbd4b1969bc302c84ce68c9d8444b6cdf1d0dd","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.1.0.tgz","integrity":"sha512-B1tzhK5BYGujsQZgTHrRAvfvCczlMZtcOAaEp+dyYPnrmuvco+kn28uwnJKCoeigjTYK3/Jg+3VfAxQoU02WLA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBS/gKgIfrGFSa7gxlswXAZrOGjLT37pSeMydJBvXHaVAiAcg2yacLffPRYaybJnMc3QpBgQ3KiAlV+D7tIzjK6keQ=="}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/express-throttle-1.1.0.tgz_1468143633549_0.6350247084628791"}},"1.1.1":{"name":"express-throttle","version":"1.1.1","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"istanbul cover test/throttle.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","istanbul":"^0.4.4","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"568ae7659cc2b7314fff5f571969204e5c389587","_id":"express-throttle@1.1.1","_shasum":"5584d330e773040d3503fb91e8e38d2cdc63215b","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"5584d330e773040d3503fb91e8e38d2cdc63215b","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.1.1.tgz","integrity":"sha512-UTeA91+GOQ5gxcydqK3z7Ugb2QQ2FzzBninT7HL3cFisQj8L+Qb+FYYKNi6IM/9v8lPys6xLyisxPzT2CaZBew==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDXqUZqsm46Wg+VAuf7GlXCBpP+fZoM1LlkgA19Ku4fmAIgQiViiiAvQOvFB+r5ROOvuqGf4jBcXnaWqs+03Kf4g/s="}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/express-throttle-1.1.1.tgz_1468187366078_0.692527137696743"}},"1.2.0":{"name":"express-throttle","version":"1.2.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"istanbul cover test/throttle.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","istanbul":"^0.4.4","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"7993ce1a3af7506f933d7319fd07da560a0010f7","_id":"express-throttle@1.2.0","_shasum":"7e74b060d9c7a95354f054d69615d985157d1dbb","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"7e74b060d9c7a95354f054d69615d985157d1dbb","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.2.0.tgz","integrity":"sha512-DI8bPx2+nZvCHyh8jkCkFJdHMDSGoLKU6aS3q9Tj0u/zqt7SSGp89RIChL5xpEXZyfykb/qq+hWDiAZSV5sU0w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCni2aKQ0a0WHxN9zEzuRJs7dpRqoXmTXNaE78NvgkbiAIgYOMONk03t2bqzQDLHunMUdnJCxoZWqn1oJaRx76gsak="}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/express-throttle-1.2.0.tgz_1468229833100_0.23791863885708153"}},"1.3.0":{"name":"express-throttle","version":"1.3.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"istanbul cover test/throttle.js","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","istanbul":"^0.4.4","supertest":"^1.2.0","tape":"^4.6.0"},"gitHead":"cbae7054a9fab60eb560943aad075d41bc56ee3b","_id":"express-throttle@1.3.0","_shasum":"decbf7ec32c5edf47a695afb3c8908b724251d2d","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"decbf7ec32c5edf47a695afb3c8908b724251d2d","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.3.0.tgz","integrity":"sha512-di8wYd6dSrM/p6zUNQcls6xH5AIQ0hhWB1QY9jsbM2RmowoZO/nVXdL2x99MJp8DPKj6xfKDAo2aRZyqaRIR/Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWXbEYhLHI55dQP5jd/ihsDDICQx9AyxnLc3jQNxBv/gIhANCy/RHZcrSuRY8er/1NeHkOT20W4aa6n3wuKATQvnz0"}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/express-throttle-1.3.0.tgz_1468266652199_0.2009276479948312"}},"1.3.2":{"name":"express-throttle","version":"1.3.2","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tap test/*.js --coverage","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tap":"^6.1.1"},"gitHead":"80987c47646ffbe590947cdacefc653926f2adcd","_id":"express-throttle@1.3.2","_shasum":"6cded9a43f70ef45e047b900f11eebd48eddff76","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"6cded9a43f70ef45e047b900f11eebd48eddff76","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.3.2.tgz","integrity":"sha512-lGZh3PxLvMtcSWxsx300p5Lz4KEAvkFywdWt6o3+ozTN/K5YnDe2kPUcZaDhZEWo96hgNfH2vxxy7gBr+6rYMg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD3GGKL43N62AakoK8Kc9pVR/vhFcwf9MKJqhlQ//OmvQIhAOfYUVHrVP52V9WiS3em7YdO3WSkp4fJVLVJke8OQY92"}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/express-throttle-1.3.2.tgz_1468325584685_0.3400633046403527"}},"1.4.0":{"name":"express-throttle","version":"1.4.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tap test/*.unit.js --coverage","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tap":"^6.1.1"},"gitHead":"3c83b382f12d64d86df9d672c7e4d3fa38844058","_id":"express-throttle@1.4.0","_shasum":"28b076952645dcf817bbeec4a1d6e476dbecd69b","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"28b076952645dcf817bbeec4a1d6e476dbecd69b","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-1.4.0.tgz","integrity":"sha512-U6udnS9Unu3lToBiRwmiQeIKMNaXozClKMM6nrYrtfrzR8Sfpn2nNrQfhXnKuaQ6q93rs2YaHkYvOHYpvPjIOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH/1Tquhstqsw0C10wf81WhmkCb3RPP3liFVJmf9Wt1oAiB9nLoF4JFGKr7Uz61vZhoD9OSbRv3TYv7qMN0PYTsk9A=="}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/express-throttle-1.4.0.tgz_1468411015630_0.9840155420824885"}},"2.0.0":{"name":"express-throttle","version":"2.0.0","description":"Request throttling middleware for Express","main":"index.js","scripts":{"test":"tap test/*.unit.js --coverage","lint":"eslint lib test"},"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"keywords":["throttle","request","express","middleware"],"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"license":"MIT","bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"homepage":"https://github.com/GlurG/express-throttle#readme","dependencies":{"lru-cache":"^4.0.1"},"devDependencies":{"express":"^4.14.0","supertest":"^1.2.0","tap":"^6.1.1"},"gitHead":"3f417a5e871e3e0439c537c19c31dcee6fa7f271","_id":"express-throttle@2.0.0","_shasum":"371cca348a82ccf2b924379119df7e73c05f6acf","_from":".","_npmVersion":"3.8.6","_nodeVersion":"6.0.0","_npmUser":{"name":"glurg","email":"dont-use-this@email.com"},"dist":{"shasum":"371cca348a82ccf2b924379119df7e73c05f6acf","tarball":"https://registry.npmjs.org/express-throttle/-/express-throttle-2.0.0.tgz","integrity":"sha512-LIQtqMsLfFVgpN2URzcZiRSjF6RoGb2Eq1R6SfLDQEfdeiHNg+SpUfUk92iKVEqE2jVUotfnEga5OEUph7y1Ag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSWpw7vkz/ilV9uUnpqVveP972k/tYqyeBvrJwRcK6QAIhANdHwLIKyfx850USqjLTtsO0vymW1ea0LBd5ImZynDBo"}]},"maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/express-throttle-2.0.0.tgz_1468847839912_0.20795837487094104"}}},"readme":"# express-throttle\r\nRequest throttling middleware for Express framework\r\n\r\n[![npm version](https://badge.fury.io/js/express-throttle.svg)](https://badge.fury.io/js/express-throttle)\r\n[![Build Status](https://travis-ci.org/GlurG/express-throttle.svg?branch=master)](https://travis-ci.org/GlurG/express-throttle)\r\n\r\n## Installation\r\n\r\n```bash\r\n$ npm install express-throttle\r\n```\r\n\r\n## Implementation\r\n\r\nThe throttling is done using the canonical [token bucket](https://en.wikipedia.org/wiki/Token_bucket) algorithm, where tokens are \"refilled\" in a sliding window manner by default (can be configured to fixed time windows). This means that if we a set maximum rate of 10 requests / minute, a client will not be able to send 10 requests 0:59, and 10 more 1:01. However, if the client sends 10 requests at 0:30, he will be able to send a new request at 0:36 (since tokens are refilled continuously 1 every 6 seconds).\r\n\r\n## Limitations\r\n\r\nBy default, throttling data is stored in memory and is thus not shared between multiple processes. If your application is behind a load balancer which distributes traffic among several node processes, then throttling will be applied per process, which is generally not what you want (unless you can ensure that a client always hits the same process). It is possible to customize the storage so that the throttling data gets saved to a shared backend (e.g Redis). However, the current implementation contains a race-condition and will likely fail (erroneously allow/block certain requests) under high load. My plan is to address this shortcoming in future versions.\r\n\r\n**TL;DR** - Use this package in production at your own risk, beware of the limitations.\r\n* If you are running node as single process = you should be fine\r\n* If you are running node as multiple processes = be aware that throttling is done per process\r\n* If you have configured to use an external backend = some requests may erroneously be throttled (or passed through) under high load conditions\r\n\r\n## Examples\r\n\r\n```js\r\nvar express = require(\"express\");\r\nvar throttle = require(\"express-throttle\");\r\n  \r\nvar app = express();\r\n  \r\n// Allow 5 requests at any rate with an average rate of 5/s\r\napp.post(\"/search\", throttle({ \"rate\": \"5/s\" }), function(req, res, next) {\r\n  // ...\r\n});\r\n\r\n// Allow 5 requests at any rate during a fixed time window of 1 sec \r\napp.post(\"/search\", throttle({ \"burst\": 5, \"period\": \"1s\" }), function(req, res, next) {\r\n  // ...\r\n});\r\n```\r\nCombine it with a burst capacity of 10, meaning that the client can make 10 requests at any rate. The burst capacity is \"refilled\" with the specified rate (in this case 5/s).\r\n```js\r\napp.post(\"/search\", throttle({ \"burst\": 10, \"rate\": \"5/s\" }), function(req, res, next) {\r\n  // ...\r\n});\r\n  \r\n// \"Half\" requests are supported as well (1 request every other second)\r\napp.post(\"/search\", throttle({ \"burst\": 5, \"rate\": \"1/2s\" }), function(req, res, next) {\r\n  // ...\r\n});\r\n```\r\nBy default, throttling is done on a per ip-address basis (see [this link](http://expressjs.com/en/api.html#req.ip) about how the ip address is extracted from the request). This can be configured by providing a custom key-function:\r\n```js\r\nvar options = {\r\n  \"burst\": 10,\r\n  \"rate\": \"5/s\",\r\n  \"key\": function(req) {\r\n    return req.session.username;\r\n  }\r\n};\r\n\r\napp.post(\"/search\", throttle(options), function(req, res, next) {\r\n  // ...\r\n});\r\n```\r\nThe \"cost\" per request can also be customized, making it possible to, for example whitelist certain requests:\r\n```js\r\nvar whitelist = [\"ip-1\", \"ip-2\", ...];\r\n  \r\nvar options = {\r\n  \"burst\": 10,\r\n  \"rate\": \"5/s\",\r\n  \"cost\": function(req) {\r\n    var ip_address = req.connection.remoteAddress;\r\n      \r\n    if (whitelist.indexOf(ip_address) >= 0) {\r\n      return 0;\r\n    } else if (req.session.is_privileged_user) {\r\n      return 0.5;\r\n    } else {\r\n      return 1;\r\n    }\r\n  }\r\n};\r\n  \r\napp.post(\"/search\", throttle(options), function(req, res, next) {\r\n  // ...\r\n});\r\n\r\nvar options = {\r\n  \"rate\": \"1/s\",\r\n  \"burst\": 10,\r\n  \"cost\": 2.5 // fixed costs are also supported\r\n};\r\n\r\napp.post(\"/expensive\", throttle(options), function(req, res, next) {\r\n  // ...\r\n});\r\n```\r\nThrottled requests will simply be responded with an empty 429 response. This can be overridden:\r\n```js\r\nvar options = {\r\n  \"burst\": 5\r\n  \"period\": \"1min\",\r\n  \"on_throttled\": function(req, res, next, bucket) {\r\n    // Possible course of actions:\r\n    // 1) Log request\r\n    // 2) Add client ip address to a ban list\r\n    // 3) Send back more information\r\n    res.set(\"X-Rate-Limit-Limit\", 5);\r\n    res.set(\"X-Rate-Limit-Remaining\", 0);\r\n    // bucket.etime = expiration time in Unix epoch ms, only available\r\n    // for fixed time windows\r\n    res.set(\"X-Rate-Limit-Reset\", bucket.etime);\r\n    res.status(503).send(\"System overloaded, try again at a later time.\");\r\n  }\r\n};\r\n```\r\nYou may also customize the response on requests that are passed through:\r\n```js\r\nvar options = {\r\n  \"rate\": \"5/s\",\r\n  \"on_allowed\": function(req, res, next, bucket) {\r\n    res.set(\"X-Rate-Limit-Limit\", 5);\r\n    res.set(\"X-Rate-Limit-Remaining\", bucket.tokens);\r\n  }\r\n}\r\n```\r\nThrottling can be applied across multiple processes. This requires an external storage mechanism which can be configured as follows:\r\n```js\r\nfunction ExternalStorage(connection_settings) {\r\n  // ...\r\n}\r\n\r\n// These methods must be implemented\r\nExternalStorage.prototype.get = function(key, callback) {\r\n  fetch(key, function(bucket) {\r\n    // First argument should be null if no errors occurred\r\n    callback(null, bucket);\r\n  });\r\n}\r\n  \r\nExternalStorage.prototype.set = function(key, bucket, lifetime, callback) {\r\n  save(key, bucket, function(err) {\r\n    // err should be null if no errors occurred\r\n    callback(err); \r\n  });\r\n}\r\n  \r\nvar options = {\r\n  \"rate\": \"5/s\",\r\n  \"store\": new ExternalStorage()\r\n}\r\n  \r\napp.post(\"/search\", throttle(options), function(req, res, next) {\r\n  // ...\r\n});\r\n```\r\n\r\n## Options\r\n\r\n`burst`: The number of requests that can be made at any rate. Defaults to *X* as defined below for rolling windows.\r\n\r\n`rate`: Determines the rate at which the burst quota is \"refilled\". This will control the average number of requests per time unit. Must be specified according to the following format: *X/Yt*\r\n\r\nwhere *X* and *Y* are integers and *t* is the time unit which can be any of the following: `ms, s, sec, m, min, h, hour, d, day`\r\n\r\nE.g `5/s, 180/15min, 1000/d` \r\n\r\n`period`: The duration of the time window after which the entire burst quota is refilled. Must be specified according to the following format: *Y/t*, where *Y* and *t* are defined as above.\r\n\r\nE.g `5s, 15min, 1000d`\r\n\r\n`store`: Custom storage class. Must implement a `get` and `set` method with the following signatures:\r\n```js\r\n// callback in both methods must be called with an error (if any) as first argument\r\n\r\nfunction get(key, callback) {\r\n  fetch(key, function(err, bucket) {\r\n    if (err) callback(err);\r\n    else callback(null, bucket);\r\n  });\r\n}\r\nfunction set(key, bucket, callback) {\r\n  // 'bucket' will be an object with the following structure:\r\n  /*\r\n    {\r\n      \"tokens\": Number, (current number of tokens)\r\n      \"mtime\": Number, (last modification time)\r\n      \"etime\": Number (expiration time, only available for fixed time windows)\r\n    }\r\n  */\r\n  save(key, bucket, function(err) {\r\n    callback(err);\r\n  }\r\n}\r\n```\r\nDefaults to an LRU cache with a maximum of 10000 entries.\r\n\r\n`store_size`: Determines the maximum number of entries for the default in-memory LRU cache. 0 indicates no limit, **not recommended**, since entries in the cache are not expired / cleaned up / garbage collected.\r\n\r\n`key`: Function used to identify clients. It will be called with an [express request object](http://expressjs.com/en/4x/api.html#req). Defaults to:\r\n```js\r\nfunction(req) {\r\n\treturn req.ip; // http://expressjs.com/en/api.html#req.ip\r\n}\r\n```\r\n\r\n`cost`: Number or function used to calculate the cost for a request with an [express request object](http://expressjs.com/en/4x/api.html#req). Defaults to 1.\r\n\r\n`on_allowed`: A function called when the request is passed through with an [express request object](http://expressjs.com/en/4x/api.html#req), [express response object](http://expressjs.com/en/4x/api.html#res), `next` function and a `bucket` object. Defaults to:\r\n```js\r\nfunction(req, res, next, bucket) {\r\n\tnext();\r\n}\r\n``` \r\n\r\n`on_throttled`: A function called when the request is throttled with an [express request object](http://expressjs.com/en/4x/api.html#req), [express response object](http://expressjs.com/en/4x/api.html#res), `next` function and a `bucket` object. Defaults to:\r\n```js\r\nfunction(req, res, next, bucket) {\r\n\tres.status(429).end();\r\n};\r\n```","maintainers":[{"name":"glurg","email":"dont-use-this@email.com"}],"time":{"modified":"2022-06-17T22:42:35.486Z","created":"2016-07-06T09:36:01.576Z","0.1.0":"2016-07-06T09:36:01.576Z","1.0.0":"2016-07-07T08:44:19.107Z","1.0.1":"2016-07-07T09:02:48.770Z","1.1.0":"2016-07-10T09:40:35.818Z","1.1.1":"2016-07-10T21:49:28.300Z","1.2.0":"2016-07-11T09:37:14.665Z","1.3.0":"2016-07-11T19:50:53.719Z","1.3.2":"2016-07-12T12:13:06.414Z","1.4.0":"2016-07-13T11:56:57.537Z","2.0.0":"2016-07-18T13:17:22.159Z"},"homepage":"https://github.com/GlurG/express-throttle#readme","keywords":["throttle","request","express","middleware"],"repository":{"type":"git","url":"git+https://github.com/GlurG/express-throttle.git"},"author":{"name":"Martin Tittenberger","url":"https://github.com/GlurG"},"bugs":{"url":"https://github.com/GlurG/express-throttle/issues"},"license":"MIT","readmeFilename":"README.md","users":{"rocket0191":true,"andreaspizsa":true}}