From 1bce2a29cc82c9ff0c1d65c706b41b4b5ba05d5b Mon Sep 17 00:00:00 2001 From: Hermes Date: Thu, 9 Apr 2026 20:54:13 -0500 Subject: [PATCH] =?UTF-8?q?Proxy=20API=20through=20Next.js=20route=20handl?= =?UTF-8?q?ers=20=E2=80=94=20eliminates=20CORS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/[...path]/route.ts | 63 +++++++++++++++++++++++++++++++++++++ app/health/route.ts | 16 ++++++++++ lib/api.ts | 4 +-- next.config.ts | 1 - public/icon-192.png | Bin 0 -> 546 bytes public/icon-512.png | Bin 0 -> 1879 bytes 6 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 app/api/[...path]/route.ts create mode 100644 app/health/route.ts create mode 100644 public/icon-192.png create mode 100644 public/icon-512.png diff --git a/app/api/[...path]/route.ts b/app/api/[...path]/route.ts new file mode 100644 index 0000000..30ea081 --- /dev/null +++ b/app/api/[...path]/route.ts @@ -0,0 +1,63 @@ +import { NextRequest, NextResponse } from "next/server"; + +const BACKEND = process.env.HERMES_BACKEND_URL || "http://127.0.0.1:8643"; + +export async function GET(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) { + const { path } = await params; + const target = path.join("/"); + const qs = req.nextUrl.search; + const res = await fetch(`${BACKEND}/api/${target}${qs}`); + const data = await res.text(); + return new NextResponse(data, { + status: res.status, + headers: { "content-type": res.headers.get("content-type") || "application/json" }, + }); +} + +export async function POST(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) { + const { path } = await params; + const target = path.join("/"); + const body = await req.text(); + const res = await fetch(`${BACKEND}/api/${target}`, { + method: "POST", + headers: { "content-type": "application/json" }, + body, + }); + const data = await res.text(); + return new NextResponse(data, { + status: res.status, + headers: { "content-type": res.headers.get("content-type") || "application/json" }, + }); +} + +export async function PATCH(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) { + const { path } = await params; + const target = path.join("/"); + const body = await req.text(); + const res = await fetch(`${BACKEND}/api/${target}`, { + method: "PATCH", + headers: { "content-type": "application/json" }, + body, + }); + const data = await res.text(); + return new NextResponse(data, { + status: res.status, + headers: { "content-type": res.headers.get("content-type") || "application/json" }, + }); +} + +export async function DELETE(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) { + const { path } = await params; + const target = path.join("/"); + const body = await req.text(); + const res = await fetch(`${BACKEND}/api/${target}`, { + method: "DELETE", + headers: { "content-type": "application/json" }, + body: body || undefined, + }); + const data = await res.text(); + return new NextResponse(data, { + status: res.status, + headers: { "content-type": res.headers.get("content-type") || "application/json" }, + }); +} diff --git a/app/health/route.ts b/app/health/route.ts new file mode 100644 index 0000000..2dd6f68 --- /dev/null +++ b/app/health/route.ts @@ -0,0 +1,16 @@ +import { NextResponse } from "next/server"; + +const BACKEND = process.env.HERMES_BACKEND_URL || "http://127.0.0.1:8643"; + +export async function GET() { + try { + const res = await fetch(`${BACKEND}/health`); + const data = await res.text(); + return new NextResponse(data, { + status: res.status, + headers: { "content-type": "application/json" }, + }); + } catch { + return NextResponse.json({ status: "error" }, { status: 502 }); + } +} diff --git a/lib/api.ts b/lib/api.ts index 4499c74..f53be22 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -1,4 +1,4 @@ -const BASE = process.env.NEXT_PUBLIC_HERMES_API || "http://localhost:8787"; +const BASE = ""; async function get(path: string): Promise { const res = await fetch(`${BASE}${path}`); @@ -85,4 +85,4 @@ export const fetchSkill = (name: string) => export const fetchConfig = () => get("/api/config"); // Health -export const fetchHealth = () => get<{ status: string }>("/api/health"); +export const fetchHealth = () => get<{ status: string }>("/health"); diff --git a/next.config.ts b/next.config.ts index 3df43b8..2f6491c 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,6 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - output: "standalone", reactStrictMode: true, }; diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..a69ba2ee84a65a3e8fc8aa36b94c9a6dcb8fcbca GIT binary patch literal 546 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE2}s`E_d9@rf$^oMi(^Q|oVS-Yaxy3g9B_D@ zf2TgW+@O_%-Q1yT%}n0w*FH1tOH&YHo+#0A#6g8k$xxuP(Sye&X;f%Pg~Un5&bEzm UUwY5p1japsr>mdKI;Vst0771tzyJUM literal 0 HcmV?d00001 diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..539331691d0bd6d599437ea9813b34efba81eee6 GIT binary patch literal 1879 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_pLHPZ!6KiaBqu8uBt2@Eq81 zulCsdw+UZ5RGCjqzgf$`a<-C@L7j&|;S>YIqETuz2u4%EXhs+<3r35>kx?VqNtAM! UiaOu61Xh>~p00i_>zopr0B~QhEdT%j literal 0 HcmV?d00001