Skip to content

Commit

Permalink
fix: route body limit (#36)
Browse files Browse the repository at this point in the history
* fix: route body limit

* test: improve
  • Loading branch information
Eomm authored Oct 25, 2022
1 parent 84f755f commit 4e79cc2
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 2 deletions.
10 changes: 8 additions & 2 deletions plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,22 @@ function rawBody (fastify, opts, next) {
next()

function preparsingRawBody (request, reply, payload, done) {
const applyLimit = request.context._parserOptions.limit ?? fastify.initialConfig.bodyLimit

getRawBody(runFirst ? request.raw : payload, {
length: null, // avoid content lenght check: fastify will do it
limit: fastify.initialConfig.bodyLimit, // limit to avoid memory leak or DoS
limit: applyLimit, // limit to avoid memory leak or DoS
encoding
}, function (err, string) {
if (err) {
/**
* the error is managed by fastify server
* so the request object will not have any
* `body` parsed
* `body` parsed.
*
* The preparsingRawBody decorates the request
* meanwhile the `payload` is processed by
* the fastify server.
*/
return
}
Expand Down
6 changes: 6 additions & 0 deletions test/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ t.test('body limit', async t => {
payload
})
t.equal(res.statusCode, 413)
t.same(res.json(), {
statusCode: 413,
code: 'FST_ERR_CTP_BODY_TOO_LARGE',
error: 'Payload Too Large',
message: 'Request body is too large'
})
})

t.test('empty body', async t => {
Expand Down
144 changes: 144 additions & 0 deletions test/route-limit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
'use strict'

const t = require('tap')
const Fastify = require('fastify')
const rawBody = require('../plugin')

const payloadMini = { h: 1 }
const payloadSmall = { hello: '1' }
const payloadBig = { hello: '1'.repeat(100) }

const limitError = Object.freeze({
statusCode: 413,
code: 'FST_ERR_CTP_BODY_TOO_LARGE',
error: 'Payload Too Large',
message: 'Request body is too large'
})

async function buildApp ({
serverLimit,
routeLimit
}) {
const app = Fastify({ bodyLimit: serverLimit })

await app.register(rawBody, {
field: 'rawBody',
global: false,
runFirst: false
})

app.post('/route-limit', {
config: { rawBody: true },
bodyLimit: routeLimit,
handler (req) { return req.rawBody }
})

app.post('/server-limit', {
config: { rawBody: true },
handler (req) { return req.rawBody }
})

return app
}

t.test('body limit per route (route-limit > server-limit)', async t => {
const app = await buildApp({
serverLimit: 10,
routeLimit: 100
})

await t.test('must succeed if body is smaller than route limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/route-limit',
payload: payloadSmall
})

t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify(payloadSmall))
})

await t.test('must reject if body is bigger than route limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/route-limit',
payload: payloadBig
})

t.equal(res.statusCode, 413)
t.same(res.json(), limitError)
})

await t.test('must succeed if body is smaller then server limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/server-limit',
payload: payloadMini
})

t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify(payloadMini))
})

await t.test('must reject if body is bigger then the server limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/server-limit',
payload: payloadSmall
})

t.equal(res.statusCode, 413)
t.same(res.json(), limitError)
})
})

t.test('body limit per route (route-limit < server-limit)', async t => {
const app = await buildApp({
serverLimit: 100,
routeLimit: 10
})

await t.test('must succeed if body is smaller than route limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/route-limit',
payload: payloadMini
})

t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify(payloadMini))
})

await t.test('must reject if body is bigger than route limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/route-limit',
payload: payloadSmall
})

t.equal(res.statusCode, 413)
t.same(res.json(), limitError)
})

await t.test('must succeed if body is smaller then server limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/server-limit',
payload: payloadSmall
})

t.equal(res.statusCode, 200)
t.equal(res.payload, JSON.stringify(payloadSmall))
})

await t.test('must reject if body is bigger then the server limit', async t => {
const res = await app.inject({
method: 'POST',
url: '/server-limit',
payload: payloadBig
})

t.equal(res.statusCode, 413)
t.same(res.json(), limitError)
})
})

0 comments on commit 4e79cc2

Please sign in to comment.