Skip to content

Instantly share code, notes, and snippets.

@theJian
Last active December 24, 2025 04:39
Show Gist options
  • Select an option

  • Save theJian/59d43fa83a885c387455ff46a9de981a to your computer and use it in GitHub Desktop.

Select an option

Save theJian/59d43fa83a885c387455ff46a9de981a to your computer and use it in GitHub Desktop.
frontend api proxy
import httpProxy from "http-proxy";
import { NextApiRequest, NextApiResponse } from "next";
import { env } from "runtime-injector";
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
const isDev = process.env.NODE_ENV === "development";
const isCorsHeader = (header: string) =>
header.toLowerCase().startsWith("access-control-");
const getQueryString = (req: NextApiRequest) => {
const url = req.url;
if (!url) return "";
const indexStart = url.indexOf("?");
if (indexStart === -1) return "";
return url.substring(indexStart);
};
let server: any;
const proxy = httpProxy.createProxy().on("proxyRes", (proxyRes, req, res) => {
const origin = req.headers.origin || "*";
// Rewrite CORS header
if ("origin" in req.headers) {
res.setHeader("access-control-allow-origin", origin);
res.setHeader("access-control-allow-credentials", "true");
}
if (req.headers["access-control-request-method"]) {
res.setHeader(
"access-control-allow-methods",
req.headers["access-control-request-method"]
);
}
if (req.headers["access-control-request-headers"]) {
res.setHeader(
"access-control-allow-headers",
req.headers["access-control-request-headers"]
);
}
});
const Page = async (req: NextApiRequest, res: NextApiResponse<any>) => {
if (!isDev) {
res.status(400).end();
return;
}
const proxyTarget = env.NEXT_PUBLIC_PROXY_TARGET;
const proxyTargetCms = env.NEXT_PUBLIC_PROXY_TARGET_CMS;
const wsProxyTarget = env.NEXT_PUBLIC_CRYPTO_WS_PROXY_TARGET;
if (!proxyTarget) {
res.status(500).send({
error:
"environment variable `NEXT_PUBLIC_PROXY_TARGET` needs to be presented for api proxy to work",
});
return;
}
if (!proxyTargetCms) {
res.status(500).send({
error:
"environment variable `NEXT_PUBLIC_PROXY_TARGET_CMS` needs to be presented for api proxy to work",
});
return;
}
const { slug = [] } = req.query;
const target =
Array.isArray(slug) && slug[0] === "cms" ? proxyTargetCms : proxyTarget;
const path = Array.isArray(slug) ? slug.join("/") : slug;
const queryString = getQueryString(req);
req.url = path + queryString;
if (wsProxyTarget /* enable WebSocket proxying */ && !server) {
server = (res.socket as any)?.server;
server.on("upgrade", (req: any, socket: any, head: any) => {
if (!req.url.startsWith("/api/proxy/ws")) return;
req.url = req.url.replace(/^\/api\/proxy\/ws/, "");
req.headers.host = wsProxyTarget.replace(/^wss?:\/\//, "");
proxy.ws(req, socket, head, {
target: wsProxyTarget,
});
});
}
proxy.web(req, res, {
changeOrigin: true,
target: target,
cookieDomainRewrite: "localhost",
});
};
export default Page;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment