はじめに
先進サービス開発事業部の山岡です。
小ネタですがgrpcweb *1 の検証をしている時にCORSエラーでハマったので対処法をメモしておきます。
症状
定番である Access to XMLHttpRequest at 'http://localhost:8080/helloworld.Greeter/SayHello' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
が発生していました。
CORSのpreflightに失敗しているときのアレです。
原因
grpcweb.WrapServer()
で生成されるラップされたサーバーはデフォルトでは全てのオリジンを拒否するようになっていることが原因でした。
var ( defaultOptions = &options{ allowedRequestHeaders: []string{"*"}, corsForRegisteredEndpointsOnly: true, originFunc: func(origin string) bool { return false }, allowNonRootResources: false, } )
対処方法
originFuncは引数としてオリジンが渡されるので(例えば http://localhost:3000
のように)これを必要に応じて判定して許可するならばtrueを、拒否するならfalseを返却すればOKです。今回の例では手元の検証だけなので全許可するようにしました。変更するには下記のようにWrapServerにオプションを渡します。
func main() { s := grpc.NewServer() pb.RegisterSomeServer(s, &someService{}) wrappedServer := grpcweb.WrapServer( s, grpcweb.WithOriginFunc(func(origin string) bool { return true }), )
これでサーバーをリロードすれば解消されるはずです。