311 lines
8.2 KiB
TypeScript
311 lines
8.2 KiB
TypeScript
import { createNext } from 'e2e-utils'
|
|
import { NextInstance } from 'e2e-utils'
|
|
import { fetchViaHTTP } from 'next-test-utils'
|
|
|
|
describe('Middleware fetches with body', () => {
|
|
let next: NextInstance
|
|
|
|
beforeAll(async () => {
|
|
next = await createNext({
|
|
files: {
|
|
'pages/api/default.js': `
|
|
export default (req, res) => res.json({ body: req.body })
|
|
`,
|
|
'pages/api/size_limit_5kb.js': `
|
|
export const config = { api: { bodyParser: { sizeLimit: '5kb' } } }
|
|
export default (req, res) => res.json({ body: req.body })
|
|
`,
|
|
'pages/api/size_limit_5mb.js': `
|
|
export const config = { api: { bodyParser: { sizeLimit: '5mb' } } }
|
|
export default (req, res) => res.json({ body: req.body })
|
|
`,
|
|
'pages/api/body_parser_false.js': `
|
|
export const config = { api: { bodyParser: false } }
|
|
|
|
async function buffer(readable) {
|
|
const chunks = []
|
|
for await (const chunk of readable) {
|
|
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)
|
|
}
|
|
return Buffer.concat(chunks)
|
|
}
|
|
|
|
export default async (req, res) => {
|
|
const buf = await buffer(req)
|
|
const rawBody = buf.toString('utf8');
|
|
|
|
res.json({ rawBody, body: req.body })
|
|
}
|
|
`,
|
|
'middleware.js': `
|
|
import { NextResponse } from 'next/server';
|
|
|
|
export default async (req) => NextResponse.next();
|
|
`,
|
|
},
|
|
dependencies: {},
|
|
})
|
|
})
|
|
afterAll(() => next.destroy())
|
|
|
|
describe('with default bodyParser sizeLimit (1mb)', () => {
|
|
it('should return 413 for body greater than 1mb', async () => {
|
|
const bodySize = 1024 * 1024 + 1
|
|
const body = 'r'.repeat(bodySize)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/default',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
|
|
try {
|
|
expect(res.status).toBe(413)
|
|
|
|
if (!(global as any).isNextDeploy) {
|
|
expect(res.statusText).toBe('Body exceeded 1mb limit')
|
|
}
|
|
} catch (err) {
|
|
// TODO: investigate occasional EPIPE errors causing
|
|
// a 500 status instead of a 413
|
|
if (res.status !== 500) {
|
|
throw err
|
|
}
|
|
}
|
|
})
|
|
|
|
it('should be able to send and return body size equal to 1mb', async () => {
|
|
const bodySize = 1024 * 1024
|
|
const body = 'B1C2D3E4F5G6H7I8J9K0LaMbNcOdPeQf'.repeat(bodySize / 32)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/default',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body.length).toBe(bodySize)
|
|
expect(data.body.split('B1C2D3E4F5G6H7I8J9K0LaMbNcOdPeQf').length).toBe(
|
|
bodySize / 32 + 1
|
|
)
|
|
})
|
|
|
|
it('should be able to send and return body greater than default highWaterMark (16KiB)', async () => {
|
|
const bodySize = 16 * 1024 + 1
|
|
const body =
|
|
'CD1E2F3G4H5I6J7K8L9M0NaObPcQdReS'.repeat(bodySize / 32) + 'C'
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/default',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body.length).toBe(bodySize)
|
|
expect(data.body.split('CD1E2F3G4H5I6J7K8L9M0NaObPcQdReS').length).toBe(
|
|
512 + 1
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('with custom bodyParser sizeLimit (5kb)', () => {
|
|
it('should return 413 for body greater than 5kb', async () => {
|
|
const bodySize = 5 * 1024 + 1
|
|
const body = 's'.repeat(bodySize)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/size_limit_5kb',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
|
|
try {
|
|
expect(res.status).toBe(413)
|
|
|
|
if (!(global as any).isNextDeploy) {
|
|
expect(res.statusText).toBe('Body exceeded 5kb limit')
|
|
}
|
|
} catch (err) {
|
|
// TODO: investigate occasional EPIPE errors causing
|
|
// a 500 status instead of a 413
|
|
if (res.status !== 500) {
|
|
throw err
|
|
}
|
|
}
|
|
})
|
|
|
|
it('should be able to send and return body size equal to 5kb', async () => {
|
|
const bodySize = 5120
|
|
const body = 'DEF1G2H3I4J5K6L7M8N9O0PaQbRcSdTe'.repeat(bodySize / 32)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/size_limit_5kb',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body.length).toBe(bodySize)
|
|
expect(data.body.split('DEF1G2H3I4J5K6L7M8N9O0PaQbRcSdTe').length).toBe(
|
|
bodySize / 32 + 1
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('with custom bodyParser sizeLimit (5mb)', () => {
|
|
it('should return 413 for body greater than 5mb', async () => {
|
|
const bodySize = 5 * 1024 * 1024 + 1
|
|
const body = 'u'.repeat(bodySize)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/size_limit_5mb',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
|
|
try {
|
|
expect(res.status).toBe(413)
|
|
|
|
if (!(global as any).isNextDeploy) {
|
|
expect(res.statusText).toBe('Body exceeded 5mb limit')
|
|
}
|
|
} catch (err) {
|
|
// TODO: investigate occasional EPIPE errors causing
|
|
// a 500 status instead of a 413
|
|
if (res.status !== 500) {
|
|
throw err
|
|
}
|
|
}
|
|
})
|
|
|
|
if (!(global as any).isNextDeploy) {
|
|
it('should be able to send and return body size equal to 5mb', async () => {
|
|
const bodySize = 5 * 1024 * 1024
|
|
const body = 'FGHI1J2K3L4M5N6O7P8Q9R0SaTbUcVdW'.repeat(bodySize / 32)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/size_limit_5mb',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body.length).toBe(bodySize)
|
|
expect(data.body.split('FGHI1J2K3L4M5N6O7P8Q9R0SaTbUcVdW').length).toBe(
|
|
bodySize / 32 + 1
|
|
)
|
|
})
|
|
}
|
|
})
|
|
|
|
describe('with bodyParser = false', () => {
|
|
it('should be able to send and return with body size equal to 16KiB', async () => {
|
|
const bodySize = 16 * 1024
|
|
const body = 'HIJK1L2M3N4O5P6Q7R8S9T0UaVbWcXdY'.repeat(bodySize / 32)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/body_parser_false',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body).toBeUndefined()
|
|
expect(data.rawBody.length).toBe(bodySize)
|
|
expect(
|
|
data.rawBody.split('HIJK1L2M3N4O5P6Q7R8S9T0UaVbWcXdY').length
|
|
).toBe(bodySize / 32 + 1)
|
|
})
|
|
|
|
it('should be able to send and return with body greater than 16KiB', async () => {
|
|
const bodySize = 1024 * 1024
|
|
const body = 'JKLM1N2O3P4Q5R6S7T8U9V0WaXbYcZdA'.repeat(bodySize / 32)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/body_parser_false',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
const data = await res.json()
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(data.body).toBeUndefined()
|
|
expect(data.rawBody.length).toBe(bodySize)
|
|
expect(
|
|
data.rawBody.split('JKLM1N2O3P4Q5R6S7T8U9V0WaXbYcZdA').length
|
|
).toBe(bodySize / 32 + 1)
|
|
})
|
|
})
|
|
|
|
it('should return 413 for body equal to 10mb', async () => {
|
|
const bodySize = 10 * 1024 * 1024
|
|
const body = 't'.repeat(bodySize)
|
|
|
|
const res = await fetchViaHTTP(
|
|
next.url,
|
|
'/api/size_limit_5mb',
|
|
{},
|
|
{
|
|
body,
|
|
method: 'POST',
|
|
}
|
|
)
|
|
|
|
try {
|
|
expect(res.status).toBe(413)
|
|
|
|
if (!(global as any).isNextDeploy) {
|
|
expect(res.statusText).toBe('Body exceeded 5mb limit')
|
|
}
|
|
} catch (err) {
|
|
// TODO: investigate occasional EPIPE errors causing
|
|
// a 500 status instead of a 413
|
|
if (res.status !== 500) {
|
|
throw err
|
|
}
|
|
}
|
|
})
|
|
})
|