You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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预检请求未被正确拦截处理。按以下步骤修复:

  1. 添加CORS依赖
    在Cargo.toml中加入axum的cors组件(tonic基于hyper,axum的CorsLayer兼容):
axum = { version = "0.7", features = ["cors"] }
  1. 调整服务器层顺序
    将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()?)
);
  1. 问题说明
    之前的自定义函数错误地将CORS层应用在tonic-web包装后的服务上,导致OPTIONS请求直接进入gRPC服务逻辑,返回400错误。正确的顺序是让CORS层作为最外层,先处理预检请求,再将合法请求传递给GrpcWeb层做协议转换。

内容的提问来源于stack exchange,提问作者alindner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 23:12:21