gRPC前端调用时跨域问题怎么解决?
我最近在用 gRPC-Web 做前后端通信,后端是 Go 写的 gRPC 服务,前端用的是 Vue。本地开发时请求一直被浏览器拦截,报 CORS 错误。我已经在后端加了 cors 中间件,但还是不行。是不是前端这边也要配什么?或者我的 HTML 引入方式有问题?
这是我在 index.html 里引入 proto 生成的 js 文件的方式:
<script src="./proto/myService_grpc_web_pb.js"></script>
<script src="./proto/myService_pb.js"></script>
<script>
const client = new MyServiceClient('http://localhost:8080');
// 调用方法时报跨域错误
</script>
问题在于 gRPC-Web 使用了特殊的请求头和 Content-Type,普通的 cors 中间件可能没配置这些。
Go 后端这边,你得确保 CORS 允许这几个关键头:
前端调用地址这块也有问题。你写的是
http://localhost:8080,但如果你的 Vue 开发服务器跑在另一个端口(比如 8081),那还是有跨域。正确做法是让前端直接请求你 Go 服务的地址,或者通过 nginx 代理。还有一种更省心的方案:别用 gRPC-Web,直接用 grpc-gateway 把 gRPC 转成 REST 接口,前端就按普通 API 调用,没这些破事。gRPC-Web 适合内部服务间通信,给浏览器用的话 REST 还是稳一点。
前端这边主要检查三点:
1. 确保grpc-web的content-type是application/grpc-web,而不是普通ajax的application/json。可以这样初始化client:
2. 如果你用的是webpack开发服务器,在vue.config.js里配个代理:
3. 服务端记得设置这几个响应头:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: content-type, x-grpc-web, x-user-agent
我之前也被这问题折磨了两天,最后发现是envoy配置里漏了allow_methods。grpc-web的坑比restful api多不少,调试的时候多看看浏览器的网络请求详情。