☰
Angular6+ 反向代理 实现跨域开发:把 proxy.conf.json 改到 TaoToken 的完整配置
2026/10/8 12:23:14 网站建设 项目流程

1. Angular6+ 本地开发跨域联调的真实痛点

Angular6+ 反向代理 实现跨域开发,本质上是把浏览器发出的同源请求交给 dev-server 转发到真实后端,从而绕开浏览器同源策略。你在本地ng serve跑 Angular 应用时,页面地址是http://localhost:4200,而接口服务往往在另一个域名或端口上。浏览器一旦发现请求的协议、域名、端口三者有一个不同,就会判定为跨域,直接拦截响应,控制台抛出Access to XMLHttpRequest at '...' from origin 'http://localhost:4200' has been blocked by CORS policy。这个报错跟你的 Angular 代码写得对不对没关系,是浏览器安全模型在起作用。

很多人的第一反应是让后端加Access-Control-Allow-Origin响应头。但现实里后端可能是第三方服务、可能是统一的大模型 API 网关、也可能你根本没有权限改它的响应头。这时候 Angular CLI 内置的 webpack-dev-server 代理就成了最省事的方案:浏览器只跟localhost:4200通信,dev-server 在 Node 层把请求转发出去,Node 之间没有同源策略,跨域问题自然消失。

这篇聚焦的场景很具体:Angular6+ 项目本地开发,用proxy.conf.json把接口请求代理到 TaoToken 的统一 Key/API 通道。TaoToken 是一个聚合多家大模型能力的 API 平台,你申请一个 Key 就能调用不同厂商的模型,接口地址统一在https://taotoken.net/api。本地联调时,前端直接请求这个地址同样会遇到跨域,所以正好用反向代理把它接进来。适合谁看:正在用 Angular 做 AI 应用前端、需要本地调模型接口、又不想在后端折腾 CORS 的开发者。下面从零给出可复制的配置和验证步骤。

2. TaoToken 前置准备:Key、Base URL 与模型 ID

在动proxy.conf.json之前,先把 TaoToken 侧的三件套准备好,否则代理配好了也会收到 401。这三件套是:Base URL、API Key、Model ID。它们分别对应请求发往哪里、用什么身份、调用哪个模型。

Base URL 用https://taotoken.net/api,注意这里不带任何查询参数,代理配置里的 target 就填它。API Key 需要到控制台创建,路径是https://taotoken.net/console,登录后在 API Keys 页面新建一个,复制出来形如sk-开头的一串字符。这个 Key 只显示一次,建议先存到本地环境变量或密码管理器里。Model ID 取决于你要调哪个模型,可以在模型对话页面先试跑一次,确认模型名称拼写正确,比如常见的对话模型 ID 会写在文档里。

这里有个容易踩的坑:很多人把 Key 直接写进proxy.conf.json或者前端代码里,然后提交到 Git。代理配置本身不承载鉴权,鉴权应该由前端请求头携带,或者由代理在转发时注入。更稳妥的做法是前端在请求拦截器里统一加Authorization: Bearer <你的Key>,Key 从 Angular 的environment.ts读取,而environment.ts在.gitignore里排除掉本地覆盖版本。如果你只是想快速验证代理通不通,也可以先临时把 Key 放在请求头里手动测一次。

另外提醒一点,TaoToken 的接口是标准的 OpenAI 兼容风格,路径通常是/v1/chat/completions。所以最终前端请求的完整地址是https://taotoken.net/api/v1/chat/completions。代理配置要做的就是把你本地的某个前缀,比如/api,映射到这个地址上。理解了这个映射关系,后面的pathRewrite就不会写错。

如果你还没创建 Key,可以先打开https://taotoken.net/api-keys这个 deep link 直达创建页,省得在控制台里找。创建完记得把 Key 和 Model ID 记下来,下一步配置里会用到。

3. 可复制配置:proxy.conf.json 与 angular.json 片段

这一节是全文的核心,给出可以直接粘贴的配置。先建文件,再改angular.json,最后说明每个字段为什么这么写。

在 Angular 项目根目录(和angular.json同级)新建proxy.conf.json,内容如下:

{ "/api": { "target": "https://taotoken.net/api", "secure": true, "changeOrigin": true, "logLevel": "debug", "pathRewrite": { "^/api": "" } } }

