fix: 开发代理避免 CORS,ideship Track 路径去重段
All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m40s
All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m40s
本地开发改为同源代理到生产/测试 API;ideship 将 /Track/Track 归一为 /track/Track,避免 404。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c0c37a4eac
commit
2a51677908
@ -1,18 +1,13 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 本地开发默认 → 测试环境 oms.nanafa.com / api.nanafa.com
|
# 本地开发默认 → 测试环境(Vite 代理到 api.nanafa.com,无浏览器 CORS)
|
||||||
# 切换到生产 API:pnpm dev:ideship (加载 .env.ideship)
|
# 切生产:pnpm dev:ideship
|
||||||
# 发版构建:pnpm build(生产) / pnpm build:test(测试)
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
VITE_DEPLOY_TARGET=nanafa
|
VITE_DEPLOY_TARGET=nanafa
|
||||||
VITE_API_ORIGIN=http://api.nanafa.com
|
|
||||||
VITE_API_ADMIN_URL=http://api.nanafa.com/admin
|
|
||||||
VITE_OMS_ADMIN_URL=http://api.nanafa.com/admin
|
VITE_OMS_ADMIN_URL=http://api.nanafa.com/admin
|
||||||
VITE_API_ASSET_ORIGIN=http://api.nanafa.com/admin
|
VITE_API_ORIGIN=http://api.nanafa.com
|
||||||
|
|
||||||
# 企业微信客服
|
|
||||||
VITE_WECOM_KF_URL=https://work.weixin.qq.com/kfid/kfcae09c206f6c7045a
|
VITE_WECOM_KF_URL=https://work.weixin.qq.com/kfid/kfcae09c206f6c7045a
|
||||||
|
|
||||||
# 智谱 AI(接口映射脚本生成)
|
|
||||||
VITE_ZHIPU_API_KEY=85bbbef6bafd4ca383eef04189decd07.lKVQHcLGtYE8oUn5
|
VITE_ZHIPU_API_KEY=85bbbef6bafd4ca383eef04189decd07.lKVQHcLGtYE8oUn5
|
||||||
VITE_ZHIPU_BASE_URL=/zhipu-api
|
VITE_ZHIPU_BASE_URL=/zhipu-api
|
||||||
VITE_ZHIPU_MODEL=glm-5.1
|
VITE_ZHIPU_MODEL=glm-5.1
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 本地开发直连生产 API(ideship.com)— pnpm dev:ideship
|
# 本地开发直连生产 API(ideship)— pnpm dev:ideship
|
||||||
# 仅用于联调生产;正式发版请用 pnpm build(.env.production)
|
# 浏览器仍请求 localhost,由 Vite 代理到 api.ideship.com(避免 CORS)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
VITE_DEPLOY_TARGET=ideship
|
VITE_DEPLOY_TARGET=ideship
|
||||||
VITE_API_ORIGIN=https://api.ideship.com
|
|
||||||
VITE_API_ADMIN_URL=https://api.ideship.com/admin
|
|
||||||
VITE_OMS_ADMIN_URL=https://api.ideship.com/admin
|
VITE_OMS_ADMIN_URL=https://api.ideship.com/admin
|
||||||
VITE_API_ASSET_ORIGIN=https://api.ideship.com/admin
|
VITE_API_ORIGIN=https://api.ideship.com
|
||||||
|
|
||||||
VITE_WECOM_KF_URL=https://work.weixin.qq.com/kfid/kfcae09c206f6c7045a
|
VITE_WECOM_KF_URL=https://work.weixin.qq.com/kfid/kfcae09c206f6c7045a
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 测试环境(oms.nanafa.com)— pnpm build:test → vite build --mode nanafa
|
# 测试环境构建(oms.nanafa.com)— pnpm build:test
|
||||||
# 三套 API:http://api.nanafa.com/{admin|itfx|track}
|
|
||||||
# 前端站点:https://oms.nanafa.com
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
VITE_DEPLOY_TARGET=nanafa
|
VITE_DEPLOY_TARGET=nanafa
|
||||||
VITE_API_ORIGIN=http://api.nanafa.com
|
VITE_API_ORIGIN=http://api.nanafa.com
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Admin API 地址(方案 A)
|
* Admin API 地址(方案 A)
|
||||||
* - 优先 VITE_API_ADMIN_URL(.env.production / .env.nanafa / .env.ideship 切换)
|
* - 开发:始终相对路径,由 Vite 代理到 VITE_OMS_ADMIN_URL(避免 localhost→api 跨域)
|
||||||
* - 未配置且开发:相对路径走 Vite 代理
|
* - 生产构建:VITE_API_ADMIN_URL / 默认 https://api.ideship.com/admin
|
||||||
* - 未配置且生产构建:默认 https://api.ideship.com/admin
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function normalizeBase(base: string): string {
|
function normalizeBase(base: string): string {
|
||||||
@ -22,34 +21,27 @@ function configuredAdminBase(): string | undefined {
|
|||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function prodAdminBase(): string {
|
|
||||||
return configuredAdminBase() ?? DEFAULT_PROD_ADMIN
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 浏览器请求 Admin API(OpenAPI.BASE 或 omsUrl/orderUrl 等) */
|
/** 浏览器请求 Admin API(OpenAPI.BASE 或 omsUrl/orderUrl 等) */
|
||||||
export function resolveAdminApiPath(path: string): string {
|
export function resolveAdminApiPath(path: string): string {
|
||||||
const p = ensureLeadingSlash(path)
|
const p = ensureLeadingSlash(path)
|
||||||
const configured = configuredAdminBase()
|
// 开发走同源代理,不直连远程(生产 CORS 不放行 localhost)
|
||||||
if (configured) {
|
if (import.meta.env.DEV) {
|
||||||
return `${configured}${p}`
|
|
||||||
}
|
|
||||||
if (!import.meta.env.DEV) {
|
|
||||||
return `${DEFAULT_PROD_ADMIN}${p}`
|
|
||||||
}
|
|
||||||
return p
|
return p
|
||||||
|
}
|
||||||
|
return `${configuredAdminBase() ?? DEFAULT_PROD_ADMIN}${p}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveOpenApiBase(): string {
|
export function resolveOpenApiBase(): string {
|
||||||
const configured = configuredAdminBase()
|
if (import.meta.env.DEV) {
|
||||||
if (configured) return configured
|
|
||||||
if (!import.meta.env.DEV) {
|
|
||||||
return DEFAULT_PROD_ADMIN
|
|
||||||
}
|
|
||||||
return ''
|
return ''
|
||||||
|
}
|
||||||
|
return configuredAdminBase() ?? DEFAULT_PROD_ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 桌面 Agent 等直连 Admin 网关 */
|
/** 桌面 Agent 等直连 Admin 网关(不受浏览器 CORS 限制) */
|
||||||
export function resolveDirectAdminApiUrl(): string {
|
export function resolveDirectAdminApiUrl(): string {
|
||||||
|
const fromOms = import.meta.env.VITE_OMS_ADMIN_URL as string | undefined
|
||||||
|
if (fromOms?.trim()) return normalizeBase(fromOms)
|
||||||
const configured = configuredAdminBase()
|
const configured = configuredAdminBase()
|
||||||
if (configured) return configured
|
if (configured) return configured
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
@ -60,14 +52,12 @@ export function resolveDirectAdminApiUrl(): string {
|
|||||||
|
|
||||||
/** 静态资源(uploads)在 Admin wwwroot,须带 `/admin`。 */
|
/** 静态资源(uploads)在 Admin wwwroot,须带 `/admin`。 */
|
||||||
export function resolveAdminAssetOrigin(): string {
|
export function resolveAdminAssetOrigin(): string {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
const override = import.meta.env.VITE_API_ASSET_ORIGIN as string | undefined
|
const override = import.meta.env.VITE_API_ASSET_ORIGIN as string | undefined
|
||||||
if (override?.trim()) {
|
if (override?.trim()) {
|
||||||
return normalizeBase(override)
|
return normalizeBase(override)
|
||||||
}
|
}
|
||||||
const configured = configuredAdminBase()
|
return configuredAdminBase() ?? DEFAULT_PROD_ADMIN
|
||||||
if (configured) return configured
|
|
||||||
if (!import.meta.env.DEV) {
|
|
||||||
return DEFAULT_PROD_ADMIN
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,9 +20,10 @@ const SPA_API_PREFIXES = [
|
|||||||
const DEFAULT_PROD_API = 'https://api.ideship.com'
|
const DEFAULT_PROD_API = 'https://api.ideship.com'
|
||||||
|
|
||||||
function prodApiOrigin(): string | null {
|
function prodApiOrigin(): string | null {
|
||||||
|
// 开发走 Vite 代理,不改写为跨域绝对地址
|
||||||
|
if (import.meta.env.DEV) return null
|
||||||
const override = (import.meta.env.VITE_API_ORIGIN as string | undefined)?.trim()
|
const override = (import.meta.env.VITE_API_ORIGIN as string | undefined)?.trim()
|
||||||
if (override) return override.replace(/\/$/, '')
|
if (override) return override.replace(/\/$/, '')
|
||||||
if (import.meta.env.DEV) return null
|
|
||||||
return DEFAULT_PROD_API
|
return DEFAULT_PROD_API
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +77,28 @@ export function rewriteBrowserApiPath(url: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path.startsWith('/Track')) {
|
if (path.startsWith('/Track')) {
|
||||||
|
// ideship:/Track/Track/Order → /track/Track/Order
|
||||||
|
// nanafa:保持 /track + /Track/Track/Order
|
||||||
|
const useSingle =
|
||||||
|
String(import.meta.env.VITE_DEPLOY_TARGET || '').toLowerCase() === 'ideship' ||
|
||||||
|
/ideship\.com/i.test(origin)
|
||||||
|
if (useSingle && path.startsWith('/Track/Track/')) {
|
||||||
|
return `${origin}/track/Track/${path.slice('/Track/Track/'.length)}`
|
||||||
|
}
|
||||||
return `${origin}/track${path}`
|
return `${origin}/track${path}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.startsWith('/trackApi/')) {
|
if (path.startsWith('/trackApi/')) {
|
||||||
return `${origin}/track/${path.slice('/trackApi/'.length)}`
|
const rest = path.slice('/trackApi/'.length)
|
||||||
|
const useSingle =
|
||||||
|
String(import.meta.env.VITE_DEPLOY_TARGET || '').toLowerCase() === 'ideship' ||
|
||||||
|
/ideship\.com/i.test(origin)
|
||||||
|
// trackApi/Track/Order → /track/Track/Order
|
||||||
|
if (useSingle && rest.startsWith('Track/')) {
|
||||||
|
return `${origin}/track/${rest}`
|
||||||
|
}
|
||||||
|
// nanafa 历史:trackApi/Track/Order → /track/Track/Track/Order(与双 Track 客户端一致时由调用方决定)
|
||||||
|
return `${origin}/track/${rest}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|||||||
@ -14,10 +14,33 @@ import configCompressPlugin from './config/plugin/compress';
|
|||||||
|
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const env = loadEnv(mode, process.cwd(), '');
|
const env = loadEnv(mode, process.cwd(), '');
|
||||||
// Admin API 目标:由 VITE_OMS_ADMIN_URL 决定(开发默认线上)
|
// Admin API 目标:由 VITE_OMS_ADMIN_URL 决定(开发走代理,避免浏览器 CORS)
|
||||||
const omsAdminTarget = (
|
const omsAdminTarget = (
|
||||||
env.VITE_OMS_ADMIN_URL || 'http://api.nanafa.com/admin'
|
env.VITE_OMS_ADMIN_URL || env.VITE_API_ADMIN_URL || 'http://api.nanafa.com/admin'
|
||||||
).replace(/\/$/, '');
|
).replace(/\/$/, '');
|
||||||
|
// API 根(itfx/track):优先 VITE_API_ORIGIN,否则从 Admin URL 去掉 /admin
|
||||||
|
const apiOrigin = (
|
||||||
|
env.VITE_API_ORIGIN ||
|
||||||
|
omsAdminTarget.replace(/\/admin\/?$/, '') ||
|
||||||
|
'http://api.nanafa.com'
|
||||||
|
).replace(/\/$/, '');
|
||||||
|
// ideship:PATHBASE=/track → /track/Track/Order/...
|
||||||
|
// nanafa:网关仍吃 /track/Track/Track/Order/...(前端历史双 Track)
|
||||||
|
const trackUseSingleSegment =
|
||||||
|
String(env.VITE_DEPLOY_TARGET || '').toLowerCase() === 'ideship' ||
|
||||||
|
/ideship\.com/i.test(apiOrigin);
|
||||||
|
|
||||||
|
const rewriteTrackProxyPath = (path: string) => {
|
||||||
|
if (trackUseSingleSegment) {
|
||||||
|
if (path.startsWith('/Track/Track/')) {
|
||||||
|
return `/track/Track/${path.slice('/Track/Track/'.length)}`;
|
||||||
|
}
|
||||||
|
if (path.startsWith('/Track/') || path === '/Track') {
|
||||||
|
return `/track${path}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `/track${path}`;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
server: {
|
server: {
|
||||||
@ -34,16 +57,17 @@ export default defineConfig(({ mode }) => {
|
|||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
// 上传静态资源:/api/upload/xxx -> http://api.nanafa.com/upload/xxx
|
// 上传静态资源:/api/upload/xxx -> {apiOrigin}/upload/xxx(Admin 多为 /admin/uploads)
|
||||||
// 必须放在通用 /api 规则前,避免被转发到 /itfx/upload 导致 404
|
// 必须放在通用 /api 规则前,避免被转发到 /itfx/upload 导致 404
|
||||||
'/api/upload': {
|
'/api/upload': {
|
||||||
target: 'http://api.nanafa.com',
|
target: apiOrigin,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
secure: false,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
proxyTimeout: 30000,
|
proxyTimeout: 30000,
|
||||||
},
|
},
|
||||||
// Admin API:目标由 VITE_OMS_ADMIN_URL 决定(默认 http://api.nanafa.com/admin)
|
// Admin API:目标由 VITE_OMS_ADMIN_URL 决定
|
||||||
'/rbac': {
|
'/rbac': {
|
||||||
target: omsAdminTarget,
|
target: omsAdminTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
@ -281,22 +305,24 @@ export default defineConfig(({ mode }) => {
|
|||||||
secure: false,
|
secure: false,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
},
|
},
|
||||||
// 轨迹(track)43.139.210.35:8889 -> http://api.nanafa.com/track,路径与 rbac、api 一致:/Track/xxx
|
// 轨迹(track):{apiOrigin}/track/...
|
||||||
'/Track': {
|
'/Track': {
|
||||||
target: 'http://api.nanafa.com',
|
target: apiOrigin,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => '/track' + path,
|
secure: false,
|
||||||
|
rewrite: rewriteTrackProxyPath,
|
||||||
configure: (proxy) => {
|
configure: (proxy) => {
|
||||||
proxy.on('error', (err, req, res) => {
|
proxy.on('error', (err, req, res) => {
|
||||||
console.error('proxy error', err);
|
console.error('proxy error', err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// API(itfx)43.139.210.35:8888 -> http://api.nanafa.com/itfx
|
// API(itfx):{apiOrigin}/itfx
|
||||||
// 使用正则表达式匹配,排除前端路由路径
|
// 使用正则表达式匹配,排除前端路由路径
|
||||||
'^/api/(?!upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface|downstreamInterface/newPort|appList|appList/createApplication|requestLog|callStatistics|apiDebugger|trackApi)': {
|
'^/api/(?!upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface|downstreamInterface/newPort|appList|appList/createApplication|requestLog|callStatistics|apiDebugger|trackApi)': {
|
||||||
target: 'http://api.nanafa.com/itfx',
|
target: `${apiOrigin}/itfx`,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
secure: false,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
proxyTimeout: 30000,
|
proxyTimeout: 30000,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user