From 66cbfa9629a707800a29e4f2c38da20089ab1161 Mon Sep 17 00:00:00 2001 From: vinland100 Date: Thu, 30 Oct 2025 14:58:20 +0800 Subject: [PATCH] fix: route dashscope calls through dev proxy to avoid CORS --- src/components/ui/card.tsx | 83 ++++++++++++++++++++++++++++++++++++++ vite.config.ts | 24 +++++++++++ 2 files changed, 107 insertions(+) diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index f4f85ac..c8372b1 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -2,6 +2,89 @@ import * as React from "react"; import { cn } from "@/shared/utils/utils"; +declare global { + interface Window { + __dashscopeProxyPatched__?: boolean; + } +} + +const DASH_SCOPE_ORIGIN = "https://dashscope.aliyuncs.com"; +const DASH_SCOPE_PROXY_PREFIX = "/dashscope-proxy"; + +// Ensure dashscope API traffic is routed through the local proxy during development to avoid browser CORS blocks. +if (typeof window !== "undefined" && import.meta.env.DEV) { + const globalWindow = window as Window; + + if (!globalWindow.__dashscopeProxyPatched__) { + const originalFetch = window.fetch.bind(window); + + const rewriteUrl = (url: string): string => { + if (url.startsWith(DASH_SCOPE_PROXY_PREFIX)) return url; + + if (typeof window !== "undefined") { + const originPrefixed = `${window.location.origin}${DASH_SCOPE_PROXY_PREFIX}`; + if (url.startsWith(originPrefixed)) { + return url.slice(window.location.origin.length); + } + } + + if (url.startsWith(DASH_SCOPE_ORIGIN)) { + return url.replace(DASH_SCOPE_ORIGIN, DASH_SCOPE_PROXY_PREFIX); + } + + return url; + }; + + const rewriteRequestInfo = (input: RequestInfo | URL): RequestInfo => { + if (typeof input === "string") { + return rewriteUrl(input); + } + + if (input instanceof URL) { + return rewriteUrl(input.toString()); + } + + const rewrittenUrl = rewriteUrl(input.url); + if (rewrittenUrl === input.url) { + return input; + } + + const cloned = input.clone(); + const init: RequestInit = { + method: cloned.method, + headers: cloned.headers, + body: + cloned.method && ["GET", "HEAD"].includes(cloned.method.toUpperCase()) + ? undefined + : cloned.body, + cache: cloned.cache, + credentials: cloned.credentials, + integrity: cloned.integrity, + keepalive: cloned.keepalive, + mode: cloned.mode, + redirect: cloned.redirect, + referrer: cloned.referrer, + referrerPolicy: cloned.referrerPolicy, + signal: cloned.signal, + }; + + return new Request(rewrittenUrl, init); + }; + + window.fetch = ((input: RequestInfo | URL, init?: RequestInit) => { + const proxiedInput = rewriteRequestInfo(input); + + if (proxiedInput instanceof Request) { + return originalFetch(proxiedInput); + } + + return originalFetch(proxiedInput, init); + }) as typeof window.fetch; + + globalWindow.__dashscopeProxyPatched__ = true; + } +} + function Card({ className, ...props }: React.ComponentProps<"div">) { return (
path.replace(/^\/dashscope-proxy/, ""), + configure: (proxy) => { + proxy.on("proxyReq", (proxyReq) => { + proxyReq.setHeader("origin", "https://dashscope.aliyuncs.com"); + }); + }, + }, + }, }, preview: { port: 5173,