Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update app route handler proxy handling #47088

Merged
merged 1 commit into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,12 @@ function proxyRequest(req: NextRequest, module: AppRouteModule): NextRequest {
const result = handleForceStatic(target.href, prop)
if (result !== undefined) return result
}
const value = (target as any)[prop]

return (target as any)[prop]
if (typeof value === 'function') {
return value.bind(target)
}
return value
},
set(target, prop, value) {
handleNextUrlBailout(prop)
Expand Down Expand Up @@ -320,8 +324,12 @@ function proxyRequest(req: NextRequest, module: AppRouteModule): NextRequest {
const result = handleForceStatic(target.url, prop)
if (result !== undefined) return result
}
const value = (target as any)[prop]

return (target as any)[prop]
if (typeof value === 'function') {
return value.bind(target)
}
return value
},
set(target, prop, value) {
handleReqBailout(prop)
Expand Down
75 changes: 75 additions & 0 deletions test/e2e/app-dir/app-routes/app-custom-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ createNextDescribe(
const meta = getRequestMeta(res.headers)
expect(meta.ping).toEqual('pong')
})

it('can read query parameters (edge)', async () => {
const res = await next.fetch('/edge/advanced/query?ping=pong')

expect(res.status).toEqual(200)
const meta = getRequestMeta(res.headers)
expect(meta.ping).toEqual('pong')
})
})

describe('response', () => {
Expand Down Expand Up @@ -203,6 +211,27 @@ createNextDescribe(
})
}

it('can handle handle a streaming request and streaming response (edge)', async () => {
const body = new Array(10).fill(JSON.stringify({ ping: 'pong' }))
let index = 0
const stream = new Readable({
read() {
if (index >= body.length) return this.push(null)

this.push(body[index] + '\n')
index++
},
})

const res = await next.fetch('/edge/advanced/body/streaming', {
method: 'POST',
body: stream,
})

expect(res.status).toEqual(200)
expect(await res.text()).toEqual(body.join('\n') + '\n')
})

it('can read a JSON encoded body', async () => {
const body = { ping: 'pong' }
const res = await next.fetch('/advanced/body/json', {
Expand All @@ -215,6 +244,18 @@ createNextDescribe(
expect(meta.body).toEqual(body)
})

it('can read a JSON encoded body (edge)', async () => {
const body = { ping: 'pong' }
const res = await next.fetch('/edge/advanced/body/json', {
method: 'POST',
body: JSON.stringify(body),
})

expect(res.status).toEqual(200)
const meta = getRequestMeta(res.headers)
expect(meta.body).toEqual(body)
})

// we can't stream a body to a function currently only stream response
if (!(global as any).isNextDeploy) {
it('can read a streamed JSON encoded body', async () => {
Expand All @@ -240,6 +281,28 @@ createNextDescribe(
})
}

it('can read a streamed JSON encoded body (edge)', async () => {
const body = { ping: 'pong' }
const encoded = JSON.stringify(body)
let index = 0
const stream = new Readable({
async read() {
if (index >= encoded.length) return this.push(null)

this.push(encoded[index])
index++
},
})
const res = await next.fetch('/edge/advanced/body/json', {
method: 'POST',
body: stream,
})

expect(res.status).toEqual(200)
const meta = getRequestMeta(res.headers)
expect(meta.body).toEqual(body)
})

it('can read the text body', async () => {
const body = 'hello, world'
const res = await next.fetch('/advanced/body/text', {
Expand All @@ -251,6 +314,18 @@ createNextDescribe(
const meta = getRequestMeta(res.headers)
expect(meta.body).toEqual(body)
})

it('can read the text body (edge)', async () => {
const body = 'hello, world'
const res = await next.fetch('/edge/advanced/body/text', {
method: 'POST',
body,
})

expect(res.status).toEqual(200)
const meta = getRequestMeta(res.headers)
expect(meta.body).toEqual(body)
})
})

describe('context', () => {
Expand Down
12 changes: 12 additions & 0 deletions test/e2e/app-dir/app-routes/app/edge/advanced/body/json/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { NextRequest } from 'next/server'
import { withRequestMeta } from '../../../../../helpers'

export const runtime = 'experimental-edge'

export async function POST(request: NextRequest) {
const body = await request.json()
return new Response('hello, world', {
status: 200,
headers: withRequestMeta({ body }),
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NextRequest } from 'next/server'

export const runtime = 'experimental-edge'

export async function POST(request: NextRequest) {
const reader = request.body?.getReader()
if (!reader) {
return new Response(null, { status: 400, statusText: 'Bad Request' })
}

// Readable stream here is polyfilled from the Fetch API (from undici).
const stream = new ReadableStream({
async pull(controller) {
// Read the next chunk from the stream.
const { value, done } = await reader.read()
if (done) {
// Finish the stream.
return controller.close()
}

// Add the request value to the response stream.
controller.enqueue(value)
},
})

return new Response(stream, { status: 200 })
}
12 changes: 12 additions & 0 deletions test/e2e/app-dir/app-routes/app/edge/advanced/body/text/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { NextRequest } from 'next/server'
import { withRequestMeta } from '../../../../../helpers'

export const runtime = 'experimental-edge'

export async function POST(request: NextRequest) {
const body = await request.text()
return new Response('hello, world', {
status: 200,
headers: withRequestMeta({ body }),
})
}
14 changes: 14 additions & 0 deletions test/e2e/app-dir/app-routes/app/edge/advanced/query/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { withRequestMeta } from '../../../../helpers'
import { NextRequest } from 'next/server'

export const runtime = 'experimental-edge'

export async function GET(request: NextRequest): Promise<Response> {
const { searchParams } = request.nextUrl

return new Response('hello, world', {
headers: withRequestMeta({
ping: searchParams.get('ping'),
}),
})
}