APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

GolangのgrpcwebでCORSエラーが出る時はOriginFuncを確認しよう

はじめに

先進サービス開発事業部の山岡です。

小ネタですが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 }),
    )

これでサーバーをリロードすれば解消されるはずです。