Skip to content

Commit 5fc70f4

Browse files
committed
refactor: support middleware in entrypoint
1 parent 1fcab24 commit 5fc70f4

16 files changed

Lines changed: 275 additions & 162 deletions

File tree

packages/astro/dev-only.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,9 @@ declare module 'virtual:astro:renderers' {
3838
import type { AstroRenderer } from './src/index.js';
3939
export const renderers: AstroRenderer[];
4040
}
41+
42+
declare module 'virtual:astro:middleware' {
43+
import type { AstroMiddlewareInstance } from './src/index.js';
44+
const middleware: AstroMiddlewareInstance;
45+
export default middleware;
46+
}

packages/astro/src/core/app/dev/app.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ import { DevPipeline } from './pipeline.js';
1212
export class DevApp extends BaseApp<DevPipeline> {
1313
logger: Logger;
1414
currentRenderContext: RenderContext | undefined = undefined;
15-
constructor(manifest: SSRManifest, streaming = true, logger: Logger, routesList: RoutesList) {
15+
constructor(manifest: SSRManifest, streaming = true, logger: Logger) {
1616
super(manifest, streaming, logger);
1717
this.logger = logger;
18-
this.manifestData = routesList;
1918
}
2019

2120
createPipeline(streaming: boolean, manifest: SSRManifest, logger: Logger): DevPipeline {

packages/astro/src/core/app/entrypoint.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,27 @@ import { App } from './app.js';
55
import type { BaseApp } from './base.js';
66
import { DevApp } from './dev/app.js';
77
import { createConsoleLogger } from './logging.js';
8+
import type { SSRManifest } from './types.js';
89

910
const actions = async () => {
1011
return await import('virtual:astro:actions/entrypoint');
1112
};
12-
const manifest = Object.assign(serializedManifest, { renderers, actions });
13+
14+
const middleware = async () => {
15+
return await import('virtual:astro:middleware');
16+
};
17+
18+
const manifest: SSRManifest = Object.assign(serializedManifest, {
19+
renderers,
20+
actions,
21+
middleware,
22+
routes,
23+
});
1324

1425
export function getApp(dev = import.meta.env.DEV): BaseApp {
1526
if (dev) {
1627
const logger = createConsoleLogger('debug');
17-
return new DevApp(manifest, true, logger, { routes: routes.map((r) => r.routeData) });
28+
return new DevApp(manifest, true, logger);
1829
} else {
1930
return new App(manifest);
2031
}

packages/astro/src/core/app/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Driver } from 'unstorage';
12
import type { ZodType } from 'zod';
23
import type { ActionAccept, ActionClient } from '../../actions/runtime/server.js';
34
import type { ComponentInstance, SerializedRouteData } from '../../types/astro.js';
@@ -8,6 +9,8 @@ import type {
89
Locales,
910
RemotePattern,
1011
ResolvedSessionConfig,
12+
SessionConfig,
13+
SessionDriverName,
1114
} from '../../types/public/config.js';
1215
import type {
1316
RouteData,
@@ -84,6 +87,7 @@ export type SSRManifest = {
8487
i18n: SSRManifestI18n | undefined;
8588
middleware?: () => Promise<AstroMiddlewareInstance> | AstroMiddlewareInstance;
8689
actions?: () => Promise<SSRActions> | SSRActions;
90+
sessionDriver?: (config: SessionConfig<SessionDriverName>['options']) => Promise<Driver> | Driver;
8791
checkOrigin: boolean;
8892
allowedDomains?: Partial<RemotePattern>[];
8993
sessionConfig?: ResolvedSessionConfig<any>;

packages/astro/src/core/base-pipeline.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export abstract class Pipeline {
135135
if (this.resolvedActions) {
136136
return this.resolvedActions;
137137
} else if (this.actions) {
138-
return await this.actions();
138+
return this.actions();
139139
}
140140
return NOOP_ACTIONS_MOD;
141141
}

packages/astro/src/core/build/plugins/plugin-ssr.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Plugin as VitePlugin } from 'vite';
22
import { ENTRYPOINT_VIRTUAL_MODULE_ID } from '../../../actions/consts.js';
33
import type { AstroAdapter } from '../../../types/public/integrations.js';
44
import { ASTRO_RENDERERS_MODULE_ID } from '../../../vite-plugin-renderers/index.js';
5-
import { MIDDLEWARE_MODULE_ID } from '../../middleware/vite-plugin.js';
5+
import { MIDDLEWARE_RESOLVED_MODULE_ID } from '../../middleware/vite-plugin.js';
66
import { routeIsRedirect } from '../../redirects/index.js';
77
import { VIRTUAL_ISLAND_MAP_ID } from '../../server-islands/vite-plugin-server-islands.js';
88
import { addRollupInput } from '../add-rollup-input.js';
@@ -101,7 +101,7 @@ function vitePluginSSR(
101101
}
102102
contents.push(`const pageMap = new Map([\n ${pageMap.join(',\n ')}\n]);`);
103103
exports.push(`export { pageMap }`);
104-
const middleware = await this.resolve(MIDDLEWARE_MODULE_ID);
104+
const middleware = await this.resolve(MIDDLEWARE_RESOLVED_MODULE_ID);
105105
const ssrCode = generateSSRCode(adapter, middleware!.id);
106106
imports.push(...ssrCode.imports);
107107
contents.push(...ssrCode.contents);

packages/astro/src/core/middleware/loadMiddleware.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { MiddlewareCantBeLoaded } from '../errors/errors-data.js';
22
import { AstroError } from '../errors/index.js';
33
import type { ModuleLoader } from '../module-loader/index.js';
4-
import { MIDDLEWARE_MODULE_ID } from './vite-plugin.js';
4+
import { MIDDLEWARE_RESOLVED_MODULE_ID } from './vite-plugin.js';
55

66
/**
77
* It accepts a module loader and the astro settings, and it attempts to load the middlewares defined in the configuration.
@@ -10,7 +10,7 @@ import { MIDDLEWARE_MODULE_ID } from './vite-plugin.js';
1010
*/
1111
export async function loadMiddleware(moduleLoader: ModuleLoader) {
1212
try {
13-
return await moduleLoader.import(MIDDLEWARE_MODULE_ID);
13+
return await moduleLoader.import(MIDDLEWARE_RESOLVED_MODULE_ID);
1414
} catch (error: any) {
1515
const astroError = new AstroError(MiddlewareCantBeLoaded, { cause: error });
1616
throw astroError;

packages/astro/src/core/middleware/vite-plugin.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { MissingMiddlewareForInternationalization } from '../errors/errors-data.
99
import { AstroError } from '../errors/index.js';
1010
import { normalizePath } from '../viteUtils.js';
1111

12-
export const MIDDLEWARE_MODULE_ID = '\0astro-internal:middleware';
12+
export const MIDDLEWARE_MODULE_ID = 'virtual:astro:middleware';
13+
export const MIDDLEWARE_RESOLVED_MODULE_ID = '\0' + MIDDLEWARE_MODULE_ID;
1314
const NOOP_MIDDLEWARE = '\0noop-middleware';
1415

1516
export function vitePluginMiddleware({ settings }: { settings: AstroSettings }): VitePlugin {
@@ -19,7 +20,10 @@ export function vitePluginMiddleware({ settings }: { settings: AstroSettings }):
1920
let userMiddlewareIsPresent = false;
2021

2122
return {
22-
name: '@astro/plugin-middleware',
23+
name: MIDDLEWARE_MODULE_ID,
24+
applyToEnvironment(environment) {
25+
return environment.name === 'ssr';
26+
},
2327
async resolveId(id) {
2428
if (id === MIDDLEWARE_MODULE_ID) {
2529
const middlewareId = await this.resolve(
@@ -28,9 +32,9 @@ export function vitePluginMiddleware({ settings }: { settings: AstroSettings }):
2832
userMiddlewareIsPresent = !!middlewareId;
2933
if (middlewareId) {
3034
resolvedMiddlewareId = middlewareId.id;
31-
return MIDDLEWARE_MODULE_ID;
35+
return MIDDLEWARE_RESOLVED_MODULE_ID;
3236
} else if (hasIntegrationMiddleware) {
33-
return MIDDLEWARE_MODULE_ID;
37+
return MIDDLEWARE_RESOLVED_MODULE_ID;
3438
} else {
3539
return NOOP_MIDDLEWARE;
3640
}
@@ -45,7 +49,7 @@ export function vitePluginMiddleware({ settings }: { settings: AstroSettings }):
4549
throw new AstroError(MissingMiddlewareForInternationalization);
4650
}
4751
return { code: 'export const onRequest = (_, next) => next()' };
48-
} else if (id === MIDDLEWARE_MODULE_ID) {
52+
} else if (id === MIDDLEWARE_RESOLVED_MODULE_ID) {
4953
if (!userMiddlewareIsPresent && settings.config.i18n?.routing === 'manual') {
5054
throw new AstroError(MissingMiddlewareForInternationalization);
5155
}
@@ -106,12 +110,12 @@ export function vitePluginMiddlewareBuild(
106110
name: '@astro/plugin-middleware-build',
107111

108112
options(options) {
109-
return addRollupInput(options, [MIDDLEWARE_MODULE_ID]);
113+
return addRollupInput(options, [MIDDLEWARE_RESOLVED_MODULE_ID]);
110114
},
111115

112116
writeBundle(_, bundle) {
113117
for (const [chunkName, chunk] of Object.entries(bundle)) {
114-
if (chunk.type !== 'asset' && chunk.facadeModuleId === MIDDLEWARE_MODULE_ID) {
118+
if (chunk.type !== 'asset' && chunk.facadeModuleId === MIDDLEWARE_RESOLVED_MODULE_ID) {
115119
const outputDirectory = getServerOutputDirectory(opts.settings);
116120
internals.middlewareEntryPoint = new URL(chunkName, outputDirectory);
117121
}

packages/integrations/cloudflare/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
"dependencies": {
4141
"@astrojs/internal-helpers": "workspace:*",
4242
"@astrojs/underscore-redirects": "workspace:*",
43-
"@cloudflare/vite-plugin": "^1.13.13",
44-
"@cloudflare/workers-types": "^4.20251011.0",
43+
"@cloudflare/vite-plugin": "^1.13.14",
44+
"@cloudflare/workers-types": "^4.20251014.0",
4545
"tinyglobby": "^0.2.15",
46-
"vite": "^7.1.7",
47-
"wrangler": "4.43.0"
46+
"vite": "^7.1.12",
47+
"wrangler": "4.44.0"
4848
},
4949
"peerDependencies": {
5050
"astro": "^5.7.0"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { defineMiddleware } from 'astro:middleware'
2+
3+
export const onRequest = defineMiddleware(async (ctx, next) => {
4+
const url = new URL(ctx.request.url);
5+
6+
if (url.pathname.includes("/mid/to-redirect")) {
7+
return ctx.redirect("/mid/from-redirect");
8+
}
9+
if (url.pathname.includes("/mid/to-rewrite")) {
10+
return ctx.rewrite("/mid/from-rewrite");
11+
}
12+
13+
14+
ctx.locals.getGreeting = () => {
15+
return `Hello from ${url.pathname}`;
16+
};
17+
18+
return next()
19+
})

0 commit comments

Comments
 (0)