b522b94cce
## Feature As the title, support `has` match, `local` that works the same with the `rewrites` and `redirects` of next.config.js on middleware config. With this PR, you can write the config like the following: ```js export const config = { matcher: [ "/foo", { source: "/bar" }, { source: "/baz", has: [ { type: 'header', key: 'x-my-header', value: 'my-value', } ] }, { source: "/en/asdf", locale: false, }, ] } ``` Also, fixes https://github.com/vercel/next.js/issues/39428 related https://github.com/vercel/edge-functions/issues/178, https://github.com/vercel/edge-functions/issues/179 - [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` Co-authored-by: JJ Kasper <jj@jjsweb.site>
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import type { MiddlewareMatcher } from '../../analysis/get-page-static-info'
|
|
import { getModuleBuildInfo } from './get-module-build-info'
|
|
import { stringifyRequest } from '../stringify-request'
|
|
import { MIDDLEWARE_LOCATION_REGEXP } from '../../../lib/constants'
|
|
|
|
export type MiddlewareLoaderOptions = {
|
|
absolutePagePath: string
|
|
page: string
|
|
matchers?: string
|
|
}
|
|
|
|
// matchers can have special characters that break the loader params
|
|
// parsing so we base64 encode/decode the string
|
|
export function encodeMatchers(matchers: MiddlewareMatcher[]) {
|
|
return Buffer.from(JSON.stringify(matchers)).toString('base64')
|
|
}
|
|
|
|
export function decodeMatchers(encodedMatchers: string) {
|
|
return JSON.parse(
|
|
Buffer.from(encodedMatchers, 'base64').toString()
|
|
) as MiddlewareMatcher[]
|
|
}
|
|
|
|
export default function middlewareLoader(this: any) {
|
|
const {
|
|
absolutePagePath,
|
|
page,
|
|
matchers: encodedMatchers,
|
|
}: MiddlewareLoaderOptions = this.getOptions()
|
|
const matchers = encodedMatchers ? decodeMatchers(encodedMatchers) : undefined
|
|
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
|
|
const buildInfo = getModuleBuildInfo(this._module)
|
|
buildInfo.nextEdgeMiddleware = {
|
|
matchers,
|
|
page:
|
|
page.replace(new RegExp(`/${MIDDLEWARE_LOCATION_REGEXP}$`), '') || '/',
|
|
}
|
|
|
|
return `
|
|
import { adapter, blockUnallowedResponse, enhanceGlobals } from 'next/dist/server/web/adapter'
|
|
|
|
enhanceGlobals()
|
|
|
|
var mod = require(${stringifiedPagePath})
|
|
var handler = mod.middleware || mod.default;
|
|
|
|
if (typeof handler !== 'function') {
|
|
throw new Error('The Middleware "pages${page}" must export a \`middleware\` or a \`default\` function');
|
|
}
|
|
|
|
export default function (opts) {
|
|
return blockUnallowedResponse(adapter({
|
|
...opts,
|
|
page: ${JSON.stringify(page)},
|
|
handler,
|
|
}))
|
|
}
|
|
`
|
|
}
|