core: centralize error handling at root level for more predictable request processing

- Moves error handler registration to the root app instead of each sub-route
- Ensures consistent error responses across all API endpoints
- Removes unused imports and simplifies route composition
This commit is contained in:
Dax Raad
2026-04-09 22:47:11 -04:00
parent 52090bdf57
commit 84f0e63c1a
2 changed files with 9 additions and 16 deletions
+2 -4
View File
@@ -18,7 +18,6 @@ import { Command } from "../command"
import { Flag } from "../flag/flag"
import { QuestionRoutes } from "./routes/question"
import { PermissionRoutes } from "./routes/permission"
import { Snapshot } from "@/snapshot"
import { ProjectRoutes } from "./routes/project"
import { SessionRoutes } from "./routes/session"
import { PtyRoutes } from "./routes/pty"
@@ -45,9 +44,8 @@ const DEFAULT_CSP =
const csp = (hash = "") =>
`default-src 'self'; script-src 'self' 'wasm-unsafe-eval'${hash ? ` 'sha256-${hash}'` : ""}; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src 'self' data:`
export const InstanceRoutes = (upgrade: UpgradeWebSocket, app: Hono = new Hono()) =>
app
.onError(errorHandler(log))
export const InstanceRoutes = (upgrade: UpgradeWebSocket) =>
new Hono()
.use(WorkspaceRouterMiddleware(upgrade))
.route("/project", ProjectRoutes())
.route("/pty", PtyRoutes(upgrade))
+7 -12
View File
@@ -5,12 +5,10 @@ import { compress } from "hono/compress"
import { createNodeWebSocket } from "@hono/node-ws"
import { cors } from "hono/cors"
import { basicAuth } from "hono/basic-auth"
import type { UpgradeWebSocket } from "hono/ws"
import z from "zod"
import { Auth } from "../auth"
import { Flag } from "../flag/flag"
import { ProviderID } from "../provider/schema"
import { WorkspaceRouterMiddleware } from "./router"
import { errors } from "./error"
import { GlobalRoutes } from "./routes/global"
import { MDNS } from "./mdns"
@@ -44,9 +42,9 @@ export namespace Server {
export const Default = lazy(() => create({}))
export function ControlPlaneRoutes(upgrade: UpgradeWebSocket, app = new Hono(), opts?: { cors?: string[] }): Hono {
export function ControlPlaneRoutes(opts?: { cors?: string[] }): Hono {
const app = new Hono()
return app
.onError(errorHandler(log))
.use((c, next) => {
// Allow CORS preflight requests to succeed without auth.
// Browser clients sending Authorization headers will preflight with OPTIONS.
@@ -235,29 +233,26 @@ export namespace Server {
return c.json(true)
},
)
.use(WorkspaceRouterMiddleware(upgrade))
}
function create(opts: { cors?: string[] }) {
const app = new Hono()
const ws = createNodeWebSocket({ app })
return {
app: ControlPlaneRoutes(ws.upgradeWebSocket, app, opts),
app: app
.onError(errorHandler(log))
.route("/", ControlPlaneRoutes(opts))
.route("/", InstanceRoutes(ws.upgradeWebSocket)),
ws,
}
}
export function createApp(opts: { cors?: string[] }) {
return create(opts).app
}
export async function openapi() {
// Build a fresh app with all routes registered directly so
// hono-openapi can see describeRoute metadata (`.route()` wraps
// handlers when the sub-app has a custom errorHandler, which
// strips the metadata symbol).
const { app, ws } = create({})
InstanceRoutes(ws.upgradeWebSocket, app)
const { app } = create({})
const result = await generateSpecs(app, {
documentation: {
info: {