gqlgen服务器配置CORS后拒绝http://localhost:3000连接问题
解决gqlgen服务器WebSocket连接被CORS拒绝的问题
你的问题根源在于:WebSocket的跨域检查和HTTP的CORS配置不匹配。
你已经通过rs/cors中间件给HTTP请求配置了允许http://localhost:3000跨域,但WebSocket传输的Upgrader.CheckOrigin函数硬编码了只允许example.org,这直接导致从http://localhost:3000发起的WebSocket连接被拒绝。
修复方案
你需要让WebSocket的CheckOrigin逻辑和HTTP的CORS规则保持一致,有两种常用方式:
方式一:直接匹配允许的Origin
修改WebSocket传输的CheckOrigin函数,直接校验请求的Origin是否在你允许的列表里:
srv.AddTransport(&transport.Websocket{ Upgrader: websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { origin := r.Header.Get("Origin") // 匹配你允许的Origin return origin == "http://localhost:3000" }, ReadBufferSize: 1024, WriteBufferSize: 1024, }, })
方式二:复用CORS配置的检查逻辑
如果后续需要修改允许的Origin,不想重复维护两份配置,可以先创建CORS实例,然后在CheckOrigin里复用它的检查逻辑:
// 先创建CORS实例并复用 corsMiddleware := cors.New(cors.Options{ AllowedOrigins: []string{"http://localhost:3000"}, AllowCredentials: true, Debug: true, }) router.Use(corsMiddleware.Handler) // WebSocket传输配置 srv.AddTransport(&transport.Websocket{ Upgrader: websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { // 复用CORS实例的Origin检查逻辑 return corsMiddleware.AllowOrigin(r) }, ReadBufferSize: 1024, WriteBufferSize: 1024, }, })
完整修复后的代码
package main import ( "log" "net/http" "os" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/playground" "github.com/go-chi/chi" "github.com/gorilla/websocket" "github.com/megajon/gqlgen-cors/graph" "github.com/rs/cors" ) const defaultPort = "8081" func main() { port := os.Getenv("PORT") if port == "" { port = defaultPort } router := chi.NewRouter() // 创建CORS实例并复用 corsMiddleware := cors.New(cors.Options{ AllowedOrigins: []string{"http://localhost:3000"}, AllowCredentials: true, Debug: true, }) router.Use(corsMiddleware.Handler) srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}})) srv.AddTransport(&transport.Websocket{ Upgrader: websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { // 复用CORS的Origin检查逻辑 return corsMiddleware.AllowOrigin(r) }, ReadBufferSize: 1024, WriteBufferSize: 1024, }, }) router.Handle("/", playground.Handler("GraphQL playground", "/query")) router.Handle("/query", srv) log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) err := http.ListenAndServe(":"+port, router) if err != nil { panic(err) } }
关键说明
gqlgen的WebSocket传输不会自动继承路由的CORS中间件,因为WebSocket握手阶段的Origin检查是由websocket.Upgrader单独处理的,必须显式配置CheckOrigin函数来允许合法的跨域请求。
内容的提问来源于stack exchange,提问作者megajon
相关产品推荐
相关产品推荐

