mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-04 19:02:38 +00:00
Rate limit /api requests from each IP address
100 requests each 5 minutes.
This commit is contained in:
@@ -116,6 +116,17 @@ const ErrorNavItem = createClass({
|
|||||||
</Nav.item>;
|
</Nav.item>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(HBErrorCode === '55') {
|
||||||
|
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
||||||
|
Oops!
|
||||||
|
<div className='errorContainer' onClick={clearError}>
|
||||||
|
Looks like there are too many requests
|
||||||
|
from this IP address in a short time.
|
||||||
|
Please try again after a few minutes.
|
||||||
|
</div>
|
||||||
|
</Nav.item>;
|
||||||
|
}
|
||||||
|
|
||||||
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
||||||
Oops!
|
Oops!
|
||||||
<div className='errorContainer'>
|
<div className='errorContainer'>
|
||||||
|
|||||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -25,6 +25,7 @@
|
|||||||
"expr-eval": "^2.0.2",
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
|
"express-rate-limit": "^7.4.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "11.2.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@@ -6352,6 +6353,21 @@
|
|||||||
"integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==",
|
"integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/express-rate-limit": {
|
||||||
|
"version": "7.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.0.tgz",
|
||||||
|
"integrity": "sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/express-rate-limit"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": "4 || 5 || ^5.0.0-beta.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/express-static-gzip": {
|
"node_modules/express-static-gzip": {
|
||||||
"version": "2.1.7",
|
"version": "2.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz",
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
"expr-eval": "^2.0.2",
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
|
"express-rate-limit": "^7.4.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "11.2.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const yaml = require('js-yaml');
|
|||||||
const asyncHandler = require('express-async-handler');
|
const asyncHandler = require('express-async-handler');
|
||||||
const { nanoid } = require('nanoid');
|
const { nanoid } = require('nanoid');
|
||||||
const { splitTextStyleAndMetadata } = require('../shared/helpers.js');
|
const { splitTextStyleAndMetadata } = require('../shared/helpers.js');
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
|
||||||
const { DEFAULT_BREW, DEFAULT_BREW_LOAD } = require('./brewDefaults.js');
|
const { DEFAULT_BREW, DEFAULT_BREW_LOAD } = require('./brewDefaults.js');
|
||||||
|
|
||||||
@@ -24,6 +25,16 @@ const isStaticTheme = (renderer, themeName)=>{
|
|||||||
// });
|
// });
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
// Define rate limiter options
|
||||||
|
const rateLimiter = rateLimit({
|
||||||
|
timeWindow : 5 * 60 * 1000, // 5 minutes window
|
||||||
|
max : 100, // limit each IP to 100 requests per timeWindow
|
||||||
|
handler: (req, res, next) => {
|
||||||
|
console.log(`Rate limiting user ${req.account?.username}`);
|
||||||
|
throw { HBErrorCode: '55', status: 429, message: 'Too many requests from this IP, please try again after 5 minutes'};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const MAX_TITLE_LENGTH = 100;
|
const MAX_TITLE_LENGTH = 100;
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
@@ -473,6 +484,7 @@ const api = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
router.use('/api', rateLimiter);
|
||||||
router.use('/api', require('./middleware/check-client-version.js'));
|
router.use('/api', require('./middleware/check-client-version.js'));
|
||||||
router.post('/api', asyncHandler(api.newBrew));
|
router.post('/api', asyncHandler(api.newBrew));
|
||||||
router.put('/api/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
router.put('/api/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
||||||
|
|||||||
Reference in New Issue
Block a user