[功能]: 为原生 Fetch 请求提供统一的 Service URL 构造能力
Author: yz-yang04Created Jul 25, 2026Updated Aug 20, 2026
Labelsenhancement
描述
getServiceBaseURL() 当前可能返回以下几类 Base URL:
- 同源根路径,例如
/或空字符串; - 本地开发代理前缀,例如
/proxy-default; - 独立后端域名,例如
https://api.example.com。
普通 Axios 请求可以由请求客户端处理 Base URL 与 API path 的斜杠边界,但项目在实现 SSE、Fetch Stream、文件传输或其他必须直接使用原生 fetch 的请求时,通常需要自行拼接 URL。
如果调用方直接使用:
fetch(`${baseURL}/api/v1/events`)当 baseURL 为 / 时,结果会成为 //api/v1/events。浏览器会将其解析为协议相对 URL,例如在 HTTPS 页面中请求 https://api/v1/events,而不是当前站点的 /api/v1/events。
这类问题在开发代理或绝对 API 域名配置下不一定出现,容易到同源生产部署时才暴露。希望 Soybean Admin 为不经过统一 Axios 客户端的原生请求提供公共 URL 构造能力,或在 Service URL 规范中明确推荐做法。
建议的解决方案
建议在 src/utils/service.ts 提供一个轻量、可测试的 URL 构造函数,例如:
buildServiceURL(baseURL, path, query?)建议至少满足以下行为:
| Base URL | API path | 期望结果 |
|---|---|---|
/ |
/api/v1/events |
/api/v1/events |
| `` | /api/v1/events |
/api/v1/events |
/proxy-default |
/api/v1/events |
/proxy-default/api/v1/events |
/proxy-default/ |
/api/v1/events |
/proxy-default/api/v1/events |
https://api.example.com |
/api/v1/events |
https://api.example.com/api/v1/events |
https://api.example.com/ |
/api/v1/events |
https://api.example.com/api/v1/events |
同时建议:
path只接受由应用代码提供、以单个/开头的受控路径,拒绝绝对 URL 和//协议相对路径;- 查询参数使用
URLSearchParams或等价结构化 API; - 不通过全局替换
//处理,以免破坏https://; - 增加上述矩阵的单元测试;
- 在文档中说明 Axios 请求与原生
fetch请求的 URL 构造边界。
替代方案
- 每个原生
fetch调用点自行执行baseURL.replace(/\/+$/, '') + path。实现简单,但容易重复、遗漏,且不同业务可能产生不一致行为。 - 所有请求都强制使用 Axios。对于 POST SSE、Fetch Stream、AbortSignal 或特殊传输场景不一定合适。
- 仅在文档中提示调用方处理斜杠。可以降低风险,但无法通过公共测试长期保证行为一致。
额外的上下文
这个建议不要求改变 VITE_SERVICE_BASE_URL 或现有代理语义,也不要求重构统一 Axios 请求库。目标只是为绕过 Axios 的少量原生请求提供与现有 Service 配置一致的安全 URL 构造入口。
Source: soybeanjs/soybean-admin