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 +38 -5
- package/lib/express-rate-limit.js +17 -5
- package/package.json +10 -10
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,
|
|
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.
|
|
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(
|
|
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(
|
|
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
|
+
"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.
|
|
37
|
-
"eslint-config-prettier": "^
|
|
38
|
-
"eslint-plugin-prettier": "^
|
|
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": "^
|
|
41
|
-
"mocha": "^
|
|
42
|
-
"prettier": "^2.
|
|
43
|
-
"pretty-quick": "^3.1.
|
|
44
|
-
"sinon": "^
|
|
45
|
-
"supertest": "^6.1.
|
|
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 .",
|