Skip to content

Commit

Permalink
[middleware] add tests for body reading methods #37980 (#41718)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kikobeats committed Nov 2, 2022
1 parent 460e19f commit 137008e
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -141,6 +141,7 @@
"faunadb": "2.6.1",
"firebase": "7.14.5",
"flat": "5.0.2",
"form-data": "4.0.0",
"fs-extra": "9.0.0",
"get-port": "5.1.1",
"glob": "7.1.6",
Expand Down
4 changes: 2 additions & 2 deletions packages/next/compiled/undici/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/next/package.json
Expand Up @@ -276,7 +276,7 @@
"timers-browserify": "2.0.12",
"tty-browserify": "0.0.1",
"ua-parser-js": "0.7.28",
"undici": "5.10.0",
"undici": "5.12.0",
"unistore": "3.4.1",
"util": "0.12.4",
"uuid": "8.3.2",
Expand Down
33 changes: 29 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/e2e/edge-can-read-request-body/app/.gitignore
@@ -0,0 +1 @@
.vercel
49 changes: 49 additions & 0 deletions test/e2e/edge-can-read-request-body/app/middleware.js
@@ -0,0 +1,49 @@
// @ts-check

import { NextResponse } from 'next/server'

/**
* @param {NextRequest} req
*/
export default async function middleware(req) {
const res = NextResponse.next()
res.headers.set('x-incoming-content-type', req.headers.get('content-type'))

const handler =
bodyHandlers[req.nextUrl.searchParams.get('middleware-handler')]
const headers = await handler?.(req)
for (const [key, value] of headers ?? []) {
res.headers.set(key, value)
}

return res
}

/**
* @typedef {import('next/server').NextRequest} NextRequest
* @typedef {(req: NextRequest) => Promise<[string, string][]>} Handler
* @type {Record<string, Handler>}
*/
const bodyHandlers = {
json: async (req) => {
const json = await req.json()
return [
['x-req-type', 'json'],
['x-serialized', JSON.stringify(json)],
]
},
text: async (req) => {
const text = await req.text()
return [
['x-req-type', 'text'],
['x-serialized', text],
]
},
formData: async (req) => {
const formData = await req.formData()
return [
['x-req-type', 'formData'],
['x-serialized', JSON.stringify(Object.fromEntries(formData))],
]
},
}
3 changes: 3 additions & 0 deletions test/e2e/edge-can-read-request-body/app/pages/api/nothing.js
@@ -0,0 +1,3 @@
export default (_req, res) => {
res.send('ok')
}
124 changes: 124 additions & 0 deletions test/e2e/edge-can-read-request-body/index.test.ts
@@ -0,0 +1,124 @@
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { fetchViaHTTP, renderViaHTTP } from 'next-test-utils'
import FormData from 'form-data'
import path from 'path'

async function serialize(response: Response) {
return {
text: await response.text(),
headers: Object.fromEntries(response.headers),
status: response.status,
}
}

describe('Edge can read request body', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: new FileRef(path.resolve(__dirname, './app')),
dependencies: {},
})
})
afterAll(() => next.destroy())

it('renders the static page', async () => {
const html = await renderViaHTTP(next.url, '/api/nothing')
expect(html).toContain('ok')
})

describe('middleware', () => {
it('reads a JSON body', async () => {
const response = await fetchViaHTTP(
next.url,
'/api/nothing?middleware-handler=json',
null,
{
method: 'POST',
body: JSON.stringify({ hello: 'world' }),
}
)
expect(await serialize(response)).toMatchObject({
text: expect.stringContaining('ok'),
status: 200,
headers: {
'x-req-type': 'json',
'x-serialized': '{"hello":"world"}',
},
})
})

it('reads a text body', async () => {
try {
const response = await fetchViaHTTP(
next.url,
'/api/nothing?middleware-handler=text',
null,
{
method: 'POST',
body: JSON.stringify({ hello: 'world' }),
}
)

expect(await serialize(response)).toMatchObject({
text: expect.stringContaining('ok'),
status: 200,
headers: {
'x-req-type': 'text',
'x-serialized': '{"hello":"world"}',
},
})
} catch (err) {
console.log('FAILED', err)
}
})

it('reads an URL encoded form data', async () => {
const response = await fetchViaHTTP(
next.url,
'/api/nothing?middleware-handler=formData',
null,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ hello: 'world' }).toString(),
}
)
expect(await serialize(response)).toMatchObject({
text: expect.stringContaining('ok'),
status: 200,
headers: {
'x-req-type': 'formData',
'x-serialized': '{"hello":"world"}',
},
})
})

it('reads a multipart form data', async () => {
const formData = new FormData()
formData.append('hello', 'world')

const response = await fetchViaHTTP(
next.url,
'/api/nothing?middleware-handler=formData',
null,
{
method: 'POST',
body: formData,
}
)

expect(await serialize(response)).toMatchObject({
text: expect.stringContaining('ok'),
status: 200,
headers: {
'x-req-type': 'formData',
'x-serialized': '{"hello":"world"}',
},
})
})
})
})

0 comments on commit 137008e

Please sign in to comment.