0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-03 22:29:08 -05:00

fix: dynamically imported middlewares

This commit is contained in:
Princesseuh 2024-09-24 09:51:47 +01:00
parent 7fa6f782cd
commit d1e5977533
No known key found for this signature in database
GPG key ID: 105BBD6D57F2B0C0
2 changed files with 101 additions and 73 deletions

View file

@ -9,9 +9,12 @@ import type {
SSRManifest,
SSRResult,
} from '../types/public/internal.js';
import { createOriginCheckMiddleware } from './app/middlewares.js';
import { AstroError } from './errors/errors.js';
import { AstroErrorData } from './errors/index.js';
import type { Logger } from './logger/core.js';
import { NOOP_MIDDLEWARE_FN } from './middleware/noop-middleware.js';
import { sequence } from './middleware/sequence.js';
import { RouteCache } from './render/route-cache.js';
import { createDefaultRoutes } from './routing/default.js';
@ -22,82 +25,107 @@ import { createDefaultRoutes } from './routing/default.js';
* Thus, a `Pipeline` is created once at process start and then used by every `RenderContext`.
*/
export abstract class Pipeline {
readonly internalMiddleware: MiddlewareHandler[];
constructor(
readonly logger: Logger,
readonly manifest: SSRManifest,
/**
* "development" or "production"
*/
readonly mode: RuntimeMode,
readonly renderers: SSRLoadedRenderer[],
readonly resolve: (s: string) => Promise<string>,
/**
* Based on Astro config's `output` option, `true` if "server" or "hybrid".
*/
readonly serverLike: boolean,
readonly streaming: boolean,
/**
* Used to provide better error messages for `Astro.clientAddress`
*/
readonly adapterName = manifest.adapterName,
readonly clientDirectives = manifest.clientDirectives,
readonly inlinedScripts = manifest.inlinedScripts,
readonly compressHTML = manifest.compressHTML,
readonly i18n = manifest.i18n,
readonly middleware = manifest.middleware,
readonly routeCache = new RouteCache(logger, mode),
/**
* Used for `Astro.site`.
*/
readonly site = manifest.site ? new URL(manifest.site) : undefined,
readonly callSetGetEnv = true,
/**
* Array of built-in, internal, routes.
* Used to find the route module
*/
readonly defaultRoutes = createDefaultRoutes(manifest),
) {
this.internalMiddleware = [];
// We do use our middleware only if the user isn't using the manual setup
if (i18n?.strategy !== 'manual') {
this.internalMiddleware.push(
createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat),
);
readonly internalMiddleware: MiddlewareHandler[];
resolvedMiddleware: MiddlewareHandler | undefined = undefined;
constructor(
readonly logger: Logger,
readonly manifest: SSRManifest,
/**
* "development" or "production"
*/
readonly mode: RuntimeMode,
readonly renderers: SSRLoadedRenderer[],
readonly resolve: (s: string) => Promise<string>,
/**
* Based on Astro config's `output` option, `true` if "server" or "hybrid".
*/
readonly serverLike: boolean,
readonly streaming: boolean,
/**
* Used to provide better error messages for `Astro.clientAddress`
*/
readonly adapterName = manifest.adapterName,
readonly clientDirectives = manifest.clientDirectives,
readonly inlinedScripts = manifest.inlinedScripts,
readonly compressHTML = manifest.compressHTML,
readonly i18n = manifest.i18n,
readonly middleware = manifest.middleware,
readonly routeCache = new RouteCache(logger, mode),
/**
* Used for `Astro.site`.
*/
readonly site = manifest.site ? new URL(manifest.site) : undefined,
readonly callSetGetEnv = true,
/**
* Array of built-in, internal, routes.
* Used to find the route module
*/
readonly defaultRoutes = createDefaultRoutes(manifest),
) {
this.internalMiddleware = [];
// We do use our middleware only if the user isn't using the manual setup
if (i18n?.strategy !== 'manual') {
this.internalMiddleware.push(
createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat),
);
}
// In SSR, getSecret should fail by default. Setting it here will run before the
// adapter override.
if (callSetGetEnv && manifest.envGetSecretEnabled) {
setGetEnv(() => {
throw new AstroError(AstroErrorData.EnvUnsupportedGetSecret);
}, true);
}
}
// In SSR, getSecret should fail by default. Setting it here will run before the
// adapter override.
if (callSetGetEnv && manifest.envGetSecretEnabled) {
setGetEnv(() => {
throw new AstroError(AstroErrorData.EnvUnsupportedGetSecret);
}, true);
abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
abstract componentMetadata(
routeData: RouteData,
): Promise<SSRResult['componentMetadata']> | void;
/**
* It attempts to retrieve the `RouteData` that matches the input `url`, and the component that belongs to the `RouteData`.
*
* ## Errors
*
* - if not `RouteData` is found
*
* @param {RewritePayload} rewritePayload The payload provided by the user
* @param {Request} request The original request
*/
abstract tryRewrite(
rewritePayload: RewritePayload,
request: Request,
): Promise<TryRewriteResult>;
/**
* Tells the pipeline how to retrieve a component give a `RouteData`
* @param routeData
*/
abstract getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
/**
* Resolves the middleware from the manifest, and returns the `onRequest` function. If `onRequest` isn't there,
* it returns a no-op function
*/
async getMiddleware(): Promise<MiddlewareHandler> {
if (this.resolvedMiddleware) {
return this.resolvedMiddleware;
} else {
const middlewareInstance = await this.middleware();
const onRequest = middlewareInstance.onRequest ?? NOOP_MIDDLEWARE_FN;
if (this.manifest.checkOrigin) {
this.resolvedMiddleware = sequence(createOriginCheckMiddleware(), onRequest);
} else {
this.resolvedMiddleware = onRequest;
}
return this.resolvedMiddleware;
}
}
}
abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
/**
* It attempts to retrieve the `RouteData` that matches the input `url`, and the component that belongs to the `RouteData`.
*
* ## Errors
*
* - if not `RouteData` is found
*
* @param {RewritePayload} rewritePayload The payload provided by the user
* @param {Request} request The original request
*/
abstract tryRewrite(rewritePayload: RewritePayload, request: Request): Promise<TryRewriteResult>;
/**
* Tells the pipeline how to retrieve a component give a `RouteData`
* @param routeData
*/
abstract getComponentByRoute(routeData: RouteData): Promise<ComponentInstance>;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface HeadElements extends Pick<SSRResult, 'scripts' | 'styles' | 'links'> {}

View file

@ -1,3 +1,3 @@
import type { MiddlewareHandler } from '../../@types/astro.js';
import type { MiddlewareHandler } from "../../types/public/common.js";
export const NOOP_MIDDLEWARE_FN: MiddlewareHandler = (_, next) => next();