逐字段解释。"/api"是匹配前缀,意思是前端所有以/api开头的请求都会被代理接管。target是转发目标,填 TaoToken 的 Base URL。secure: true表示对 HTTPS 目标做证书校验,TaoToken 是正规 HTTPS 服务,保持 true 即可;如果你代理的是自签名证书的本地服务才需要设 false。changeOrigin: true会把请求头里的 Host 改成目标域名,很多网关会校验 Host,不开这个容易 403。logLevel: "debug"会在终端打印每条代理日志,联调阶段非常有用,上线前可以删掉。pathRewrite把开头的/api去掉,因为 target 里已经带了/api,不去掉就会变成/api/api/v1/...,这是最常见的 404 来源。

接着改angular.json。找到projects下你的项目名,再找到architect.serve.options,加上proxyConfig字段:

"serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "your-app-name:build", "proxyConfig": "proxy.conf.json" }, "configurations": { "production": { "browserTarget": "your-app-name:build:production" } } }

把your-app-name换成你angular.json里真实的项目名,通常在文件顶部projects的第一个键就是。proxyConfig的值是相对项目根目录的路径,如果你把文件放到src/下,这里就要写src/proxy.conf.json。Angular6 到 Angular11 用的是browserTarget,Angular12 之后改成了buildTarget,如果你升级过 CLI 发现启动报browserTarget相关错误,把它改成buildTarget即可。

配置完成后,前端代码里请求就写相对路径/api/v1/chat/completions,不要写完整域名。比如用 Angular 的 HttpClient:

this.http.post('/api/v1/chat/completions', { model: 'your-model-id', messages: [{ role: 'user', content: '你好' }] }, { headers: { 'Authorization': 'Bearer ' + environment.taoTokenKey, 'Content-Type': 'application/json' } }).subscribe(res => console.log(res));

这样浏览器看到的是http://localhost:4200/api/v1/chat/completions,同源,不触发 CORS;dev-server 收到后转发到https://taotoken.net/api/v1/chat/completions,带上你注入的 Authorization 头。整个链路就通了。

4. 启动 dev server 并验证跨域请求成功

配置写好后,重启 dev server 让angular.json的改动生效。注意是重启,不是热更新,proxyConfig属于构建配置,热更新不会重新读取。命令:

ng serve

启动后终端会打印编译信息,如果logLevel设了 debug,你会在请求发生时看到类似[HPM] POST /api/v1/chat/completions -> https://taotoken.net/api/v1/chat/completions的日志。这行日志就是代理生效的直接证据。

验证分两步。第一步用 curl 直接打本地 dev-server,确认代理转发链路通:

curl -i -X POST http://localhost:4200/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{"model":"your-model-id","messages":[{"role":"user","content":"ping"}]}'

如果返回 200 和一段 JSON,说明代理、鉴权、模型调用全部正常。如果返回 401,是 Key 问题;返回 404,多半是pathRewrite写错导致路径重复;返回 502 或连接超时,检查 target 是否可达。

第二步在浏览器里验证。打开http://localhost:4200,在页面里触发一次接口调用,然后打开 DevTools 的 Network 面板。找到那条请求,看 Request URL 应该是http://localhost:4200/api/v1/chat/completions,Status 是 200,Response 里有模型返回内容。同时看 Console,应该没有任何 CORS 相关红字。这两点同时满足,跨域联调就算成功了。

我试过在 Network 面板里对比代理前后的差异:代理生效时,请求的 Remote Address 显示的是本地 dev-server 地址,而不是 TaoToken 的 IP,因为浏览器根本没直接连 TaoToken。这也解释了为什么跨域消失了——浏览器视角里它只跟同源的 localhost 说话。

如果你用的是 Angular 的HttpClient加拦截器统一注入 Key,验证时可以在拦截器里console.log一下最终请求头,确认 Authorization 确实带上了。有时候 Key 读成了undefined,请求会以匿名身份发出,返回 401,但代理日志看起来一切正常,容易误判成代理问题。

5. 本篇常见报错排查:401、404、proxy failed 与 OAuth

联调阶段最常见的几类报错,这里逐个对照真实错误信息给排查路径。

