1923

都内と業界の隅っこで生活しているエンジニアのノート

gRPC-Web for .NET のサービスを Azure App Service にデプロイしてブラウザからアクセスする

gRPC-Web for .NETが正式リリースされましたので、簡単なアプリを Azure App Service にデプロイしてWebブラウザからアクセスしてみます。
詳しい手順が書かれた公式ドキュメントが揃っていますのでメモ程度です。

環境 - Windows 10 / Visual Studio 2019

Server

チュートリアル: ASP.NET Core で gRPC のクライアントとサーバーを作成するブラウザー アプリでの gRPC の使用を参考にgRPC・gRPC-webに対応したサーバーを作成します。

ざっくり以下な感じです。

  1. gRPC サービスのプロジェクトを作成
  2. Grpc.AspNetCore パッケージを 2.29 以降に更新し、Grpc.AspNetCore.Web パッケージを追加
  3. UseGrpcWeb と EnableGrpcWeb を Startup.cs に追加
  4. CORSの設定。CORSはローカルで開発する際に必要ですが、App Service では設定で対応できます。
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            _configuration = configuration;
            _env = env;
        }

        private readonly IConfiguration _configuration;
        private readonly IWebHostEnvironment _env;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddGrpc();

            if (_env.IsDevelopment())
            {
                services.AddCors(o => o.AddPolicy("AllowAll", builder =>
                {
                    builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
                }));
            }
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();

            app.UseGrpcWeb();

            if (env.IsDevelopment())
            {
                app.UseCors();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb().RequireCors("AllowAll");
                });
            }
            else
            {
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
                });
            }
        }
    }

あとは 普通に App Service にデプロイすればサーバーの準備は完了です。App Serviceの構成にHTTPバージョンの設定がありますので2.0に変更も可能です。

Client

デプロイした gRPC-web にWebブラウザでアクセスするクライアントを作成します。

最初にprotobufスキーマからJavaScriptなどを生成する protoc と grpc-web を準備します。それぞれ実行可能なバイナリファイルを以下からダウンロード。適当にパスの通ったフォルダにコピーし、grpc-webは protoc-gen-grpc-web.exe に名前を変更します。

protoc
https://github.com/protocolbuffers/protobuf/releases

grpc-web
https://github.com/grpc/grpc-web/releases

今回は TypeScriptで書きたいのでimport_styleにcommonjs, typescriptを指定してコマンドを実行し、gRPCのJavaScript・型定義ファイル、grpc-web の TypeScriptのファイルを作成します。また、protoファイルは Server で使用した greet.proto をそのまま使っています。

コマンド例

protoc --proto_path= greet.proto --js_out=import_style=commonjs:./ --grpc-web_out=import_style=typescript,mode=grpcwebtext:./

生成されたファイル

  • greet_pb.js
  • greet_pb.d.ts
  • GreetServiceClientPb.ts

Vue CLI などでクライアントプロジェクトを作成して、上記で作成したファイルを適当な場所にコピーすれば準備完了です。 以下のようにアクセスできます。

import Vue from "vue";
import { HelloRequest } from "../models/greet_pb";
import { GreeterClient } from "../models/GreetServiceClientPb";
export default Vue.extend({
  name: "Home",
  components: {
    HelloWorld
  },
  data() {
    return {
      msg: ""
    };
  },
  mounted: function() {
    const request = new HelloRequest();
    request.setName("匿名希望");

    const client = new GreeterClient(
      "https://xxxxx.azurewebsites.net",
      {},
      {}
    );
    client.sayHello(request, {}, (err, ret) => {
      if (err || ret === null) {
        console.log(err);
      } else {
        this.msg = ret.getMessage();
      }
    });
  }
});

参考