使用tonic-web时如何配置允许CORS请求头?
Rust gRPC Web服务器CORS错误问题及解决
我用Rust搭建了gRPC Web服务器,代码如下:
use tonic_web::GrpcWebLayer; use tonic::{ transport::Server, }; let grpc_web_handle = tokio::spawn( Server::builder() .accept_http1(true) .layer(GrpcWebLayer::new()) .add_service( tonic_web::enable( AuthServer::new( AuthImpl::default() ) ) ) .serve("127.0.0.1:9001".parse()?) ) //...
但Firefox抛出CORS错误:
OPTIONS http://127.0.0.1:9001/auth.Auth/Login (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
响应信息:
HTTP/1.1 400 Bad Request content-length: 0 date: Wed, 13 Dec 2023 22:25:53 GMT
我尝试用自定义cors函数包装AuthServer,代码如下:
fn cors<S>(service: S) -> CorsGrpcWeb<S> where S: Service<http::Request<hyper::Body>, Response=http::Response<BoxBody>>, S: Clone + Send + 'static, S::Future: Send + 'static, S::Error: Into<BoxError> + Send { CorsLayer::permissive().layer(tonic_web::enable(service)).into_inner() }
问题依旧存在。
依赖版本:
tonic = {version = "0.10.2", features = []} tonic-web = {version = "0.10.2",features = []} tokio = { version = "1.34.0", features = ["full"] }
修复方案
问题核心是CORS层的处理顺序错误,以及OPTIONS预检请求未被正确拦截处理。按以下步骤修复:
- 添加CORS依赖
在Cargo.toml中加入axum的cors组件(tonic基于hyper,axum的CorsLayer兼容):
axum = { version = "0.7", features = ["cors"] }
- 调整服务器层顺序
将CORS层放在GrpcWebLayer之前,确保预检请求先被CORS层处理:
use tonic_web::GrpcWebLayer; use tonic::{transport::Server}; use axum::cors::{CorsLayer, Any, Origin}; // 配置CORS规则(生产环境请限制具体域名,不要用Any) let cors_layer = CorsLayer::new() .allow_origin(Any) .allow_methods(Any) .allow_headers(Any) .allow_credentials(true); let grpc_web_handle = tokio::spawn( Server::builder() .accept_http1(true) // 先添加CORS层,再添加GrpcWeb层 .layer(cors_layer) .layer(GrpcWebLayer::new()) .add_service(tonic_web::enable(AuthServer::new(AuthImpl::default()))) .serve("127.0.0.1:9001".parse()?) );
- 问题说明
之前的自定义函数错误地将CORS层应用在tonic-web包装后的服务上,导致OPTIONS请求直接进入gRPC服务逻辑,返回400错误。正确的顺序是让CORS层作为最外层,先处理预检请求,再将合法请求传递给GrpcWeb层做协议转换。
内容的提问来源于stack exchange,提问作者alindner
相关产品推荐
相关产品推荐

