{"id":13464909,"url":"https://github.com/futurestudio/hapi-rate-limitor","last_synced_at":"2025-04-05T16:05:08.072Z","repository":{"id":34186298,"uuid":"140299832","full_name":"futurestudio/hapi-rate-limitor","owner":"futurestudio","description":"A hapi plugin for rate limiting. Simple and easy.","archived":false,"fork":false,"pushed_at":"2025-03-24T08:50:51.000Z","size":523,"stargazers_count":43,"open_issues_count":1,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T15:09:53.336Z","etag":null,"topics":["async-ratelimiter","future-studio-university","hapi","hapi-plugin","hapijs","ioredis","node","nodejs","rate-limit","rate-limiting","rate-limits","redis"],"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/futurestudio.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-09T14:46:29.000Z","updated_at":"2025-03-10T12:36:35.000Z","dependencies_parsed_at":"2024-01-16T05:41:06.306Z","dependency_job_id":"1c7cde6c-9645-426f-bd8f-5e1a6845d177","html_url":"https://github.com/futurestudio/hapi-rate-limitor","commit_stats":{"total_commits":456,"total_committers":11,"mean_commits":41.45454545454545,"dds":0.4320175438596491,"last_synced_commit":"941a0932ac3e2a7d06ad36a74d990cbf4b7b899f"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futurestudio%2Fhapi-rate-limitor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futurestudio%2Fhapi-rate-limitor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futurestudio%2Fhapi-rate-limitor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futurestudio%2Fhapi-rate-limitor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/futurestudio","download_url":"https://codeload.github.com/futurestudio/hapi-rate-limitor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247361615,"owners_count":20926642,"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":["async-ratelimiter","future-studio-university","hapi","hapi-plugin","hapijs","ioredis","node","nodejs","rate-limit","rate-limiting","rate-limits","redis"],"created_at":"2024-07-31T14:00:52.609Z","updated_at":"2025-04-05T16:05:08.024Z","avatar_url":"https://github.com/futurestudio.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/futurestudio/hapi-rate-limitor/blob/master/media/hapi-rate-limitor.png?raw=true\" alt=\"hapi-rate-limitor logo\" width=\"471\" style=\"max-width:100%;\"\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n\n  \u003cp\u003e\n    Solid and easy to use rate limiting for hapi.\n  \u003c/p\u003e\n  \u003cbr/\u003e\n  \u003cp\u003e\n    \u003ca href=\"#installation\"\u003e\u003cstrong\u003eInstallation\u003c/strong\u003e\u003c/a\u003e ·\n    \u003ca href=\"#usage\"\u003e\u003cstrong\u003eUsage\u003c/strong\u003e\u003c/a\u003e ·\n    \u003ca href=\"#plugin-options\"\u003e\u003cstrong\u003ePlugin Options\u003c/strong\u003e\u003c/a\u003e ·\n    \u003ca href=\"#route-options\"\u003e\u003cstrong\u003eRoute Options\u003c/strong\u003e\u003c/a\u003e ·\n    \u003ca href=\"#response-headers\"\u003e\u003cstrong\u003eResponse Headers\u003c/strong\u003e\u003c/a\u003e\n  \u003c/p\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://travis-ci.org/futurestudio/hapi-rate-limitor\"\u003e\u003cimg src=\"https://travis-ci.org/futurestudio/hapi-rate-limitor.svg?branch=master\" alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://snyk.io/test/github/futurestudio/hapi-rate-limitor\"\u003e\u003cimg src=\"https://snyk.io/test/github/futurestudio/hapi-rate-limitor/badge.svg\" alt=\"Known Vulnerabilities\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/hapi-rate-limitor\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/hapi-rate-limitor.svg\" alt=\"Latest Version\"\u003e\u003c/a\u003e\n      \u003ca href=\"https://www.npmjs.com/package/hapi-rate-limitor\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/hapi-rate-limitor.svg\" alt=\"Total downloads\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n  \u003cp\u003e\n    \u003cem\u003eFollow \u003ca href=\"http://twitter.com/marcuspoehls\"\u003e@marcuspoehls\u003c/a\u003e for updates!\u003c/em\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n------\n\n\u003cp align=\"center\"\u003e\u003csup\u003eThe \u003ca href=\"https://futurestud.io\"\u003eFuture Studio University\u003c/a\u003e supports development of this hapi plugin 🚀\u003c/sup\u003e\n\u003cbr\u003e\u003cb\u003e\nJoin the \u003ca href=\"https://futurestud.io/university\"\u003eFuture Studio University and Skyrocket in Node.js\u003c/a\u003e\u003c/b\u003e\n\u003c/p\u003e\n\n------\n\n\n## Introduction\nA hapi plugin to prevent brute-force attacks in your app. The rate limiter uses [Redis](https://redis.io/) to store rate-limit related data.\n\n`hapi-rate-limitor` is built on top of these solid and awesome projects:\n\n- [async-ratelimiter](https://github.com/microlinkhq/async-ratelimiter)\n- [ioredis](https://github.com/luin/ioredis)\n- [request-ip](https://github.com/pbojinov/request-ip)\n\nEach package solves its own problem perfectly. `hapi-rate-limitor` composes the solutions of each problem to a solid rate limit plugin for hapi.\n\n\n## Requirements\n\u003e **hapi v19 (or later)** and **Node.js v12 (or newer)**\n\nThis plugin requires **hapi v19** (or later) and **Node.js v12 or newer**.\n\n\n### Compatibility\n| Major Release | [hapi.js](https://github.com/hapijs/hapi) version | Node.js version |\n| --- | --- | --- |\n| `v3` | `\u003e=17 hapi` | `\u003e=12` |\n| `v2` | `\u003e=17 hapi` | `\u003e=8` |\n\n\n## Installation\nAdd `hapi-rate-limitor` as a dependency to your project:\n\n```bash\nnpm i hapi-rate-limitor\n```\n\n\n### Using hapi v18 or lower?\nUse the `2.x` release line:\n\n```bash\nnpm i hapi-rate-limitor@2\n```\n\n\n## Usage\nThe most straight forward to use `hapi-rate-limitor` is to register it to your hapi server.\n\nThis will use the default configurations of [`async-ratelimiter`](https://github.com/microlinkhq/async-ratelimiter#api) and [ioredis](https://github.com/luin/ioredis/blob/master/API.md).\n\n```js\nawait server.register({\n  plugin: require('hapi-rate-limitor')\n})\n\n// went smooth like chocolate with default settings :)\n```\n\n\n## Plugin Options\nCustomize the plugin’s default configuration with the following options:\n\n- **`max`**: Integer, default: `60`\n  - the maximum number of requests allowed in a `duration`\n- **`duration`**: Integer, default: `60000` (1 minute)\n  - the lifetime window keeping records of a request in milliseconds\n- **`namespace`**: String, default: `'hapi-rate-limitor'`\n  - the used prefix to create the rate limit identifier before storing the data\n- **`redis`**: Object, default: `undefined`\n  - the `redis` configuration property will be passed through to `ioredis` creating your custom Redis client\n- **`extensionPoint`**: String, default: `'onPostAuth'`\n  - the [request lifecycle extension point](https://futurestud.io/downloads/hapi/request-lifecycle) for rate limiting\n- **`userAttribute`**: String, default: `'id'`\n  - the property name identifying a user (credentials) for [dynamic rate limits](https://github.com/futurestudio/hapi-rate-limitor#dynamic-rate-limits). This option is used to access the value from `request.auth.credentials`.\n- **`userLimitAttribute`**: String, default: `'rateLimit'`\n  - the property name identifying the rate limit value on [dynamic rate limit](https://github.com/futurestudio/hapi-rate-limitor#dynamic-rate-limits). This option is used to access the value from `request.auth.credentials`.\n- **`view`**: String, default: `undefined`\n  - view path to render the view instead of throwing an error (this uses `h.view(yourView, { total, remaining, reset }).code(429)`)\n- **`enabled`**: Boolean, default: `true`\n  - a shortcut to enable or disable the plugin, e.g. when running tests\n- **`skip`**: Function, default: `() =\u003e false`\n  - an async function with the signature `async (request)` to determine whether to skip rate limiting for a given request. The `skip` function retrieves the incoming request as the only argument\n- **`ipWhitelist`**: Array, default: `[]`\n  - an array of whitelisted IP addresses that won’t be rate-limited. Requests from such IPs proceed the request lifecycle. Notice that the related responses won’t contain rate limit headers.\n- **`getIp`**: Function, default: `undefined`\n  - an async function with the signature `async (request)` to manually determine the requesting IP address. This is helpful if your load balancer provides the client IP address as the last item in the list of forwarded addresses (e.g. Heroku and AWS ELB)\n- **`emitter`**: Object, default: `server.events`\n  - an event emitter instance used to emit the [rate-limitting events](https://github.com/futurestudio/hapi-rate-limitor#events)\n\nAll other options are directly passed through to [async-ratelimiter](https://github.com/microlinkhq/async-ratelimiter#api).\n\n```js\nawait server.register({\n  plugin: require('hapi-rate-limitor'),\n  options: {\n    redis: {\n      port: 6379,\n      host: '127.0.0.1'\n    },\n    extensionPoint: 'onPreAuth',\n    namespace: 'hapi-rate-limitor',\n    max: 2,                                     // a maximum of 2 requests\n    duration: 1000,                              // per second (the value is in milliseconds),\n    userAttribute: 'id',\n    userLimitAttribute: 'rateLimit',\n    view: 'rate-limit-exceeded',                // render this view when the rate limit exceeded\n    enabled: true,\n    skip: async (request) =\u003e {\n      return request.path.includes('/admin')    // example: disable rate limiting for the admin panel\n    },\n    ipWhitelist: ['1.1.1.1'],                   // list of IP addresses skipping rate limiting\n    getIp: async (request) =\u003e {                 // manually determine the requesting IP address\n      const ips = request.headers['x-forwarded-for'].split(',')\n\n      return ips[ips.length - 1]\n    },\n    emitter: yourEventEmitter,                  // your event emitter instance\n  }\n})\n\n// went smooth like chocolate :)\n```\n\nYou can also use a Redis connection string.\n\n```js\nawait server.register({\n  plugin: require('hapi-rate-limitor'),\n  options: {\n    redis: 'redis://lolipop:SOME_PASSWORD@dokku-redis-lolipop:6379',\n    extensionPoint: 'onPreAuth',\n    namespace: 'hapi-rate-limitor'\n    // ... etc\n  }\n})\n\n// went smooth like chocolate :)\n```\n\nPlease check the [async-ratelimiter API](https://github.com/microlinkhq/async-ratelimiter#api) for all options.\n\n\n### Events\n`hapi-rate-limitor` dispatches the following three events in the rate-limiting lifecycle:\n\n- `rate-limit:attempt`: before rate-limiting the request\n- `rate-limit:in-quota`: after rate-limiting and only if the request’s limit is in the quota\n- `rate-limit:exceeded`: after rate-limiting and only if the request’s quota is exceeded\n\nEach event listener receives the related request as the only parameter. Here’s a sample listener:\n\n```js\n\nemitter.on('rate-limit:exceeded', request =\u003e {\n  // handle rate-limiting exceeded\n})\n```\n\nYou can pass your own event `emitter` instance as a config property while registering the `hapi-rate-limitor` plugin to your hapi server. By default, `hapi-rate-limitor` uses hapi’s server as an event emitter.\n\n```js\nconst EventEmitter = require('events')\n\nconst myEmitter = new EventEmitter()\n\nawait server.register({\n  plugin: require('hapi-rate-limitor'),\n  options: {\n    emitter: myEmitter\n\n    // … other plugin options\n  }\n})\n```\n\n\n## Route Options\nCustomize the plugin’s default configuration on routes. A use case for this is a login route where you want to reduce the request limit even lower than the default limit.\n\nOn routes, `hapi-rate-limitor` respects all options related to rate limiting. Precisely, all options that [async-ratelimiter](https://github.com/microlinkhq/async-ratelimiter#api) supports. It does not accept Redis connection options or identifiers for dynamic rate limiting.\n\nAll other options are directly passed through to [async-ratelimiter](https://github.com/microlinkhq/async-ratelimiter#api).\n\n```js\nawait server.register({\n  plugin: require('hapi-rate-limitor'),\n  options: {\n    redis: {\n      port: 6379,\n      host: '127.0.0.1'\n    },\n    namespace: 'hapi-rate-limitor',\n    max: 60,             // a maximum of 60 requests\n    duration: 60 * 1000, // per minute (the value is in milliseconds)\n  }\n})\n\nawait server.route({\n  method: 'POST',\n  path: '/login',\n  options: {\n    handler: () {\n      // do the login handling\n    },\n    plugins: {\n      'hapi-rate-limitor': {\n        max: 5,              // a maximum of 5 requests\n        duration: 60 * 1000, // per minute\n        enabled: false       // but it’s actually not enabled ;-)\n      }\n    }\n  }\n})\n\n// went smooth like chocolate :)\n```\n\nPlease check the [async-ratelimiter API](https://github.com/microlinkhq/async-ratelimiter#api) for all options.\n\n\n## Dynamic Rate Limits\nTo make use of user-specific rate limits, you need to configure the `userAttribute` and `userLimitAttribute` attributes in the `hapi-rate-limitor` options.\n\nThese attributes are used to determine the rate limit for an authenticated user. The `userAttribute` is the property name that uniquely identifies a user. The `userLimitAttribute` is the property name that contains the rate limit value.\n\n```js\nawait server.register({\n  plugin: require('hapi-rate-limitor'),\n  options: {\n    userAttribute: 'id',\n    userLimitAttribute: 'rateLimit',\n    max: 500,                          // a maximum of 500 requests (default is 2500)\n    duration: 60 * 60 * 1000           // per hour (the value is in milliseconds)\n    // … other plugin options\n  }\n})\n```\n\nThis will calculate the maximum requests individually for each authenticated user based on the user’s `id` and `'rateLimit'` attributes. Imagine the following user object as an authenticated user:\n\n```js\n/**\n * the authenticated user object may contain a custom rate limit attribute.\n * In this case, it’s called \"rateLimit\".\n */\nrequest.auth.credentials = {\n  id: 'custom-uuid',\n  rateLimit: 1750,\n  name: 'Marcus'\n  // … further attributes\n}\n```\n\nFor this specific user, the maximum amount of requests is `1750` per hour (and not the plugin’s default `500`).\n\n`hapi-rate-limitor` uses the plugin’s limit if the request is unauthenticated or `request.auth.credentials` doesn’t contain a rate-limit-related attribute.\n\n\n## Response Headers\nThe plugin sets the following response headers:\n\n- `X-Rate-Limit-Limit`: total request limit (`max`) within `duration`\n- `X-Rate-Limit-Remaining`: remaining quota until reset\n- `X-Rate-Limit-Reset`: time since epoch in seconds that the rate limiting period will end\n\n\n## Feature Requests\nDo you miss a feature? Please don’t hesitate to\n[create an issue](https://github.com/futurestudio/hapi-rate-limitor/issues) with a short description of your desired addition to this plugin.\n\n\n## Links \u0026 Resources\n\n- [hapi tutorial series](https://futurestud.io/tutorials/hapi-get-your-server-up-and-running) with 100+ tutorials\n\n\n## Contributing\n\n1.  Create a fork\n2.  Create your feature branch: `git checkout -b my-feature`\n3.  Commit your changes: `git commit -am 'Add some feature'`\n4.  Push to the branch: `git push origin my-new-feature`\n5.  Submit a pull request 🚀\n\n\n## License\n\nMIT © [Future Studio](https://futurestud.io)\n\n---\n\n\u003e [futurestud.io](https://futurestud.io) \u0026nbsp;\u0026middot;\u0026nbsp;\n\u003e GitHub [@futurestudio](https://github.com/futurestudio/) \u0026nbsp;\u0026middot;\u0026nbsp;\n\u003e Twitter [@futurestud_io](https://twitter.com/futurestud_io)\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturestudio%2Fhapi-rate-limitor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuturestudio%2Fhapi-rate-limitor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturestudio%2Fhapi-rate-limitor/lists"}