Node.js: express.json limit whitelist

Issue

I have a Node.js backend with many routes which have nothing to do with uploading files (for regular users, therefore a limit of 50kb). But I want to have a few routes for only admins that can upload files, therefore I want a higher express.json and express.urlencoded limit (10MB). I would use router.use in a routes file but some extra middleware needs the express.json and express.urlencoded. Here’s my current code:

const express = require("express");
const app = express();
...
app.use(express.json({ limit: '50kb' }));
app.use(express.urlencoded({ limit: '50kb', extended: true }));
!!! Some middlewares that need the json and urlencoded middleware !!!
...
app.use("/api/account", accountRoutes);
app.use("/api/users", usersRoutes);
app.use("/api/news", newsRoutes);
app.use("/api/admin", adminRoutes); // I want a higher limit for this route
...

Each Routes file exports a express.Router()

Is there some kind of whitelisting? Could I make a middleware myself with a whitelist?

Solution

You can just rate-limit per individual routers. Here’s a trivial example (note that I set the global limit after the individual route limits, that is important):

const app = express();

// one specific route
const onekbRouter = express.Router()
onekbRouter.use(express.json({ limit: '400b' }))
onekbRouter.post('/', (_, res) => res.send('okay buddy'))

// another route
const oneMbRouter = express.Router()
oneMbRouter.use(express.json({ limit: '1Mb' }))
oneMbRouter.post('/', (_, res) => res.send('okay buddy'))

app.use('/1kb', onekbRouter)
app.use('/1Mb', oneMbRouter)

// global limit
app.use(express.json({ limit: '1kb' }))

app.get('/', (_, res) => res.send('<a href="/1kb">1kb</a> <a href="/1mb">1Mb</a>'))

app.listen(3000, () => console.log('Go get\'em'))

module.exports = app

Testing this works properly for me. 3 requests return "okay buddy", 1 fails here:

okay buddy[[email protected] ~/tmp/new]$ curl -d @1kb.json http://localhost:3000/1kb -X POST -H "content-type: application/json"
okay buddy[[email protected] ~/tmp/new]$ curl -d @1kb.json http://localhost:3000/1mb -X POST -H "content-type: application/json"
okay buddy[[email protected] ~/tmp/new]$ curl -d @1mb.json http://localhost:3000/1mb -X POST -H "content-type: application/json"
okay buddy[[email protected] ~/tmp/new]$ curl -d @1mb.json http://localhost:3000/1kb -X POST -H "content-type: application/json"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>PayloadTooLargeError: request entity too large<br> &nbsp; &nbsp;at readStream (/home/zlatko/tmp/new/node_modules/raw-body/index.js:155:17)<br> &nbsp; &nbsp;at getRawBody (/home/zlatko/tmp/new/node_modules/raw-body/index.js:108:12)<br> &nbsp; &nbsp;at read (/home/zlatko/tmp/new/node_modules/body-parser/lib/read.js:77:3)<br> &nbsp; &nbsp;at jsonParser (/home/zlatko/tmp/new/node_modules/body-parser/lib/types/json.js:135:5)<br> &nbsp; &nbsp;at Layer.handle [as handle_request] (/home/zlatko/tmp/new/node_modules/express/lib/router/layer.js:95:5)<br> &nbsp; &nbsp;at trim_prefix (/home/zlatko/tmp/new/node_modules/express/lib/router/index.js:317:13)<br> &nbsp; &nbsp;at /home/zlatko/tmp/new/node_modules/express/lib/router/index.js:284:7<br> &nbsp; &nbsp;at Function.process_params (/home/zlatko/tmp/new/node_modules/express/lib/router/index.js:335:12)<br> &nbsp; &nbsp;at next (/home/zlatko/tmp/new/node_modules/express/lib/router/index.js:275:10)<br> &nbsp; &nbsp;at Function.handle (/home/zlatko/tmp/new/node_modules/express/lib/router/index.js:174:3)</pre>
</body>
</html>
[[email protected] ~/tmp/new]$

The sizes are not there, but are around the limits:

$ ls -hl 1*json
-rw-r--r--. 1 zlatko zlatko  28 Aug  5 15:23 1kb.json
-rw-r--r--. 1 zlatko zlatko 14K Aug  5 15:26 1mb.json

Answered By – Zlatko

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published