Skip to content

Commit 40ecef5

Browse files
committed
feature: cloudcmd: ratelimit: X-Forwarded-For (#437)
1 parent cad5e0f commit 40ecef5

7 files changed

Lines changed: 61 additions & 31 deletions

File tree

.madrun.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export default {
2828
'lint:fresh': () => run('lint', '--fresh'),
2929
'fix:lint': async () => `putout --rulesdir rules --fix . && redlint fix`,
3030
'lint:stream': () => run('lint', '-f stream'),
31-
'test': () => [testEnv, `tape 'test/**/*.js' '{bin,client,static,common,server}/**/*.spec.js' -f fail`],
31+
'test': () => [testEnv, `tape '{test,test-e2e}/**/*.js' '{bin,client,static,common,server}/**/*.spec.js' -f fail`],
32+
'test:e2e': () => `tape 'test-e2e/**/*.js'`,
3233
'test:client': () => `tape 'test/client/**/*.js'`,
3334
'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`,
3435
'wisdom': async () => await run(['lint:all', 'build', 'test'], null, {

.npmignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ img/logo/cloudcmd-hq.png
2020
webpack.config.js
2121

2222
docker
23-
test
23+
test*
2424
fixture
2525
fixture-*
2626
coverage

bin/cloudcmd.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ function validateRoot(root, config) {
264264
if (root === '/')
265265
return;
266266

267-
console.log(`root: ${root}`);
267+
if (config('log'))
268+
console.log(`root: ${root}`);
268269
}
269270

270271
async function getPassword(password) {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"fix:lint": "madrun fix:lint",
5656
"lint:stream": "madrun lint:stream",
5757
"test": "madrun test",
58+
"test:e2e": "madrun test:e2e",
5859
"test:client": "madrun test:client",
5960
"test:server": "madrun test:server",
6061
"wisdom": "madrun wisdom",

server/server.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ const RATE_WINDOW = 15 * 60 * 1000;
2020
const bind = (f, self) => f.bind(self);
2121

2222
const two = currify((f, a, b) => f(a, b));
23-
const shutdown = wraptile(async (promises) => {
24-
console.log('closing cloudcmd...');
23+
const shutdown = wraptile(async (config, promises) => {
24+
if (config('log'))
25+
console.log('closing cloudcmd...');
26+
2527
await Promise.all(promises);
2628
process.exit(0);
2729
});
@@ -41,7 +43,7 @@ export default async (options, config) => {
4143
const app = express();
4244
const server = http.createServer(app);
4345

44-
if (logger)
46+
if (config('log') && logger)
4547
app.use(logger('dev'));
4648

4749
if (prefix)
@@ -56,6 +58,8 @@ export default async (options, config) => {
5658
limit: RATE_LIMIT,
5759
});
5860

61+
app.set('trust proxy', 1);
62+
5963
app.use(compression());
6064
app.use(limiter);
6165
app.use(prefix, cloudcmd({
@@ -74,16 +78,17 @@ export default async (options, config) => {
7478
server.on('error', exitPort);
7579
await listen(port, ip);
7680

77-
const close = shutdown([closeServer, closeSocket]);
81+
const close = shutdown(config, [closeServer, closeSocket]);
7882

7983
process.on('SIGINT', close);
80-
process.on('SIUSR1', close);
84+
process.on('SIGUSR1', close);
8185

8286
const host = config('ip') || 'localhost';
8387
const port0 = port || server.address().port;
8488
const url = `http://${host}:${port0}${prefix}/`;
8589

86-
console.log(`url: ${url}`);
90+
if (config('log'))
91+
console.log(`url: ${url}`);
8792

8893
if (!config('open'))
8994
return;

test-e2e/ratelimit.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import process from 'node:process';
2+
import {test} from 'supertape';
3+
4+
let i = 0;
5+
6+
test('cloudcmd: server: ratelimit: x-forwarded-for', async (t) => {
7+
const PORT = 3000;
8+
9+
process.env.PORT = PORT;
10+
process.env.CLOUDCMD_LOG = 0;
11+
12+
await import('../bin/cloudcmd.js');
13+
14+
const {status} = await fetch(`http://localhost:${PORT}`, {
15+
headers: {
16+
'X-Forwarded-For': '127.0.0.1',
17+
},
18+
});
19+
20+
process.kill(process.pid, 'SIGUSR1');
21+
22+
t.notEqual(status, 500);
23+
t.end();
24+
});
25+
26+
test('cloudcmd: server: ratelimit', async (t) => {
27+
const PORT = 3001;
28+
const STATUS = 429;
29+
30+
process.env.PORT = PORT;
31+
process.env.CLOUDCMD_LOG = 0;
32+
33+
await import(`../bin/cloudcmd.js?${i++}`);
34+
35+
for (let i = 0; i < 1000; i++) {
36+
await fetch(`http://localhost:${PORT}`);
37+
}
38+
39+
const {status} = await fetch(`http://localhost:${PORT}`);
40+
process.kill(process.pid, 'SIGUSR1');
41+
42+
t.equal(status, STATUS);
43+
t.end();
44+
});

test/e2e/ratelimit.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)