From 2fe3409c2b3ae1bf520fa2267aaac3be5d93184a Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Thu, 15 Aug 2024 13:03:58 -0700 Subject: [PATCH] Add request proxying (#365) --- .github/workflows/deploy-cloud-run.yaml | 2 - DEPLOYMENT.md | 2 +- frontend/app/api/[..._path]/route.ts | 67 +++++++++++++++++++++++++ frontend/app/components/ChatWindow.tsx | 4 +- frontend/app/page.tsx | 8 +-- frontend/app/utils/constants.tsx | 4 -- frontend/package.json | 2 +- frontend/yarn.lock | 8 +-- 8 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 frontend/app/api/[..._path]/route.ts diff --git a/.github/workflows/deploy-cloud-run.yaml b/.github/workflows/deploy-cloud-run.yaml index 22df5024d..4b87c142f 100644 --- a/.github/workflows/deploy-cloud-run.yaml +++ b/.github/workflows/deploy-cloud-run.yaml @@ -13,8 +13,6 @@ jobs: env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - NEXT_PUBLIC_API_BASE_URL: ${{ secrets.NEXT_PUBLIC_API_BASE_URL }} - NEXT_PUBLIC_LANGCHAIN_API_KEY: ${{ secrets.NEXT_PUBLIC_LANGCHAIN_API_KEY }} steps: - uses: actions/checkout@v2 - name: Install Vercel CLI diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 48fb0cd20..946d6a3cd 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -89,4 +89,4 @@ Once you confirm that the server is working locally, you can deploy your app wit ## Connect to the backend API (LangGraph Cloud) -In Vercel add an environment variable `NEXT_PUBLIC_API_BASE_URL` to match your LangGraph Cloud URL as well as `NEXT_PUBLIC_LANGCHAIN_API_KEY`. \ No newline at end of file +In Vercel add an environment variable `API_BASE_URL` to match your LangGraph Cloud URL as well as `LANGCHAIN_API_KEY`. \ No newline at end of file diff --git a/frontend/app/api/[..._path]/route.ts b/frontend/app/api/[..._path]/route.ts new file mode 100644 index 000000000..dada5bae8 --- /dev/null +++ b/frontend/app/api/[..._path]/route.ts @@ -0,0 +1,67 @@ +import { NextRequest, NextResponse } from "next/server"; + +export const runtime = "edge"; + +function getCorsHeaders() { + return { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': '*', + }; +} + +async function handleRequest(req: NextRequest, method: string) { + try { + const path = req.nextUrl.pathname.replace(/^\/?api\//, ""); + const url = new URL(req.url); + const searchParams = new URLSearchParams(url.search); + searchParams.delete("_path"); + searchParams.delete("nxtP_path"); + const queryString = searchParams.toString() + ? `?${searchParams.toString()}` + : ""; + + const options: RequestInit = { + method, + headers: { + "x-api-key": process.env.LANGCHAIN_API_KEY || "", + }, + }; + + if (["POST", "PUT", "PATCH"].includes(method)) { + options.body = await req.text(); + } + + const res = await fetch( + `${process.env.API_BASE_URL}/${path}${queryString}`, + options, + ); + + return new NextResponse(res.body, { + status: res.status, + statusText: res.statusText, + headers: { + ...res.headers, + ...getCorsHeaders(), + }, + }); + } catch (e: any) { + return NextResponse.json({ error: e.message }, { status: e.status ?? 500 }); + } +} + +export const GET = (req: NextRequest) => handleRequest(req, "GET"); +export const POST = (req: NextRequest) => handleRequest(req, "POST"); +export const PUT = (req: NextRequest) => handleRequest(req, "PUT"); +export const PATCH = (req: NextRequest) => handleRequest(req, "PATCH"); +export const DELETE = (req: NextRequest) => handleRequest(req, "DELETE"); + +// Add a new OPTIONS handler +export const OPTIONS = () => { + return new NextResponse(null, { + status: 204, + headers: { + ...getCorsHeaders(), + }, + }); +}; \ No newline at end of file diff --git a/frontend/app/components/ChatWindow.tsx b/frontend/app/components/ChatWindow.tsx index 914c567c6..236465445 100644 --- a/frontend/app/components/ChatWindow.tsx +++ b/frontend/app/components/ChatWindow.tsx @@ -316,9 +316,7 @@ export function ChatWindow() { }} width={"240px"} > - + diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 890e53b14..56c261374 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -7,13 +7,15 @@ import { Client } from "@langchain/langgraph-sdk"; import { ChatWindow } from "./components/ChatWindow"; import { LangGraphClientContext } from "./hooks/useLangGraphClient"; -import { API_BASE_URL, LANGCHAIN_API_KEY } from "./utils/constants"; + +const apiUrl = process.env.NEXT_PUBLIC_API_URL + ? process.env.NEXT_PUBLIC_API_URL + : "http://localhost:3000/api"; export default function Home() { const queryClient = new QueryClient(); const langGraphClient = new Client({ - apiUrl: API_BASE_URL, - defaultHeaders: { "x-api-key": LANGCHAIN_API_KEY }, + apiUrl, }); return ( diff --git a/frontend/app/utils/constants.tsx b/frontend/app/utils/constants.tsx index 474891e8b..f464e85a4 100644 --- a/frontend/app/utils/constants.tsx +++ b/frontend/app/utils/constants.tsx @@ -1,6 +1,2 @@ -export const API_BASE_URL = - process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8123"; -export const LANGCHAIN_API_KEY = process.env.NEXT_PUBLIC_LANGCHAIN_API_KEY; - export const RESPONSE_FEEDBACK_KEY = "user_score"; export const SOURCE_CLICK_KEY = "user_click"; diff --git a/frontend/package.json b/frontend/package.json index 5596d1f88..f22938697 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,7 +16,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@langchain/core": "^0.1.27", - "@langchain/langgraph-sdk": "^0.0.1", + "@langchain/langgraph-sdk": "^0.0.4", "@types/dompurify": "^3.0.5", "@types/lodash.orderby": "^4.6.9", "@types/marked": "^5.0.1", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 211a1b631..b69e9021b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1108,10 +1108,10 @@ zod "^3.22.4" zod-to-json-schema "^3.22.3" -"@langchain/langgraph-sdk@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.1.tgz#78759169f18602c9900c33380c7686cd281fe1a1" - integrity sha512-ya7PUQPfMAA2iyX/TuBmxEsIC1+Clu3nIl8M7sb8Z8rx0Xts7vtX2YDMXexEmTCN38RQmG5TNfVN860QFMKO+w== +"@langchain/langgraph-sdk@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.4.tgz#26dd13d275335f7e7d7e2fd1f6c47e47b82c9ba7" + integrity sha512-r1B7sZVBVVTEgXXCQWmFXxjnqXcw3BZX+ZESVy/ymrkrA7HPs/xH8Ib6GBXdKk08Qce/QyPO4dNhQEGrstQgJw== dependencies: "@types/json-schema" "^7.0.15" eventsource-parser "^1.1.2"