📶
connect-goとconnect-webでCORSが出た時の解決
gRPC互換の Connect について、チュートリアルを読みながら進めていたところ、CORSの解決でややハマってしまったので共有。
構成
-
server:
Go
-
connectrpc.com/connect
を使用 localhost:8080
-
-
client: Webからアクセス
-
Vite
のnpx vite
で開発環境を建てる - 公式DocのGetting Started と同じように、
@buf/connectrpc_eliza.connectrpc_es
@connectrpc/connect
@connectrpc/connect-web
を導入済み -
localhost:5173
(viteのデフォルト)
-
解決策
雑に解決するなら、Go側で github.com/rs/cors
の cors.AllowAll()
をhandlerとして使う。
func main() {
chat := &ChatServer{}
mux := http.NewServeMux()
path, handler := chatv1connect.NewChatServiceHandler(chat)
mux.Handle(path, handler)
// cors.Default()ではダメだった
// corsHandler := cors.Default().Handler(h2c.NewHandler(mux, &http2.Server{}))
// これ
corsHandler := cors.AllowAll().Handler(h2c.NewHandler(mux, &http2.Server{}))
http.ListenAndServe(
"localhost:8080",
corsHandler,
)
}
解説
cors.Default()
を使ったhandlerを使用するサンプルコードを幾つか見つけたのですが、これだとローカル環境で普通にCORSでひっかかりました。
rs/cors のデフォルト値を調べてみると、以下のように書いてあります。
AllowedMethods []string: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (GET and POST).
一方、MDNにはこうもあります。
ブラウザーが HTTP の OPTIONS リクエストメソッドを用いて、あらかじめリクエストの「プリフライト」 (サーバーから対応するメソッドの一覧を収集すること) を行い、サーバーの「認可」のもとに実際のリクエストを送信することを指示しています
恐らくrs/cors
のデフォルト設定では、OPTIONSメソッドでプリフライトメッセージが弾かれているように見えます。
その辺の記事を参考にして rs/cors
で全然解決しないが!?と1時間ぐらい悩んでました。やっぱ1次ソースをちゃんと確認しないとダメですね、反省です…
Discussion