express-rate-limit 5.3.0 → 5.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,7 @@ Note: this module does not share state with other processes/servers by default.
17
17
  - [Redis Store](https://npmjs.com/package/rate-limit-redis)
18
18
  - [Memcached Store](https://npmjs.org/package/rate-limit-memcached)
19
19
  - [Mongo Store](https://www.npmjs.com/package/rate-limit-mongo)
20
+ - [Precise Memory Store](https://www.npmjs.com/package/precise-memory-rate-limit) - similar to the built-in memory store except that it stores a distinct timestamp for each IP rather than bucketing them together.
20
21
 
21
22
  ### Alternate Rate-limiters
22
23
 
@@ -39,7 +40,7 @@ For an API-only server where the rate-limiter should be applied to all requests:
39
40
  ```js
40
41
  const rateLimit = require("express-rate-limit");
41
42
 
42
- // Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
43
+ // Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB or API Gateway, Nginx, etc)
43
44
  // see https://expressjs.com/en/guide/behind-proxies.html
44
45
  // app.set('trust proxy', 1);
45
46
 
@@ -57,7 +58,7 @@ For a "regular" web server (e.g. anything that uses `express.static()`), where t
57
58
  ```js
58
59
  const rateLimit = require("express-rate-limit");
59
60
 
60
- // Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB, Nginx, etc)
61
+ // Enable if you're behind a reverse proxy (Heroku, Bluemix, AWS ELB or API Gateway, Nginx, etc)
61
62
  // see https://expressjs.com/en/guide/behind-proxies.html
62
63
  // app.set('trust proxy', 1);
63
64
 
@@ -102,6 +103,8 @@ app.post("/create-account", createAccountLimiter, function(req, res) {
102
103
 
103
104
  A `req.rateLimit` property is added to all requests with the `limit`, `current`, and `remaining` number of requests and, if the store provides it, a `resetTime` Date object. These may be used in your application code to take additional actions or inform the user of their status.
104
105
 
106
+ The property name can be configured with the configuration option `requestPropertyName`
107
+
105
108
  ## Configuration options
106
109
 
107
110
  ### max
@@ -112,6 +115,31 @@ May be a number, or a function that returns a number or a promise. If `max` is a
112
115
 
113
116
  Defaults to `5`. Set to `0` to disable.
114
117
 
118
+ Example of using a function:
119
+
120
+ ```js
121
+ const rateLimit = require("express-rate-limit");
122
+
123
+ function isPremium(req) {
124
+ //...
125
+ }
126
+
127
+ const limiter = rateLimit({
128
+ windowMs: 15 * 60 * 1000, // 15 minutes
129
+
130
+ // max could also be an async function or return a promise
131
+ max: function(req, res) {
132
+ if (isPremium(req)) {
133
+ return 10;
134
+ }
135
+ return 5;
136
+ }
137
+ });
138
+
139
+ // apply to all requests
140
+ app.use(limiter);
141
+ ```
142
+
115
143
  ### windowMs
116
144
 
117
145
  Timeframe for which requests are checked/remembered. Also used in the Retry-After header when the limit is reached.
@@ -150,7 +178,7 @@ Defaults to `false`. Behavior and name will likely change in future releases.
150
178
 
151
179
  Function used to generate keys.
152
180
 
153
- Defaults to req.ip:
181
+ Defaults to req.ip, similar to this:
154
182
 
155
183
  ```js
156
184
  function (req /*, res*/) {
@@ -160,14 +188,14 @@ function (req /*, res*/) {
160
188
 
161
189
  ### handler
162
190
 
163
- The function to handle requests once the max limit is exceeded. It receives the request and the response objects. The "next" param is available if you need to pass to the next middleware.
191
+ The function to handle requests once the max limit is exceeded. It receives the request and the response objects. The "next" param is available if you need to pass to the next middleware. Finally, the options param has all of the options that originally passed in when creating the current limiter and the default values for other options.
164
192
 
165
193
  The`req.rateLimit` object has `limit`, `current`, and `remaining` number of requests and, if the store provides it, a `resetTime` Date object.
166
194
 
167
195
  Defaults to:
168
196
 
169
197
  ```js
170
- function (req, res, /*next*/) {
198
+ function (req, res, next, options) {
171
199
  res.status(options.statusCode).send(options.message);
172
200
  }
173
201
  ```
@@ -230,6 +258,11 @@ function (/*req, res*/) {
230
258
  }
231
259
  ```
232
260
 
261
+ ### requestPropertyName
262
+ Parameter to add to `req`-Object.
263
+
264
+ Defaults to `rateLimit`.
265
+
233
266
  ### store
234
267
 
235
268
  The storage to use when persisting rate limit attempts.
@@ -18,15 +18,21 @@ function RateLimit(options) {
18
18
  skipSuccessfulRequests: false, // Do not count successful requests
19
19
  // allows to create custom keys (by default user IP is used)
20
20
  keyGenerator: function (req /*, res*/) {
21
+ if (!req.ip) {
22
+ console.error(
23
+ "express-rate-limit: req.ip is undefined - you can avoid this by providing a custom keyGenerator function, but it may be indicative of a larger issue."
24
+ );
25
+ }
21
26
  return req.ip;
22
27
  },
23
28
  skip: function (/*req, res*/) {
24
29
  return false;
25
30
  },
26
- handler: function (req, res /*, next*/) {
31
+ handler: function (req, res /*, next, optionsUsed*/) {
27
32
  res.status(options.statusCode).send(options.message);
28
33
  },
29
34
  onLimitReached: function (/*req, res, optionsUsed*/) {},
35
+ requestPropertyName: "rateLimit", // Parameter name appended to req object
30
36
  },
31
37
  options
32
38
  );
@@ -74,7 +80,7 @@ function RateLimit(options) {
74
80
 
75
81
  Promise.resolve(maxResult)
76
82
  .then((max) => {
77
- req.rateLimit = {
83
+ req[options.requestPropertyName] = {
78
84
  limit: max,
79
85
  current: current,
80
86
  remaining: Math.max(max - current, 0),
@@ -83,7 +89,10 @@ function RateLimit(options) {
83
89
 
84
90
  if (options.headers && !res.headersSent) {
85
91
  res.setHeader("X-RateLimit-Limit", max);
86
- res.setHeader("X-RateLimit-Remaining", req.rateLimit.remaining);
92
+ res.setHeader(
93
+ "X-RateLimit-Remaining",
94
+ req[options.requestPropertyName].remaining
95
+ );
87
96
  if (resetTime instanceof Date) {
88
97
  // if we have a resetTime, also provide the current date to help avoid issues with incorrect clocks
89
98
  res.setHeader("Date", new Date().toUTCString());
@@ -95,7 +104,10 @@ function RateLimit(options) {
95
104
  }
96
105
  if (options.draft_polli_ratelimit_headers && !res.headersSent) {
97
106
  res.setHeader("RateLimit-Limit", max);
98
- res.setHeader("RateLimit-Remaining", req.rateLimit.remaining);
107
+ res.setHeader(
108
+ "RateLimit-Remaining",
109
+ req[options.requestPropertyName].remaining
110
+ );
99
111
  if (resetTime) {
100
112
  const deltaSeconds = Math.ceil(
101
113
  (resetTime.getTime() - Date.now()) / 1000
@@ -152,7 +164,7 @@ function RateLimit(options) {
152
164
  Math.ceil(options.windowMs / 1000)
153
165
  );
154
166
  }
155
- return options.handler(req, res, next);
167
+ return options.handler(req, res, next, options);
156
168
  }
157
169
 
158
170
  next();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-rate-limit",
3
- "version": "5.3.0",
3
+ "version": "5.5.1",
4
4
  "description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
5
5
  "homepage": "https://github.com/nfriedly/express-rate-limit",
6
6
  "author": {
@@ -33,16 +33,16 @@
33
33
  ],
34
34
  "devDependencies": {
35
35
  "bluebird": "^3.7.2",
36
- "eslint": "^7.19.0",
37
- "eslint-config-prettier": "^7.2.0",
38
- "eslint-plugin-prettier": "^3.3.1",
36
+ "eslint": "^7.32.0",
37
+ "eslint-config-prettier": "^8.3.0",
38
+ "eslint-plugin-prettier": "^4.0.0",
39
39
  "express": "^4.17.1",
40
- "husky": "^4.3.8",
41
- "mocha": "^8.2.1",
42
- "prettier": "^2.2.1",
43
- "pretty-quick": "^3.1.0",
44
- "sinon": "^9.2.4",
45
- "supertest": "^6.1.3"
40
+ "husky": "^7.0.2",
41
+ "mocha": "^9.1.2",
42
+ "prettier": "^2.4.1",
43
+ "pretty-quick": "^3.1.1",
44
+ "sinon": "^11.1.2",
45
+ "supertest": "^6.1.6"
46
46
  },
47
47
  "scripts": {
48
48
  "lint": "eslint .",