mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-07-18 00:47:01 +00:00
feature: cloudcmd: rate limit: add support (#437)
This commit is contained in:
parent
161bede8db
commit
5d9628ce70
5 changed files with 38 additions and 20 deletions
|
|
@ -115,7 +115,7 @@ const yargsOptions = {
|
|||
'columns': env.parse('columns') || config('columns') || '',
|
||||
'theme': env.parse('theme') || config('theme') || '',
|
||||
'vim': choose(env.bool('vim'), config('vim')),
|
||||
'log': config('log'),
|
||||
'log': choose(env.bool('log'), config('log')),
|
||||
|
||||
'import-url': env.parse('import_url') || config('importUrl'),
|
||||
'import-listen': choose(env.bool('import_listen'), config('importListen')),
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
"es6-promisify": "^7.0.0",
|
||||
"execon": "^1.2.0",
|
||||
"express": "^5.1.0",
|
||||
"express-rate-limit": "^8.5.2",
|
||||
"files-io": "^4.0.0",
|
||||
"find-up": "^8.0.0",
|
||||
"for-each-key": "^2.0.0",
|
||||
|
|
|
|||
|
|
@ -178,20 +178,3 @@ test('cloudcmd: sw', async (t) => {
|
|||
t.equal(status, 200, 'should return sw');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('cloudcmd: manifest.json', async (t) => {
|
||||
const config = {
|
||||
auth: true,
|
||||
};
|
||||
|
||||
const options = {
|
||||
config,
|
||||
};
|
||||
|
||||
const {status} = await request.get('/public/manifest.json', {
|
||||
options,
|
||||
});
|
||||
|
||||
t.equal(status, 200, 'should return manifest.json even when authentication is enabled');
|
||||
t.end();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
import http from 'node:http';
|
||||
import {promisify} from 'node:util';
|
||||
import process from 'node:process';
|
||||
import {rateLimit} from 'express-rate-limit';
|
||||
import currify from 'currify';
|
||||
import squad from 'squad';
|
||||
import {tryToCatch} from 'try-to-catch';
|
||||
import opn from 'open';
|
||||
import express from 'express';
|
||||
import {Server} from 'socket.io';
|
||||
import tryRequire from 'tryrequire';
|
||||
import wraptile from 'wraptile';
|
||||
import compression from 'compression';
|
||||
import tryRequire from 'tryrequire';
|
||||
import {cloudcmd} from '#server/cloudcmd';
|
||||
import exit from './exit.js';
|
||||
|
||||
const RATE_LIMIT = 1000;
|
||||
const RATE_WINDOW = 15 * 60 * 1000;
|
||||
|
||||
const bind = (f, self) => f.bind(self);
|
||||
|
||||
const two = currify((f, a, b) => f(a, b));
|
||||
|
|
@ -25,6 +29,7 @@ const shutdown = wraptile(async (promises) => {
|
|||
const promisifySelf = squad(promisify, bind);
|
||||
|
||||
const exitPort = two(exit, 'cloudcmd --port: %s');
|
||||
|
||||
const logger = tryRequire('morgan');
|
||||
|
||||
export default async (options, config) => {
|
||||
|
|
@ -46,8 +51,13 @@ export default async (options, config) => {
|
|||
path: `${prefix}/socket.io`,
|
||||
});
|
||||
|
||||
app.use(compression());
|
||||
const limiter = rateLimit({
|
||||
windowMs: RATE_WINDOW,
|
||||
limit: RATE_LIMIT,
|
||||
});
|
||||
|
||||
app.use(compression());
|
||||
app.use(limiter);
|
||||
app.use(prefix, cloudcmd({
|
||||
config: options,
|
||||
socket: socketServer,
|
||||
|
|
@ -65,7 +75,9 @@ export default async (options, config) => {
|
|||
await listen(port, ip);
|
||||
|
||||
const close = shutdown([closeServer, closeSocket]);
|
||||
|
||||
process.on('SIGINT', close);
|
||||
process.on('SIUSR1', close);
|
||||
|
||||
const host = config('ip') || 'localhost';
|
||||
const port0 = port || server.address().port;
|
||||
|
|
|
|||
22
test/e2e/ratelimit.js
Normal file
22
test/e2e/ratelimit.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import process from 'node:process';
|
||||
import {test} from 'supertape';
|
||||
|
||||
test('cloudcmd: server: ratelimit', async (t) => {
|
||||
const PORT = 3000;
|
||||
const STATUS = 429;
|
||||
|
||||
process.env.PORT = PORT;
|
||||
process.env.CLOUDCMD_LOG = 0;
|
||||
|
||||
await import('../../bin/cloudcmd.js');
|
||||
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
await fetch(`http://localhost:${PORT}`);
|
||||
}
|
||||
|
||||
const {status} = await fetch(`http://localhost:${PORT}`);
|
||||
process.kill(process.pid, 'SIGUSR1');
|
||||
|
||||
t.equal(status, STATUS);
|
||||
t.end();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue