使用connect-query连接Python gRPCio服务器出现ERR_INVALID_HTTP_RESPONSE错误
问题根源
你的Python gRPC服务器基于grpcio构建,仅支持标准gRPC协议(HTTP/2传输),但浏览器环境下的connect-query需要服务器支持Connect协议或gRPC-Web协议——标准gRPC的响应帧格式不符合浏览器的HTTP解析规则,因此直接请求会触发ERR_INVALID_HTTP_RESPONSE错误。官方所说的“无需代理”,特指连接原生支持Connect协议的服务器时的场景,你的情况不在此范围内。
解决方案
方案一:更换为支持Connect协议的Python服务器
使用Buf的connect-python库搭建服务器,它原生支持HTTP/1.1和HTTP/2,可直接响应connect-query的请求:
- 安装依赖:
pip install connect-python grpcio-tools - 用Connect的代码生成工具替代
grpcio-tools,基于你的.proto文件生成服务端代码 - 编写Connect服务器逻辑,替换原有
grpcio服务器:from connect import Server from your_proto_gen import YourService, YourServiceImpl server = Server(port=8080) server.add_service(YourService, YourServiceImpl()) server.serve()
方案二:给现有grpcio服务器添加gRPC-Web支持
如果不想更换服务器框架,可通过Envoy代理做协议转换,将浏览器的gRPC-Web请求转为标准gRPC请求发给后端:
- 部署Envoy代理,配置gRPC-Web过滤器和路由规则(核心配置示例):
listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 8080 } 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_server } http_filters: - name: envoy.filters.http.grpc_web - name: envoy.filters.http.router clusters: - name: grpc_server connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN http2_protocol_options: {} load_assignment: cluster_name: grpc_server endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: 127.0.0.1, port_value: 50051 } - 启动Envoy后,将
connect-query的请求地址指向Envoy的端口(如http://localhost:8080)
客户端配置检查
确保React端的connect-query使用正确的传输配置:
import { createConnectTransport } from "@connectrpc/connect-web"; import { QueryClient } from "@tanstack/react-query"; import { YourService } from "./gen/your_service_connect"; // 指向Connect服务器或Envoy代理地址 const transport = createConnectTransport({ baseUrl: "http://localhost:8080", }); const queryClient = new QueryClient(); // 在组件中使用 export function YourComponent() { const { data } = useQuery({ queryKey: ["your-data"], queryFn: async () => { const response = await YourService.yourMethod( { /* 请求参数 */ }, { transport } ); return response; }, }); }
额外注意事项
- 跨域问题:如果客户端和服务器不在同一域名,需在服务器/代理端配置CORS头,允许客户端的请求来源(如
Access-Control-Allow-Origin: *) - 协议版本:Connect服务器默认支持HTTP/1.1,无需强制HTTP/2,更适配浏览器环境
内容的提问来源于stack exchange,提问作者UselesssCat
相关产品推荐
相关产品推荐

