部署到IIS后,Vite/React项目通过代理访问Apigee出现404 Not Found问题求助
嘿,兄弟!看你这情况太闹心了——本地跑Vite/React项目的时候,代理访问Apigee完全正常,结果一部署到IIS就炸出404,我太懂这种本地好好的生产就崩的崩溃感了!我来给你捋捋问题根源和解决办法,肯定能帮到你。
先搞懂核心问题:Vite的dev proxy只在开发环境生效!
你之前在vite.config.js里配置的server.proxy,只有在你跑vite dev开发服务的时候才有用!当你执行vite build把项目打包成静态文件部署到IIS后,这个配置就彻底失效了——因为生产环境没有Vite的开发服务器来帮你转发请求啊!
这时候你的前端代码请求/api/v1,其实是直接把请求发给了IIS服务器本身,而IIS上根本没有/api/v1这个路径的资源,可不就返回404了嘛!
给你三个靠谱的解决办法,按需选:
办法一:在IIS上配置反向代理(最推荐,无额外服务)
这个是替代Vite dev proxy的生产环境方案,需要在IIS上装两个组件:Application Request Routing(ARR)和URL Rewrite,这俩是IIS做反向代理的必备工具,直接在IIS的“管理工具”里就能找到安装入口。
装完之后,在你的IIS站点根目录下新建一个web.config文件,把下面的配置粘进去:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <!-- 把/api/v1的请求转发到Apigee的实际地址 --> <rule name="Proxy to Apigee" stopProcessing="true"> <match url="^api/v1/(.*)" /> <action type="Rewrite" url="https://apigee.test-svc-232/api/v1/{R:1}" /> </rule> <!-- 处理React SPA路由刷新404的问题,这个也必须加! --> <rule name="SPA Fallback" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/index.html" /> </rule> </rules> </rewrite> </system.webServer> </configuration>
这个配置里,第一个规则负责把所有/api/v1开头的请求转发到Apigee的真实地址;第二个规则是为了React单页应用的路由——如果你不加这个,前端路由切到其他页面后刷新,也会出现404,非常影响体验。
办法二:前端直接请求Apigee完整地址(应急用,不推荐)
临时测试的话,可以把你Test.js里的请求地址从/api/v1改成Apigee的完整地址https://apigee.test-svc-232/api/v1,然后确保Apigee的端点配置了CORS,允许你的IIS站点域名访问。
⚠️ 但千万注意:这种方式会把你的client_id和client_secret(看你代码里的Authorization头,应该是用了客户端凭证模式)直接暴露在前端代码里,任何人都能扒出来,非常不安全!所以仅限测试环境应急,生产环境绝对不能用。
办法三:自建后端代理服务(最安全,适合敏感场景)
如果你不想在IIS上折腾组件,或者需要隐藏敏感的客户端凭证,那可以搭一个简单的后端服务(比如Node.js/Express)来做代理,把敏感逻辑放在后端,前端只需要调用自己的后端接口。
举个简单的Express代理例子:
const express = require('express'); const proxy = require('express-http-proxy'); const app = express(); // 转发/api/v1请求到Apigee app.use('/api/v1', proxy('https://apigee.test-svc-232', { proxyReqPathResolver: function(req) { return '/api/v1' + req.url; } })); // 托管前端打包后的静态文件 app.use(express.static('dist')); app.listen(3000, () => { console.log('代理服务启动在3000端口'); });
部署这个Node服务到IIS的话,可以用IISNode组件,或者直接用pm2管理进程。这种方式的好处是,敏感的client_id和client_secret可以存在后端服务里,不会暴露给前端,安全性拉满。
最后再提几个必踩的坑,提前避坑:
- 检查IIS服务器的网络连通性:有时候IIS所在的服务器有防火墙或者内部代理,导致无法访问外部的Apigee端点,这时候也会出现404或者502错误。可以在IIS服务器上用curl或者Postman测试一下能不能正常访问Apigee的地址。
- 检查Apigee的IP白名单:如果Apigee的端点设置了IP白名单,而IIS服务器的IP不在白名单里,也会返回404或者权限错误。
- 客户端凭证模式的安全性:你用的是
client_credentials模式拿令牌,这种模式本来就应该在后端执行,绝对不能把凭证放在前端!所以如果是生产环境,强烈推荐用办法三,把凭证存在后端,后端去拿令牌,再返回给前端或者直接用令牌请求数据返回给前端。
备注:内容来源于stack exchange,提问作者Emprende LAB