第一类,401 Unauthorized,响应体通常是{"error":{"message":"Invalid API key"}}。原因只有两个:Key 没带,或者 Key 错了。检查请求头Authorization是否是Bearer sk-xxx格式,Bearer 和 Key 之间有一个空格,少空格会解析失败。再检查 Key 是否复制完整,有没有把首尾空格带进去。如果 Key 是从环境变量读的,打印一下确认不是undefined。

第二类,404 Not Found,响应体可能是{"error":"Not Found"}。九成是路径拼接问题。回顾一下:target 是https://taotoken.net/api,前端请求/api/v1/chat/completions,pathRewrite把/api替换成空,转发路径变成https://taotoken.net/api+/v1/chat/completions,正确。如果你把pathRewrite写成{"^/api": "/api"},就会变成/api/api/v1/...,404。如果你把 target 写成https://taotoken.net(不带/api),同时pathRewrite又去掉了/api,就会变成https://taotoken.net/v1/...,也 404。对照你的实际配置,确保 target 和 pathRewrite 组合后路径唯一。

第三类,终端报[HPM] Error occurred while trying to proxy request ... (ECONNREFUSED)或proxy failed。这是 dev-server 连不上 target。先确认网络能访问https://taotoken.net,用curl -I https://taotoken.net/api看是否返回。如果公司网络有出口限制,需要走正常的网络配置,不要用任何非正规手段。另外确认 target 协议是https不是http,写错协议也会连接失败。

第四类,如果你在配置里看到OAuth相关字样,比如某些工具要求先做 OAuth 授权再拿 token,那属于另一套鉴权流程,和本篇的 API Key 方式不同。TaoToken 的 API 调用用 Key 即可,不需要 OAuth。如果你在别的工具里配过 OAuth,注意不要把两套凭证混用,否则会出现invalid_grant之类的报错。

还有一个隐蔽的坑:changeOrigin没开。表现是代理日志显示转发成功,但目标返回 403 或 400,提示 Host 不匹配。加上"changeOrigin": true就好。这个字段在跨域代理里几乎是必开项,建议默认写上。

排查时善用logLevel: "debug",它会把转发前后的 URL 都打出来,路径对不对一眼就能看出来。定位到问题后,把 debug 关掉,避免日志刷屏。

6. 把代理配置沉淀为团队可复用的开发规范

代理跑通只是第一步,真正省时间的是把它变成团队里谁都能用的规范。几个实践建议。

第一,proxy.conf.json提交到仓库,但 Key 不提交。Key 放在environment.local.ts这类被.gitignore排除的文件里,或者用 Angular 的--configuration区分本地和 CI 环境。这样新同事拉下代码,只要自己填一个 Key 就能跑,不用重新研究代理怎么配。

第二,把pathRewrite的映射关系写成注释放在配置文件里,或者维护一份简短的 README。因为路径拼接是 404 的高发区,写清楚 target 和 rewrite 的组合结果,能省下大量排查时间。

第三,如果你同时要代理多个后端,比如 TaoToken 之外还有自己的业务接口,可以在proxy.conf.json里加多个前缀:

{ "/api": { "target": "https://taotoken.net/api", "secure": true, "changeOrigin": true, "pathRewrite": { "^/api": "" } }, "/biz": { "target": "http://localhost:8080", "secure": false, "changeOrigin": true, "pathRewrite": { "^/biz": "" } } }

这样前端用/api调模型,用/biz调业务,互不干扰。注意每个前缀的pathRewrite要各自对应,别串了。

第四,长期做 AI 应用开发、需要频繁调模型和跑 Agent 的话,可以了解 TaoToken 的 Coding Plan,它面向持续编码场景做了额度优化,比按次调用更划算。入口在https://taotoken.net/coding-plan。如果只是偶尔验证模型效果,用模型对话页面就够了,地址是https://taotoken.net/chat。接入文档在https://taotoken.net/doc,遇到参数不确定时查这里最准。

最后说一个我踩过的坑:Angular 的ng serve默认端口是 4200,如果你改了端口,代理配置不用动,因为代理是 dev-server 内部行为,跟端口无关。但如果你用了--host 0.0.0.0让局域网其他设备访问,那些设备请求的 origin 会变成你的局域网 IP,此时浏览器视角仍然是同源(因为它们访问的就是你的 IP:端口),代理照样生效。这一点在手机真机联调时很有用。

配置改完记得重启,验证走一遍 curl 加浏览器 Network 面板,确认无 CORS 红字、状态码 200,就可以安心写业务代码了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询