rsnext/test/e2e/middleware-fetches-with-body/index.test.ts
JJ Kasper f57eecde5e
Separate routing code from render servers (#52492)
This breaks out routing handling from `next-server`, `next-dev-server`,
and `base-server` so that these are only handling the "render" work and
eventually these will be deleted completely in favor of the bundling
work being done.

The `router` process and separate `render` processes are still
maintained here although will be investigated further in follow-up to
see if we can reduce the need for these.

We are also changing the `require-cache` IPC to a single call instead of
call per entry to reduce overhead and also de-dupes handling for
starting the server between the standalone server and normal server.

To maintain support for existing turbopack route resolving this
implements the new route resolving in place of the existing
`route-resolver` until the new nextturbo API is fully landed.

After these initial changes we should continue to eliminate non-render
related code from `next-server`, `base-server`, and `next-dev-server`.
2023-07-20 22:13:42 -07:00

311 lines
8.2 KiB
TypeScript

import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
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
}
}
})
})