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

Go Buf Connect gRPC服务器CORS配置问题求助

问题诊断与修复

核心错误点

  1. CORS中间件作用范围错误:你当前仅将CORS中间件应用在单个gRPC接口handler上,但预检请求(OPTIONS)会先经过mux路由匹配,若未全局包裹mux,非接口路径的请求(或路由匹配前的请求)无法触发CORS逻辑。
  2. AllowedMethods未包含OPTIONS:浏览器预检请求使用OPTIONS方法,你的配置里没有允许该方法,导致rs/cors无法正确响应预检。
  3. 测试路径错误:你测试的是根路径/,但实际gRPC接口注册在特定子路径(比如你打印的Path of Handler对应的路径),根路径本身没有handler,返回404是正常的,但这不是你的CORS问题所在。

修复后的代码

package wavserver

import (
    "context"
    "fmt"
    "net/http"

    "github.com/jmoiron/sqlx"
    "github.com/pienaahj/recordingdepo/backend/gen/wavapi/v1/wavapiv1connect"
    li "github.com/pienaahj/recordingdepo/backend/logwrapper"
    "github.com/rs/cors"
    "golang.org/x/net/http2"
    "golang.org/x/net/http2/h2c"
)

type wavapiServer struct {
    Repo *sqlx.DB
}

// RunServer is the main gprs server
func RunServer(ctx context.Context, repo *sqlx.DB) error {
    fmt.Println("message from runserver, repo received: ", repo)
    CallFrom := "Call from GRPC main"
    var port string = ":50051"
    var success int = 204

    recorder := &wavapiServer{
        Repo: repo,
    }
    // create a new mux
    mux := http.NewServeMux()
    // setup the recordings service handler
    path, handler := wavapiv1connect.NewRecordingsServiceHandler(recorder)
    fmt.Println("Path of Handler: ", path)
    // 注册handler到mux
    mux.Handle(path, handler)

    // 配置CORS
    c := cors.New(cors.Options{
        AllowedHeaders: []string{
            "Content-Type",
            "Connect-Protocol-Version",
            "Connect-Timeout-Ms",
            "Grpc-Timeout",
            "X-Grpc-Web",
            "X-User-Agent",
            "Authorization", // 可选:如果需要带认证头可以加上
        },
        AllowedOrigins:       []string{"http://localhost:3000"},
        AllowCredentials:     true,
        AllowedMethods:       []string{"POST", "GET", "OPTIONS"}, // 必须包含OPTIONS
        Debug:                true, // disable for production
        OptionsPassthrough:   false, // 改为false,让rs/cors处理OPTIONS请求
        OptionsSuccessStatus: success,
    })

    // 将CORS中间件全局包裹整个mux,而非单个handler
    wrappedMux := c.Handler(mux)

    // 启动服务器
    err := http.ListenAndServe(
        port,
        // Use h2c so we can serve HTTP/2 without TLS.
        h2c.NewHandler(wrappedMux, &http2.Server{}),
    )
    if err != nil {
        li.Logger.ErrGRPCListenerMessage(CallFrom, err)
        fmt.Printf("Failed to listen and serve on gPRC server: %v\n", err)
        return err
    }
    return nil
}

关键修改说明

  • 全局包裹mux:将CORS中间件应用到整个mux上,确保所有请求(包括预检OPTIONS)都经过CORS处理。
  • 添加OPTIONS到AllowedMethods:明确允许预检请求使用的OPTIONS方法。
  • 关闭OptionsPassthrough:让rs/cors自行处理OPTIONS请求,避免传递给后续handler导致404。

正确的测试命令

使用你打印的Path of Handler路径(比如假设是/wavapi.v1.RecordingsService/ListRecordings)来发送预检请求:

curl -X OPTIONS -i -H 'Origin: http://localhost:3000' http://localhost:50051/你的接口路径

例如,如果你的接口路径是/wavapi.v1.RecordingsService/GetRecording,则测试命令为:

curl -X OPTIONS -i -H 'Origin: http://localhost:3000' http://localhost:50051/wavapi.v1.RecordingsService/GetRecording

此时应该返回包含正确CORS头的204响应,而非404。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:05:31