diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 51a76157c23f5..5e94d6c6bb744 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -5,13 +5,11 @@ import type { SSRElement, SSRManifest, } from '../../@types/astro.js'; -import { createI18nMiddleware, i18nPipelineHook } from '../../i18n/middleware.js'; import { REROUTE_DIRECTIVE_HEADER } from '../../runtime/server/consts.js'; import type { SinglePageBuiltModule } from '../build/types.js'; import { getSetCookiesFromResponse } from '../cookies/index.js'; import { consoleLogDestination } from '../logger/console.js'; import { AstroIntegrationLogger, Logger } from '../logger/core.js'; -import { sequence } from '../middleware/index.js'; import { appendForwardSlash, collapseDuplicateSlashes, @@ -20,7 +18,7 @@ import { removeTrailingForwardSlash, } from '../path.js'; import { RedirectSinglePageBuiltModule } from '../redirects/index.js'; -import { Environment, createRenderContext, type RenderContext } from '../render/index.js'; +import { createRenderContext, type RenderContext } from '../render/index.js'; import { RouteCache } from '../render/route-cache.js'; import { createAssetLink, @@ -325,18 +323,7 @@ export class App { ); let response; try { - const i18nMiddleware = createI18nMiddleware( - this.#manifest.i18n, - this.#manifest.base, - this.#manifest.trailingSlash, - this.#manifest.buildFormat - ); - const pipeline = this.#environment.createPipeline({ - pathname, - renderContext, - hookBefore: i18nPipelineHook, - middleware: sequence(i18nMiddleware, this.#manifest.middleware) - }) + const pipeline = this.#environment.createPipeline({ pathname, renderContext }); response = await pipeline.renderRoute(pageModule); } catch (err: any) { this.#logger.error(null, err.stack || err.message || String(err)); diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 0bac1e7a14f95..b7bcb182d0423 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -29,13 +29,11 @@ import { removeLeadingForwardSlash, removeTrailingForwardSlash, } from '../../core/path.js'; -import { createI18nMiddleware, i18nPipelineHook } from '../../i18n/middleware.js'; import { runHookBuildGenerated } from '../../integrations/index.js'; import { getOutputDirectory, isServerLikeOutput } from '../../prerender/utils.js'; import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js'; import type { SSRManifestI18n } from '../app/types.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; -import { sequence } from '../middleware/index.js'; import { routeIsFallback } from '../redirects/helpers.js'; import { RedirectSinglePageBuiltModule, @@ -557,17 +555,9 @@ async function generatePath( routing: i18n?.routing, defaultLocale: i18n?.defaultLocale, }); - const i18nMiddleware = createI18nMiddleware( - manifest.i18n, - manifest.base, - manifest.trailingSlash, - manifest.buildFormat - ) const pipeline = environment.createPipeline({ pathname, renderContext, - hookBefore: i18nPipelineHook, - middleware: sequence(i18nMiddleware, manifest.middleware) }) let body: string | Uint8Array; diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index d57a89aadc866..fa140ba133ff2 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -143,7 +143,7 @@ export async function callEndpoint( mod: EndpointHandler, env: Environment, ctx: RenderContext, - onRequest: MiddlewareHandler | undefined + onRequest: MiddlewareHandler ): Promise { const context = createAPIContext({ request: ctx.request, @@ -156,14 +156,9 @@ export async function callEndpoint( locales: ctx.locales, }); - let response; - if (onRequest) { - response = await callMiddleware(onRequest, context, async () => { - return await renderEndpoint(mod, context, env.serverLike, env.logger); - }); - } else { - response = await renderEndpoint(mod, context, env.serverLike, env.logger); - } + const response = await callMiddleware(onRequest, context, async () => { + return await renderEndpoint(mod, context, env.serverLike, env.logger); + }); attachCookiesToResponse(response, context.cookies); return response; diff --git a/packages/astro/src/core/pipeline.ts b/packages/astro/src/core/pipeline.ts index d8334df531ece..c04a0444f241e 100644 --- a/packages/astro/src/core/pipeline.ts +++ b/packages/astro/src/core/pipeline.ts @@ -4,8 +4,6 @@ import { callMiddleware } from './middleware/callMiddleware.js'; import { renderPage } from './render/core.js'; import { type Environment, type RenderContext } from './render/index.js'; -export type PipelineHookFunction = (ctx: RenderContext, mod: ComponentInstance | undefined) => void; - /** * This is the basic class of a pipeline. * @@ -18,35 +16,11 @@ export class Pipeline { readonly request: Request, readonly pathname: string, readonly renderContext: RenderContext, - readonly hookBefore: PipelineHookFunction = () => {}, - private middleware = environment.middleware + readonly middleware = environment.middleware ) {} - /** - * A middleware function that will be called before each request. - */ - setMiddlewareFunction(middleware: MiddlewareHandler) { - this.middleware = middleware; - } - - /** - * Removes the current middleware function. Subsequent requests won't trigger any middleware. - */ - unsetMiddlewareFunction() { - this.middleware = (_, next) => next(); - } - /** * The main function of the pipeline. Use this function to render any route known to Astro; - */ - async renderRoute( - componentInstance: ComponentInstance | undefined - ): Promise { - this.hookBefore(this.renderContext, componentInstance); - return await this.#tryRenderRoute(componentInstance, this.middleware); - } - - /** * It attempts to render a route. A route can be a: * - page * - redirect @@ -56,10 +30,10 @@ export class Pipeline { * * It throws an error if the page can't be rendered. */ - async #tryRenderRoute( - mod: Readonly | undefined, - onRequest?: MiddlewareHandler + async renderRoute( + componentInstance: ComponentInstance | undefined ): Promise { + Reflect.set(this.renderContext.request, Symbol.for('astro.routeData'), this.renderContext.route) const { renderContext, environment } = this; const { defaultLocale, locales, params, props, request, routing: routingStrategy } = renderContext; const { adapterName, site } = environment; @@ -69,26 +43,15 @@ export class Pipeline { case 'page': case 'fallback': case 'redirect': { - if (onRequest) { - return await callMiddleware(onRequest, apiContext, () => { - return renderPage({ - mod, - renderContext, - env: environment, - cookies: apiContext.cookies, - }); - }); - } else { - return await renderPage({ - mod, + return await callMiddleware(this.middleware, apiContext, () => renderPage({ + mod: componentInstance, renderContext, env: environment, cookies: apiContext.cookies, - }); - } + })) } case 'endpoint': { - return await callEndpoint(mod as any as EndpointHandler, environment, renderContext, onRequest); + return await callEndpoint(componentInstance as any as EndpointHandler, environment, renderContext, this.middleware); } default: throw new Error(`Couldn't find route of type [${renderContext.route.type}]`); diff --git a/packages/astro/src/core/render/environment.ts b/packages/astro/src/core/render/environment.ts index eecd1247a2504..1d8dc7723da5c 100644 --- a/packages/astro/src/core/render/environment.ts +++ b/packages/astro/src/core/render/environment.ts @@ -1,8 +1,10 @@ import type { MiddlewareHandler, RuntimeMode, SSRLoadedRenderer, SSRManifest } from '../../@types/astro.js'; import type { Logger } from '../logger/core.js'; import type { RouteCache } from './route-cache.js'; -import { Pipeline, type PipelineHookFunction } from '../pipeline.js'; +import { Pipeline } from '../pipeline.js'; import type { RenderContext } from './context.js'; +import { createI18nMiddleware } from '../../i18n/middleware.js'; +import { sequence } from '../middleware/index.js'; /** * The environment represents the static parts of rendering that do not change between requests. @@ -10,6 +12,8 @@ import type { RenderContext } from './context.js'; * Thus, an environment is created once at process start and then used by every pipeline. */ export abstract class Environment { + readonly internalMiddleware: MiddlewareHandler; + constructor( readonly logger: Logger, readonly manifest: SSRManifest, @@ -37,9 +41,11 @@ export abstract class Environment { * Used for `Astro.site`. */ readonly site = manifest.site, - ) {} + ) { + this.internalMiddleware = createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat); + } - createPipeline({ renderContext, pathname, hookBefore, middleware }: { pathname: string; renderContext: RenderContext; hookBefore?: PipelineHookFunction; middleware?: MiddlewareHandler }) { - return new Pipeline(this, renderContext.locals ?? {}, renderContext.request, pathname, renderContext, hookBefore, middleware); + createPipeline({ renderContext, pathname, middleware }: { pathname: string; renderContext: RenderContext; middleware?: MiddlewareHandler }) { + return new Pipeline(this, renderContext.locals ?? {}, renderContext.request, pathname, renderContext, sequence(this.internalMiddleware, middleware ?? this.middleware)); } } diff --git a/packages/astro/src/core/render/index.ts b/packages/astro/src/core/render/index.ts index 0b9a732761317..4c262477f3131 100644 --- a/packages/astro/src/core/render/index.ts +++ b/packages/astro/src/core/render/index.ts @@ -19,8 +19,4 @@ export interface SSROptions { request: Request; /** optional, in case we need to render something outside a dev server */ route: RouteData; - /** - * Optional middlewares - */ - middleware?: AstroMiddlewareInstance; } diff --git a/packages/astro/src/i18n/middleware.ts b/packages/astro/src/i18n/middleware.ts index 9fabff13af411..a65d712fc45c3 100644 --- a/packages/astro/src/i18n/middleware.ts +++ b/packages/astro/src/i18n/middleware.ts @@ -1,12 +1,5 @@ import { appendForwardSlash, joinPaths } from '@astrojs/internal-helpers/path'; -import type { - APIContext, - Locales, - MiddlewareHandler, - RouteData, - SSRManifest, -} from '../@types/astro.js'; -import type { PipelineHookFunction } from '../core/pipeline.js'; +import type { APIContext, Locales, MiddlewareHandler, RouteData, SSRManifest } from '../@types/astro.js'; import { getPathByLocale, normalizeTheLocale } from './index.js'; import { shouldAppendForwardSlash } from '../core/build/util.js'; import { ROUTE_DATA_SYMBOL } from '../core/constants.js'; @@ -214,13 +207,6 @@ export function createI18nMiddleware( }; } -/** - * This pipeline hook attaches a `RouteData` object to the `Request` - */ -export const i18nPipelineHook: PipelineHookFunction = (ctx) => { - Reflect.set(ctx.request, routeDataSymbol, ctx.route); -}; - /** * Checks if the current locale doesn't belong to a configured domain * @param i18n diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index ee775918c4efd..7251db235b9ed 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -13,7 +13,6 @@ import { getInfoOutput } from '../cli/info/index.js'; import { ASTRO_VERSION } from '../core/constants.js'; import { AstroErrorData, isAstroError } from '../core/errors/index.js'; import { req } from '../core/messages.js'; -import { sequence } from '../core/middleware/index.js'; import { loadMiddleware } from '../core/middleware/loadMiddleware.js'; import { createRenderContext, @@ -25,7 +24,6 @@ import { createRequest } from '../core/request.js'; import { matchAllRoutes } from '../core/routing/index.js'; import { isPage, resolveIdToUrl } from '../core/util.js'; import { normalizeTheLocale } from '../i18n/index.js'; -import { createI18nMiddleware, i18nPipelineHook } from '../i18n/middleware.js'; import { getSortedPreloadedMatches } from '../prerender/routing.js'; import { isServerLikeOutput } from '../prerender/utils.js'; import { PAGE_SCRIPT_ID } from '../vite-plugin-scripts/index.js'; @@ -183,8 +181,6 @@ export async function handleRoute({ let mod: ComponentInstance | undefined = undefined; let options: SSROptions | undefined = undefined; let route: RouteData; - const middleware = await loadMiddleware(environment.loader); - const onRequest: MiddlewareHandler = middleware.onRequest if (!matchedRoute) { if (config.i18n) { @@ -274,7 +270,6 @@ export async function handleRoute({ pathname, request, route, - middleware, }; mod = options.preload; @@ -301,17 +296,10 @@ export async function handleRoute({ defaultLocale: i18n?.defaultLocale, }); } - const i18Middleware = createI18nMiddleware( - manifest.i18n, - config.base, - config.trailingSlash, - config.build.format - ); const pipeline = environment.createPipeline({ pathname, renderContext, - hookBefore: i18nPipelineHook, - middleware: sequence(i18Middleware, onRequest), + middleware: (await loadMiddleware(environment.loader)).onRequest, }); let response = await pipeline.renderRoute(mod);