lelelemon’s blog

カメの歩みでのんびり学んでいます。

【トラブルシュート - Golang】gqlgen で生成した GraphQL API と WebSocket 通信できない

gqlgen.com

 

gqlgen version: v0.17.44

 

gqlgen 公式の手順に従いAPIを作成し、

const wsLink = new GraphQLWsLink(
  createClient({
    url: "ws://localhost:8080/query",
  })
);

 

Apollo Client を使って上記のように WebSocket 通信を確立しようとしたものの、

ChatMessage.tsx:16  WebSocket connection to 'ws://localhost:8080/query' failed:

のエラーに遭遇したときの対応です。

 

エラーの原因

エラーの原因は下記箇所でした。

srv := handler.NewDefaultServer

 

golang のサーバー側では下記エラーがコンソール出力されています。

unable to upgrade *http.response to websocket websocket: request origin not allowed by Upgrader.CheckOrigin: 

 

handler.NewDefaultServer 関数の中身のコードをみてみると、

func NewDefaultServer(es graphql.ExecutableSchema) *Server {
    srv := New(es)

    srv.AddTransport(transport.Websocket{
        KeepAlivePingInterval: 10 * time.Second,
    })
    srv.AddTransport(transport.Options{})
    srv.AddTransport(transport.GET{})
    srv.AddTransport(transport.POST{})
    srv.AddTransport(transport.MultipartForm{})

    srv.SetQueryCache(lru.New(1000))

    srv.Use(extension.Introspection{})
    srv.Use(extension.AutomaticPersistedQuery{
        Cache: lru.New(100),
    })

    return srv
}

 

上記のようになっており、transport.Websocket の箇所でOriginまわりの設定がないです。

 

エラー対応

handler.New 関数でサーバーを生成し、あとから WebSocket まわりの設定を追加することで WebSocket 通信できるようになりました。

 

srv := handler.New(
        graph.NewExecutableSchema(
            graph.Config{Resolvers: graph.NewResolver()}),
    )

    // add ws transport configured by ourselves
    srv.AddTransport(transport.Options{})
    srv.AddTransport(transport.GET{})
    srv.AddTransport(transport.POST{})
    srv.AddTransport(transport.MultipartForm{})
    srv.AddTransport(&transport.Websocket{
        Upgrader: websocket.Upgrader{
            //ReadBufferSize:  1024,
            //WriteBufferSize: 1024,
            CheckOrigin: func(r *http.Request) bool {
                // add checking origin logic to decide return true or false
                return true
            },
        },
        KeepAlivePingInterval: 10 * time.Second,
    })

 

同じエラーでハマっている方は上記試してみてください。

 

(この記事は、以下を参考にさせていただきました。)

stackoverflow.com

 

vallettaio.hatenablog.com