♻️ refactor(server): rename hono-runtime client to backend-proxy; drop the redundant binding route

The Next-side client is now a general forwarding layer for every
(backend) shell, not a POC binding — rename src/server/hono-runtime ->
src/server/backend-proxy and fetchHonoRuntime -> fetchBackendRuntime
(55 call sites). The /hono-runtime/[...path] prefix route is redundant
since all real routes forward directly; removed along with its guard
exception.
This commit is contained in:
Innei
2026-06-10 17:50:24 +08:00
parent f4d0afe3d3
commit 7eee9518ca
59 changed files with 111 additions and 189 deletions
+2 -2
View File
@@ -32,10 +32,10 @@ The package's exports resolve via the `~server/*` alias (`apps/server/src/*`); `
Every `src/app/(backend)/**/route.ts` is a thin forwarder into this package:
- In dev, `fetchHonoRuntime` proxies each request to the standalone Hono server (`LOBE_DEV_HONO_TARGET`, default `http://localhost:3011`).
- In dev, `fetchBackendRuntime` (`src/server/backend-proxy/client.ts`) proxies each request to the standalone Hono server (`LOBE_DEV_HONO_TARGET`, default `http://localhost:3011`).
- In production, it loads the vite-built `apps/server/dist/index.js` in-process via an opaque runtime `require` (override with `LOBE_HONO_DIST_ENTRY`), so the backend never passes through `next build`.
- Route file paths, HTTP method export names, and segment config (`maxDuration`, `dynamic`) are contractual — the cloud repo re-exports them by path. `src/app/(backend)/route-shell.guard.test.ts` enforces that route files stay logic-free.
- Exceptions: `webapi/revalidate` (Next ISR machinery) and `hono-runtime/[...path]` (the binding route itself).
- Exception: `webapi/revalidate` (Next ISR machinery).
The root `build` / `build:raw` scripts run `build:hono` first so the dist always pairs with the Next build.
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -1,29 +0,0 @@
// @vitest-environment node
import { afterEach, describe, expect, it, vi } from 'vitest';
import { GET } from './route';
describe('Next Hono binding route', () => {
afterEach(() => {
vi.unstubAllGlobals();
vi.unstubAllEnvs();
});
it('forwards the rewritten request path into the configured Hono dev runtime', async () => {
vi.stubEnv('NODE_ENV', 'development');
vi.stubEnv('LOBE_DEV_HONO_TARGET', 'http://localhost:3011');
const fetchSpy = vi.fn(async (request: Request) => {
expect(request.url).toBe('http://localhost:3011/api/version');
return Response.json({ version: '2.1.56' });
});
vi.stubGlobal('fetch', fetchSpy);
const response = await GET(new Request('http://localhost:3010/hono-runtime/api/version'));
expect(response.status).toBe(200);
expect(response.headers.get('x-lobe-dev-hono-binding')).toBe('next-catch-all');
await expect(response.json()).resolves.toEqual({ version: '2.1.56' });
expect(fetchSpy).toHaveBeenCalledTimes(1);
});
});
@@ -1,47 +0,0 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
const HONO_BINDING_PREFIX = '/hono-runtime';
const HONO_BINDING_HEADER = 'x-lobe-dev-hono-binding';
const rewriteHonoBindingRequest = (request: Request) => {
const url = new URL(request.url);
if (!url.pathname.startsWith(HONO_BINDING_PREFIX)) return request;
const pathname = url.pathname.slice(HONO_BINDING_PREFIX.length);
url.pathname = pathname || '/';
const init: RequestInit & { duplex?: 'half' } = {
headers: request.headers,
method: request.method,
redirect: request.redirect,
signal: request.signal,
};
if (request.method !== 'GET' && request.method !== 'HEAD') {
init.body = request.body;
init.duplex = 'half';
}
return new Request(url, init);
};
const handler = async (request: Request) => {
const response = await fetchHonoRuntime(rewriteHonoBindingRequest(request));
const headers = new Headers(response.headers);
headers.set(HONO_BINDING_HEADER, 'next-catch-all');
return new Response(response.body, {
headers,
status: response.status,
statusText: response.statusText,
});
};
export const DELETE = handler;
export const GET = handler;
export const HEAD = handler;
export const OPTIONS = handler;
export const PATCH = handler;
export const POST = handler;
export const PUT = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const PUT = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -15,8 +15,6 @@ const BACKEND_DIR = join(__dirname);
/** Routes allowed to keep Next-only logic, with the reason. */
const EXCEPTIONS = new Set([
// POC binding route: forwards into the standalone Hono runtime itself
'hono-runtime/[...path]/route.ts',
// revalidateTag is Next ISR machinery and cannot leave the Next runtime
'webapi/revalidate/route.ts',
]);
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
+2 -2
View File
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,6 +1,6 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
+2 -2
View File
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const POST = handler;
@@ -1,5 +1,5 @@
import { fetchHonoRuntime } from '@/server/hono-runtime/client';
import { fetchBackendRuntime } from '@/server/backend-proxy/client';
const handler = (req: Request) => fetchHonoRuntime(req);
const handler = (req: Request) => fetchBackendRuntime(req);
export const GET = handler;
@@ -92,7 +92,7 @@ const loadProductionHonoApp = () => {
return app;
};
export const fetchHonoRuntime = async (request: Request) => {
export const fetchBackendRuntime = async (request: Request) => {
const devTarget = process.env.LOBE_DEV_HONO_TARGET;
if (process.env.NODE_ENV !== 'production' && devTarget) {