Skip to content

Commit

Permalink
fix: reused existing parse-relative-url method
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattjoh committed May 3, 2024
1 parent ebf4bd9 commit 6119547
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 87 deletions.
2 changes: 1 addition & 1 deletion packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1367,7 +1367,7 @@ export async function buildAppStaticPaths({
return StaticGenerationAsyncStorageWrapper.wrap(
ComponentMod.staticGenerationAsyncStorage,
{
urlPathname: page,
url: { pathname: page },
renderOpts: {
originalPathname: page,
incrementalCache,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { staticGenerationAsyncStorage } from './static-generation-async-storage-
export interface StaticGenerationStore {
readonly isStaticGeneration: boolean
readonly pagePath?: string
readonly urlPathname: string
/**
* The URL of the request. This only specifies the pathname and the search
* part of the URL. The other parts aren't accepted so they shouldn't be used.
*/
readonly url: { readonly pathname: string; readonly search: string }
readonly incrementalCache?: IncrementalCache
readonly isOnDemandRevalidate?: boolean
readonly isPrerendering?: boolean
Expand Down
3 changes: 1 addition & 2 deletions packages/next/src/lib/metadata/metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ export function createMetadataComponents({
) => ParsedUrlQuery
}): [React.ComponentType, React.ComponentType] {
const metadataContext = {
// Make sure the pathname without query string
pathname: pathname.split('?')[0],
pathname,
trailingSlash,
}

Expand Down
10 changes: 1 addition & 9 deletions packages/next/src/lib/url.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers'

export const DUMMY_ORIGIN = 'http://n'

function getUrlWithoutHost(url: string) {
return new URL(url, DUMMY_ORIGIN)
}

export function getPathname(url: string) {
return getUrlWithoutHost(url).pathname
}
const DUMMY_ORIGIN = 'http://n'

export function isFullStringUrl(url: string) {
return /https?:\/\//.test(url)
Expand Down
26 changes: 15 additions & 11 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ import {
import { getSegmentParam } from './get-segment-param'
import { getScriptNonceFromHeader } from './get-script-nonce-from-header'
import { parseAndValidateFlightRouterState } from './parse-and-validate-flight-router-state'
import { validateURL } from './validate-url'
import { createFlightRouterStateFromLoaderTree } from './create-flight-router-state-from-loader-tree'
import { handleAction } from './action-handler'
import { isBailoutToCSRError } from '../../shared/lib/lazy-dynamic/bailout-to-csr'
Expand Down Expand Up @@ -110,6 +109,7 @@ import {
import { createServerModuleMap } from './action-utils'
import { isNodeNextRequest } from '../base-http/helpers'
import { parseParameter } from '../../shared/lib/router/utils/route-regex'
import { parseRelativeUrl } from '../../shared/lib/router/utils/parse-relative-url'

export type GetDynamicParamFromSegment = (
// [slug] / [[slug]] / [...slug]
Expand Down Expand Up @@ -312,7 +312,7 @@ async function generateFlight(
},
getDynamicParamFromSegment,
appUsingSizeAdjustment,
staticGenerationStore: { urlPathname },
staticGenerationStore: { url },
query,
requestId,
flightRouterState,
Expand All @@ -321,7 +321,7 @@ async function generateFlight(
if (!options?.skipFlight) {
const [MetadataTree, MetadataOutlet] = createMetadataComponents({
tree: loaderTree,
pathname: urlPathname,
pathname: url.pathname,
trailingSlash: ctx.renderOpts.trailingSlash,
query,
getDynamicParamFromSegment,
Expand Down Expand Up @@ -434,7 +434,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
GlobalError,
createDynamicallyTrackedSearchParams,
},
staticGenerationStore: { urlPathname },
staticGenerationStore: { url },
} = ctx
const initialTree = createFlightRouterStateFromLoaderTree(
tree,
Expand All @@ -445,7 +445,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
const [MetadataTree, MetadataOutlet] = createMetadataComponents({
tree,
errorType: asNotFound ? 'not-found' : undefined,
pathname: urlPathname,
pathname: url.pathname,
trailingSlash: ctx.renderOpts.trailingSlash,
query,
getDynamicParamFromSegment: getDynamicParamFromSegment,
Expand Down Expand Up @@ -481,7 +481,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
<AppRouter
buildId={ctx.renderOpts.buildId}
assetPrefix={ctx.assetPrefix}
initialCanonicalUrl={urlPathname}
initialCanonicalUrl={url.pathname + url.search}
// This is the router state tree.
initialTree={initialTree}
// This is the tree of React nodes that are seeded into the cache
Expand Down Expand Up @@ -526,14 +526,14 @@ async function ReactServerError({
GlobalError,
createDynamicallyTrackedSearchParams,
},
staticGenerationStore: { urlPathname },
staticGenerationStore: { url },
requestId,
res,
} = ctx

const [MetadataTree] = createMetadataComponents({
tree,
pathname: urlPathname,
pathname: url.pathname,
trailingSlash: ctx.renderOpts.trailingSlash,
errorType,
query,
Expand Down Expand Up @@ -576,7 +576,7 @@ async function ReactServerError({
<AppRouter
buildId={ctx.renderOpts.buildId}
assetPrefix={ctx.assetPrefix}
initialCanonicalUrl={urlPathname}
initialCanonicalUrl={url.pathname + url.search}
initialTree={initialTree}
initialHead={head}
globalErrorComponent={GlobalError}
Expand Down Expand Up @@ -1473,7 +1473,11 @@ export const renderToHTMLOrFlight: AppPageRender = (
query,
renderOpts
) => {
const { pathname } = validateURL(req.url)
if (!req.url) {
throw new Error('Invalid URL')
}

const url = parseRelativeUrl(req.url, undefined, false)

return RequestAsyncStorageWrapper.wrap(
renderOpts.ComponentMod.requestAsyncStorage,
Expand All @@ -1482,7 +1486,7 @@ export const renderToHTMLOrFlight: AppPageRender = (
StaticGenerationAsyncStorageWrapper.wrap(
renderOpts.ComponentMod.staticGenerationAsyncStorage,
{
urlPathname: pathname,
url,
renderOpts,
requestEndedState: { ended: false },
},
Expand Down
4 changes: 2 additions & 2 deletions packages/next/src/server/app-render/create-component-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ async function createComponentTreeInternal({
if (typeof layoutOrPageMod?.revalidate !== 'undefined') {
validateRevalidate(
layoutOrPageMod?.revalidate,
staticGenerationStore.urlPathname
staticGenerationStore.url.pathname
)
}

Expand Down Expand Up @@ -539,7 +539,7 @@ async function createComponentTreeInternal({
<Postpone
prerenderState={staticGenerationStore.prerenderState}
reason='dynamic = "force-dynamic" was used'
pathname={staticGenerationStore.urlPathname}
pathname={staticGenerationStore.url.pathname}
/>,
loadingData,
],
Expand Down
7 changes: 3 additions & 4 deletions packages/next/src/server/app-render/dynamic-rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import React from 'react'
import type { StaticGenerationStore } from '../../client/components/static-generation-async-storage.external'
import { DynamicServerError } from '../../client/components/hooks-server-context'
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'
import { getPathname } from '../../lib/url'

const hasPostpone = typeof React.unstable_postpone === 'function'

Expand Down Expand Up @@ -76,7 +75,7 @@ export function markCurrentScopeAsDynamic(
store: StaticGenerationStore,
expression: string
): void {
const pathname = getPathname(store.urlPathname)
const { pathname } = store.url
if (store.isUnstableCacheCallback) {
// inside cache scopes marking a scope as dynamic has no effect because the outer cache scope
// creates a cache boundary. This is subtly different from reading a dynamic data source which is
Expand Down Expand Up @@ -123,7 +122,7 @@ export function trackDynamicDataAccessed(
store: StaticGenerationStore,
expression: string
): void {
const pathname = getPathname(store.urlPathname)
const { pathname } = store.url
if (store.isUnstableCacheCallback) {
throw new Error(
`Route ${pathname} used "${expression}" inside a function cached with "unstable_cache(...)". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use "${expression}" outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
Expand Down Expand Up @@ -184,7 +183,7 @@ export function trackDynamicFetch(
// don't need to postpone.
if (!store.prerenderState || store.isUnstableCacheCallback) return

postponeWithTracking(store.prerenderState, expression, store.urlPathname)
postponeWithTracking(store.prerenderState, expression, store.url.pathname)
}

function postponeWithTracking(
Expand Down
13 changes: 0 additions & 13 deletions packages/next/src/server/app-render/validate-url.test.ts

This file was deleted.

18 changes: 0 additions & 18 deletions packages/next/src/server/app-render/validate-url.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import { createPrerenderState } from '../../server/app-render/dynamic-rendering'
import type { FetchMetric } from '../base-http'

export type StaticGenerationContext = {
urlPathname: string
/**
* The URL of the request. This only specifies the pathname and the search
* part of the URL. The other parts aren't accepted so they shouldn't be used.
*/
url: { pathname: string; search?: string }
requestEndedState?: { ended?: boolean }
renderOpts: {
incrementalCache?: IncrementalCache
Expand Down Expand Up @@ -51,7 +55,7 @@ export const StaticGenerationAsyncStorageWrapper: AsyncStorageWrapper<
> = {
wrap<Result>(
storage: AsyncLocalStorage<StaticGenerationStore>,
{ urlPathname, renderOpts, requestEndedState }: StaticGenerationContext,
{ url, renderOpts, requestEndedState }: StaticGenerationContext,
callback: (store: StaticGenerationStore) => Result
): Result {
/**
Expand Down Expand Up @@ -83,7 +87,13 @@ export const StaticGenerationAsyncStorageWrapper: AsyncStorageWrapper<

const store: StaticGenerationStore = {
isStaticGeneration,
urlPathname,
// Rather than just using the whole `url` here, we pull the parts we want
// to ensure we don't use parts of the URL that we shouldn't. This also
// lets us avoid requiring an empty string for `search` in the type.
url: {
pathname: url.pathname,
search: url.search ?? '',
},
pagePath: renderOpts.originalPathname,
incrementalCache:
// we fallback to a global incremental cache for edge-runtime locally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export class AppRouteRouteModule extends RouteModule<

// Get the context for the static generation.
const staticGenerationContext: StaticGenerationContext = {
urlPathname: rawRequest.nextUrl.pathname,
url: rawRequest.nextUrl,
renderOpts: context.renderOpts,
}

Expand Down
23 changes: 12 additions & 11 deletions packages/next/src/server/lib/patch-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ const getDerivedTags = (pathname: string): string[] => {

export function addImplicitTags(staticGenerationStore: StaticGenerationStore) {
const newTags: string[] = []
const { pagePath, urlPathname } = staticGenerationStore
const {
pagePath,
url: { pathname },
} = staticGenerationStore

if (!Array.isArray(staticGenerationStore.tags)) {
staticGenerationStore.tags = []
Expand All @@ -147,10 +150,8 @@ export function addImplicitTags(staticGenerationStore: StaticGenerationStore) {
}
}

if (urlPathname) {
const parsedPathname = new URL(urlPathname, 'http://n').pathname

const tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${parsedPathname}`
if (pathname) {
const tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname}`
if (!staticGenerationStore.tags?.includes(tag)) {
staticGenerationStore.tags.push(tag)
}
Expand Down Expand Up @@ -331,7 +332,7 @@ function createPatchedFetcher(
// we only want to warn if the user is explicitly setting a cache value
if (!(isRequestInput && _cache === 'default')) {
Log.warn(
`fetch for ${fetchUrl} on ${staticGenerationStore.urlPathname} specified "cache: ${_cache}" and "revalidate: ${curRevalidate}", only one should be specified.`
`fetch for ${fetchUrl} on ${staticGenerationStore.url.pathname} specified "cache: ${_cache}" and "revalidate: ${curRevalidate}", only one should be specified.`
)
}
_cache = undefined
Expand Down Expand Up @@ -360,7 +361,7 @@ function createPatchedFetcher(

revalidate = validateRevalidate(
curRevalidate,
staticGenerationStore.urlPathname
staticGenerationStore.url.pathname
)

const _headers = getRequestMeta('headers')
Expand Down Expand Up @@ -686,8 +687,8 @@ function createPatchedFetcher(

if (!staticGenerationStore.forceStatic && cache === 'no-store') {
const dynamicUsageReason = `no-store fetch ${input}${
staticGenerationStore.urlPathname
? ` ${staticGenerationStore.urlPathname}`
staticGenerationStore.url.pathname
? ` ${staticGenerationStore.url.pathname}`
: ''
}`

Expand Down Expand Up @@ -722,8 +723,8 @@ function createPatchedFetcher(
next.revalidate === 0
) {
const dynamicUsageReason = `revalidate: 0 fetch ${input}${
staticGenerationStore.urlPathname
? ` ${staticGenerationStore.urlPathname}`
staticGenerationStore.url.pathname
? ` ${staticGenerationStore.url.pathname}`
: ''
}`

Expand Down
5 changes: 1 addition & 4 deletions packages/next/src/server/web/spec-extension/revalidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
NEXT_CACHE_IMPLICIT_TAG_ID,
NEXT_CACHE_SOFT_TAG_MAX_LENGTH,
} from '../../../lib/constants'
import { getPathname } from '../../../lib/url'
import { staticGenerationAsyncStorage } from '../../../client/components/static-generation-async-storage.external'

/**
Expand Down Expand Up @@ -51,9 +50,7 @@ function revalidate(tag: string, expression: string) {

if (store.isUnstableCacheCallback) {
throw new Error(
`Route ${getPathname(
store.urlPathname
)} used "${expression}" inside a function cached with "unstable_cache(...)" which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
`Route ${store.url.pathname} used "${expression}" inside a function cached with "unstable_cache(...)" which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ export function unstable_cache<T extends Callback>(
// when the unstable_cache call is revalidated
fetchCache: 'force-no-store',
isUnstableCacheCallback: true,
urlPathname: '/',
url: { pathname: '/', search: '' },
isStaticGeneration: false,
prerenderState: null,
},
Expand Down
Loading

0 comments on commit 6119547

Please sign in to comment.