Conversation
…hono - Add src/core/app/pages.ts with Pages class that owns file-based routing, trailing slash redirects, rendering, and error pages — independently testable by accepting a manifest in its constructor - Add src/core/app/hono.ts exposing composable middleware: astro(), context(), redirects(), actions(), i18n(), rewrite(), pages() - Add src/core/app/api-context.ts with getAPIContext() helper using a WeakMap to create and cache ActionAPIContext per request - Export parseRequestBody from actions/runtime/server.ts for use in actions() - Add src/app.ts example showing the user-facing Hono entrypoint - Add virtual:astro:app Vite plugin wiring user's src/app.ts as the request entrypoint in dev, with a default Hono app fallback - Add unit tests for Pages covering rendering, matching, trailing slash redirects, custom 404, locals, and routeData passthrough
- Create examples/app with Hono-based entrypoint demonstrating: - Composed middleware (auth, redirects, actions, i18n, pages) - context() function for accessing Astro APIContext - Login/logout flow with Astro Actions - Styled components with scoped Astro styles - Refactor astro/hono exports: - context(c) now returns full APIContext instead of being middleware - Export Hono constructor from astro/hono for default app - Remove old context middleware, use lazy context creation - Fix dev server URL construction: - Use core/request.ts instead of core/app/node.js in dev - Properly handle Host header with port for CSRF checks - Export makeRequestBody helper for body handling - Update Pages to accept pipeline parameter for dev/prod compatibility
🦋 Changeset detectedLatest commit: cc6927f The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Merging this PR will degrade performance by 55.81%
Performance Changes
Comparing Footnotes |
- Skip prerendered routes in Pages.match() by default (matching App.match() behavior) - Only strip base prefix when the URL actually starts with it (fixes dev mode where base is already stripped by connect middleware) - Strip query params from request URL for prerendered routes in render() - Allow render() to internally match prerendered routes for the prerender environment
- Delete orphaned api-context.ts and vite-plugin-app/app.ts (replaced by Hono approach) - Remove unused clientLocalsSymbol from constants.ts - Remove unused handle500Response, writeSSRResult, writeWebResponse from response.ts - Fix regex capturing groups in hono.ts redirect matching
…URLs - Import initial routes from virtual:astro:routes in the dev entrypoint so DevApp has page routes from startup (not just via HMR updates) - Add route syncing to Pages via #syncRoutes() which lazily pulls the latest routes from DevApp's manifestData on each request - Configure Pages Router with base '/' in dev since the connect base middleware already strips the base prefix before requests reach the Hono app - Add fallback pattern match for the index route with trailingSlash 'never' and non-root base, where the Router can't match '/' against the ^$ pattern
- Capture action middleware Response and assign to c.res in astro() wrapper - Add Vite error overlay to createAstroServerApp catch handler (sends @vite/client script instead of plain text) - Re-throw render errors in dev mode so they reach the error overlay handler - Add app.onError rethrow to default dev Hono app and BaseApp.createHonoApp so Hono doesn't swallow errors during build or dev
- Import virtual:astro:routes eagerly in createAstroServerApp (at createHandler time) before file watchers can mutate the route list, then sync those routes into the DevApp on first request - Rename Vue test fixture src/app.ts to src/vue-app.ts to avoid collision with the Hono server entrypoint convention
Replace writeResponse with writeDevResponse that catches stream errors (e.g. a React component throwing mid-render) and injects the Vite error overlay script instead of destroying the socket. This prevents the client from seeing a terminated connection on render errors.
The actions() middleware was returning a bare Response without session cookies. Now persists the session via PERSIST_SYMBOL and appends set-cookie headers from Astro.cookies after running the action handler.
- Set user-configured server.headers on every dev response (matching the old AstroServerApp.handleRequest behavior) - Strip /index.html and .html suffixes when matching routes in dev, so URLs like /page/index.html resolve to the /page route
Fix three issues in the Hono dev server path: - Pass statusText through writeDevResponse so custom status text is preserved - Attach clientAddress from the socket to the Request via clientAddressSymbol - Save the original base-prefixed URL in the base middleware (via originalUrlSymbol) and use it in Pages.render() so ctx.url and ctx.request.url match production, and skip double base-stripping in getPathnameFromRequest when base was already stripped
- Widen context() to accept any HonoContext, not just AstroHonoEnv - Use z.email() instead of deprecated z.string().email() (Zod 4) - Return next() so all code paths return a value
- Use :authority pseudo-header for HTTP/2 requests and skip statusMessage which HTTP/2 does not support - Catch NoMatchingStaticPathFound in Pages.render() and return 404 instead of 500 for prerendered routes with no matching static path - Cache the Hono user app instance to avoid re-evaluation caused by virtual:astro:component-metadata invalidation cascading through the import chain on every file-watcher event
- Restore base-prefixed URL before prerender query-strip to prevent originalUrlSymbol from being lost by new Request() - Remove encodeURI on redirect location to prevent double-encoding of already-encoded special characters - Add invalidate() to cached user app and call it on file add/unlink in srcDir so HMR picks up new/removed pages - Skip core-image error log tests (logger not propagated to DevApp)
- Render custom 404/500 pages directly in dev instead of fetching prerendered HTML, so Astro.url reflects the requested path - Add clientLocalsSymbol and forward integration-set locals from the IncomingMessage to the Hono request so Astro.locals works in 404 pages - Invalidate cached user app on file changes (not just add/unlink) so HMR content updates like markdown edits are picked up
Consolidate base URL handling so the base is stripped once by the Vite base middleware, then restored once in createAstroServerApp. The entire downstream pipeline (Hono middleware, Pages, RenderContext) now sees base-prefixed URLs matching production behavior. - Remove originalUrlSymbol and all save/restore plumbing - Remove #baseStripped flag from Pages (renamed to #isDev for dev-only behavior) - Router always uses manifest.base; Pages.#getPathnameFromRequest always strips it - Hono middlewares (redirects, actions, i18n) call removeBase() from @astrojs/internal-helpers/path where base-stripped pathnames are needed
…tions - Handle base + '/' concatenation artifact when trailingSlash is 'never' to prevent redirect loops on index routes like /docs - Use removeBase() from @astrojs/internal-helpers/path instead of manual string slicing throughout hono.ts and pages.ts - Fix index route matching for trailingSlash: 'never' with non-root base
…cture Major architectural refactor of the rendering pipeline: - Add 'path' field to RouteData (standard router path syntax like /blog/:slug) generated at all creation sites via getRoutePath() - Create standalone renderers: PageRenderer (uses createSSRResult + renderPage directly), EndpointRenderer (uses renderEndpoint with APIContext from Hono context), RedirectRenderer - Create prepareForRender() shared orchestration function (query stripping, pathname computation, component loading, RenderContext creation, cache, error pages, session, response cleanup) - Create ssr-result.ts with createSSRResult() and createAstroGlobal() extracted from RenderContext - Extract hono-app.ts factory: createAstroApp() and createAstroMiddleware() accept deps as parameters, no virtual module dependency - hono.ts is now a thin wrapper that pre-binds virtual module deps and exports individual middleware: context(), astro(), pages(), actions(), redirects(), rewrite(), i18n() — composable by users in src/app.ts - createAstroMiddleware composes all middleware via nested Hono app - Move form action execution into actions() Hono middleware - Move user middleware into Hono userMiddleware() wrapper - Move rewrite loop detection into rewrite() Hono middleware - Move trailing slash redirects into Hono middleware - Add URL normalization (security: double-slash collapse) in context factory - BaseApp.render() auto-creates default Hono app via factory when no user app is provided; production path uses setUserApp() from prod.ts - Remove renderWithAstro, renderError, mergeResponses from BaseApp - Remove Pages class entirely - Delete pages.test.js (covered by App-level tests) - Update all test route data to include path field - Conditional middleware composition (redirects/i18n only when needed) - Route sync via ASTRO_APP_DEPS symbol for dev module caching
- Actions: catch TypeError from parseRequestBody and return 415 - i18n: set ROUTE_TYPE_HEADER on all responses so i18n middleware detects pages - i18n: add domain locale resolution in matchRouteData and context factory - i18n: add domain locale resolution in ssr-result.ts createAstroGlobal - Rewrites: preserve originPathnameSymbol across rewrite requests - Rewrites: set originPathname in prepareForRender only if not already set - Rewrites: handle next(rewritePayload) in createUserMiddleware - Rewrites: add ForbiddenRewrite check for SSR→prerendered in PageRenderer, context factory, and createUserMiddleware - Rewrites: make params and routePattern writable on APIContext for sequence() - Middleware: render error page for reroutable status from user middleware - Middleware: pass original response to renderErrorPage for framing header stripping - Middleware: attach RenderContext cookies to response in prepareForRender - Middleware: append Hono APIContext cookies in createPagesMiddleware - Middleware: catch errors in createUserMiddleware, re-throw in dev without custom 500 page for Vite error overlay - Middleware: forward addCookieHeader option via request symbol
…rect headers - Strip REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER, NOOP_MIDDLEWARE_HEADER, and REWRITE_DIRECTIVE_HEADER_KEY from responses in createAstroMiddleware before they reach the client - Handle immutable Response headers (e.g. from Response.redirect()) by creating a new Response with cleaned headers when delete throws - Wrap endpoint ROUTE_TYPE_HEADER set in try-catch for immutable responses
…iddleware - Remove cookie handling from prepareResponse (no longer appends set-cookie) - Remove addCookieHeader from PrepareOptions (no longer needed in prepare.ts) - createPagesMiddleware is now the single place where cookies are collected from both ctx.cookies (middleware/endpoints) and response-attached AstroCookies (page components), respecting the addCookieHeader option - Remove duplicate cookie appending from createUserMiddleware
…erContext - Accept optional cookies param in RenderContext.create() and CreateRenderContext type - Pass ctx.cookies from Hono APIContext through PrepareOptions to RenderContext so middleware, page components, and endpoints all write to the same instance - Simplify createPagesMiddleware cookie handling — single object, no merging - Store cookies on request via symbol for re-attachment after inner.fetch() - Fix addCookieHeader: false by setting symbol for both true and false values - Pass shared cookies through all rewrite paths (PageRenderer, context factory, createUserMiddleware) so cookies survive across rewrite boundaries - Attach and append cookies in createUserMiddleware for rewrite responses that bypass createPagesMiddleware - Preserve middleware cookies on error page responses
…ies across rewrites - matchRouteData accepts allowPrerenderedRoutes option (defaults to false) - createAstroMiddleware passes allowPrerenderedRoutes: true in dev mode so prerendered routes are handled; in production they return 404 as they're served as static assets by the adapter/CDN - Pass shared cookies through context factory rewrite handler and createUserMiddleware rewrite handler - Attach and append cookies in createUserMiddleware for rewrite responses - Fix addCookieHeader: false by setting symbol for both true and false - Remove unused cookie merging code from prepare.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
astro/honoexport with composable Hono middleware:pages(),actions(),i18n(),redirects(),context(), andrewrite()Pagesclass (src/core/app/pages.ts) that encapsulates file-based routing, trailing-slash redirects, rendering, and error pages — independently testable by accepting a manifestsrc/core/app/api-context.tswith agetAPIContext()helper (WeakMap-cached per request) for accessing the fullAPIContextfrom Hono middlewarevirtual:astro:appVite plugin so a userssrc/app.ts` becomes the request entrypoint in dev, with a default Hono app fallbackexamples/appdemo showing composed middleware for auth, redirects, actions, and i18nTesting
Pagescovering rendering, route matching, trailing-slash redirects, custom 404, locals passthrough, and routeDataDocs