rsnext/packages/next/server/web/spec-extension/response.ts
Javi Velasco 523704b83f
Execute middleware on Next.js internal requests (#37121)
* Do not exclude internal _next request in middleware

* Allow for `NextURL` to parse prefetch requests

* Add test for middleware data prefetch

* Refactor `hasBasePath` and `replaceBasePath`

* Refactor `removeTrailingSlash`

* Refactor parsed next url to use `getNextPathnameInfo`

* Allow to configure `NextURL`

* Ensure middleware rewrites with always with a locale

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-05-27 13:29:04 -05:00

78 lines
1.8 KiB
TypeScript

import type { I18NConfig } from '../../config-shared'
import { NextURL } from '../next-url'
import { toNodeHeaders, validateURL } from '../utils'
import { NextCookies } from './cookies'
const INTERNALS = Symbol('internal response')
const REDIRECTS = new Set([301, 302, 303, 307, 308])
export class NextResponse extends Response {
[INTERNALS]: {
cookies: NextCookies
url?: NextURL
}
constructor(body?: BodyInit | null, init: ResponseInit = {}) {
super(body, init)
this[INTERNALS] = {
cookies: new NextCookies(this),
url: init.url
? new NextURL(init.url, {
headers: toNodeHeaders(this.headers),
nextConfig: init.nextConfig,
})
: undefined,
}
}
public get cookies() {
return this[INTERNALS].cookies
}
static json(body: any, init?: ResponseInit) {
const { headers, ...responseInit } = init || {}
return new NextResponse(JSON.stringify(body), {
...responseInit,
headers: {
...headers,
'content-type': 'application/json',
},
})
}
static redirect(url: string | NextURL | URL, status = 307) {
if (!REDIRECTS.has(status)) {
throw new RangeError(
'Failed to execute "redirect" on "response": Invalid status code'
)
}
return new NextResponse(null, {
headers: { Location: validateURL(url) },
status,
})
}
static rewrite(destination: string | NextURL | URL) {
return new NextResponse(null, {
headers: { 'x-middleware-rewrite': validateURL(destination) },
})
}
static next() {
return new NextResponse(null, {
headers: { 'x-middleware-next': '1' },
})
}
}
interface ResponseInit extends globalThis.ResponseInit {
nextConfig?: {
basePath?: string
i18n?: I18NConfig
trailingSlash?: boolean
}
url?: string
}