React Native中grpc-web无法连接AWS上的Envoy代理服务器
React Native iOS模拟器中gRPC-Web调用AWS Elastic Beanstalk Envoy代理失败的排查与解决
问题背景
部署在AWS Elastic Beanstalk的测试用Envoy代理配置如下:
admin: access_log_path: /tmp/admin_access.log address: socket_address: { address: 0.0.0.0, port_value: 9901 } static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 80 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: cluster: grpc_cluster timeout: 0s max_stream_duration: grpc_timeout_header_max: 0s cors: allow_origin_string_match: - prefix: "*" allow_methods: GET, PUT, DELETE, POST, OPTIONS allow_headers: keep-alive,accept,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout max_age: "1728000" expose_headers: custom-header-1,grpc-status,grpc-message http_filters: - name: envoy.filters.http.grpc_web typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb - name: envoy.filters.http.cors typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: grpc_cluster connect_timeout: 0.25s type: logical_dns http2_protocol_options: {} lb_policy: round_robin load_assignment: cluster_name: grpc_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: ${server_url} port_value: ${server_port}
使用grpcurl或Node.js客户端(测试代码如下)调用正常:
import { LightStreamerClient } from "../protos-dist/LightstreamerServiceClientPb"; import { Empty, ServerInfo } from "../protos-dist/lightstreamer_pb"; import { RpcError } from "grpc-web"; const XMLHttpRequest = require("xhr2"); const client = new LightStreamerClient("http://mytest.us-west-1.elasticbeanstalk.com"); globalThis.XMLHttpRequest = XMLHttpRequest; function getServerInfo(): Promise<[RpcError, ServerInfo]> { return new Promise((res) => { client.getServerInfo(new Empty(), null, (_err, response) => { res([_err, response]); }); }); } async function main() { console.log("Testing envoy server..."); const [err, response] = await getServerInfo(); console.log({ err, response }); console.log("Done."); } main();
但在React Native iOS模拟器中执行相同gRPC-Web调用时失败,报错:[RpcError: Http response at 400 or 500 level, http status code: 0]。本地运行相同Envoy配置时所有测试正常,怀疑问题与CORS相关。
排查与解决办法
1. 调整Envoy过滤器顺序(核心修复)
当前配置中grpc_web过滤器排在cors过滤器之前,会导致CORS预检OPTIONS请求先被gRPC-Web过滤器处理——而gRPC-Web不支持OPTIONS方法,直接返回错误。需将cors过滤器移至最前面,确保OPTIONS请求优先被CORS规则处理:
http_filters: - name: envoy.filters.http.cors typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors - name: envoy.filters.http.grpc_web typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
2. 检查React Native iOS的ATS配置
iOS默认阻止HTTP请求,需在项目Info.plist中添加ATS例外,允许访问EB域名:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>mytest.us-west-1.elasticbeanstalk.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict>
3. 验证AWS EB网络配置
- 确认EB实例安全组开放80端口,允许iOS模拟器所在网络的流量访问
- 检查EB是否有负载均衡器或WAF规则拦截OPTIONS请求或gRPC-Web请求头
4. 查看Envoy访问日志定位问题
登录EB实例,查看/tmp/admin_access.log,确认请求是否到达Envoy、请求方法/头信息、返回状态码,进一步定位问题环节。
内容的提问来源于stack exchange,提问作者jowparks
相关产品推荐
相关产品推荐

