rsnext/packages/next/shared/lib/router/utils/get-next-pathname-info.ts
Javi Velasco 7584b02b34
Remove Middleware Preflight (#37490)
* Refactor data fetching to support getting headers

* Relax `getNextPathnameInfo` type

* Add test for middleware internal redirects

* Export `ParsedRelativeUrl` type

* Refactor `getMiddlewareEffects`

* Move rewrite i18n test to middleware rewrite tests

* Fix bug parsing pathname info

* Normalize data requests to page requests for middleware

* Ensure there is a header `x-nextjs-matched-path` for middleware rewrites on data requests

* Extract `getDataHref` to a function

* Stop using `getDataHref` for flight

* Always set the query in `dataHref` independently of if it is SSG

* Add test for recursive rewrites

* Refactor dynamicPath validation to `matchHrefAndAsPath`

* Add `dataHref` to `FetchDataOutput`

* Extract `matchesMiddleware` function

* Add `hasMiddleware` option to `fetchNextData`

* Move preflight test

* Remove preflight test

* Add middleware prefetch tests

* Remove preflight

* Attempt to reduce bundle size

Include `withMiddlewareEffects` and `matchHrefAndAsPath` into `router`

Bring `getDataHref` back to `page-loader`

Bring `resolveDynamicRoute` back to `router`

* Reduce arg duplication for `withMiddlewareEffects`

* Remove some async/await and spreads to reduce bundle size

* Upgrade `edge-runtime` & clone `Request` on redirects to mutate headers

* Add some rewrite tests

Co-authored-by: Kiko Beats <josefrancisco.verdu@gmail.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-06-08 10:41:28 -05:00

80 lines
2.2 KiB
TypeScript

import { normalizeLocalePath } from '../../i18n/normalize-locale-path'
import { removePathPrefix } from './remove-path-prefix'
import { pathHasPrefix } from './path-has-prefix'
export interface NextPathnameInfo {
/**
* The base path in case the pathname included it.
*/
basePath?: string
/**
* The buildId for when the parsed URL is a data URL. Parsing it can be
* disabled with the `parseData` option.
*/
buildId?: string
/**
* If there was a locale in the pathname, this will hold its value.
*/
locale?: string
/**
* The processed pathname without a base path, locale, or data URL elements
* when parsing it is enabled.
*/
pathname: string
/**
* A boolean telling if the pathname had a trailingSlash. This can be only
* true if trailingSlash is enabled.
*/
trailingSlash?: boolean
}
interface Options {
/**
* When passed to true, this function will also parse Nextjs data URLs.
*/
parseData?: boolean
/**
* A partial of the Next.js configuration to parse the URL.
*/
nextConfig?: {
basePath?: string
i18n?: { locales?: string[] } | null
trailingSlash?: boolean
}
}
export function getNextPathnameInfo(pathname: string, options: Options) {
const { basePath, i18n, trailingSlash } = options.nextConfig ?? {}
const info: NextPathnameInfo = {
pathname: pathname,
trailingSlash: pathname !== '/' ? pathname.endsWith('/') : trailingSlash,
}
if (basePath && pathHasPrefix(info.pathname, basePath)) {
info.pathname = removePathPrefix(info.pathname, basePath)
info.basePath = basePath
}
if (
options.parseData === true &&
info.pathname.startsWith('/_next/data/') &&
info.pathname.endsWith('.json')
) {
const paths = info.pathname
.replace(/^\/_next\/data\//, '')
.replace(/\.json$/, '')
.split('/')
const buildId = paths[0]
info.pathname = paths[1] !== 'index' ? `/${paths.slice(1).join('/')}` : '/'
info.buildId = buildId
}
if (i18n) {
const pathLocale = normalizeLocalePath(info.pathname, i18n.locales)
info.locale = pathLocale?.detectedLocale
info.pathname = pathLocale?.pathname || info.pathname
}
return info
}