blog.syfm

徒然なるままに考えていることなどを書いていくブログ

Evans v0.9.0 をリリースしました

汎用 gRPC クライアントである Evans の v0.9.0 をリリースしました。最後にリリースしたのは昨年末だったので、実に 5 ヶ月ぶりとなります。
今回のコードネームは GOLD RUSH です。

このリリースでは、多くの機能追加、バグ修正等があったため、特徴的なものに関してリリースノートを書こうと思います。

REPL モード

call コマンドに --dig-manually フラグを追加

REPL モードでは、入力対象の message について深さ優先探索を行い、プリミティブフィールドが現れると入力用のプロンプトが表示されるような仕様になっていますが、この実装だとネストされた message 自体に値を何もセットしたくない場合 (Go だと nil を設定したい場合) をサポートできていませんでした。 例えば、以下のような Protocol Buffers 定義があり、Request が入力である場合、Evans は自動的にネストされているメッセージのフィールド Foo.bar への入力を求めるため、そもそも Foo を入力したくない場合は --dig-manually フラグなしでは実現できません。--dig-manually フラグが有効になっている場合、Request.foo フィールドを入力するかどうかのプロンプトが表示されるため、入力をスキップすることができます。

message Foo {
  string bar = 1;
}

message Request {
  Foo foo = 1;
}

header コマンドに --raw フラグを追加

header コマンドの value にカンマ区切りで複数の値を同時に指定できますが、その影響により v0.9.0 以前の Evans では、カンマを含めた value を指定することができませんでした。カンマを value に含めてしまうと、それがデリミタとして解釈されてしまい、value が分割されてしまうためです。
今回新しく導入された --raw フラグは、value を "raw" string として扱うためのものです。これを使うことでカンマが含まれていても正常に指定することができるようになります。

f:id:ktr_0731:20200423004246p:plain

コマンドヒストリ

実行したコマンドをシェル環境のようにコマンドヒストリから探し出すことができるようになりました。↑↓キーもしくは Ctrl+PCtrl-N でヒストリを辿ることができます。残念ながら、Ctrl+R (reverse search) や Ctrl+S (forward search) は未サポートです。*1

パッケージが指定されていない Protocol Buffers 定義の許容

v0.9.0 以前の Evans の REPL モードでは対象の gRPC サービスのパッケージ名を指定することが必須になっていましたが、Protocol Buffers ではパッケージ名を省略することができるため、パッケージ名が省略された gRPC 定義を使用することができませんでしたが v0.9.0 では修正されています。

フラグ補完

REPL モードの各コマンドにはフラグを指定することができますが、v0.9.0 ではフラグの補完も有効になります。例えば call コマンドでは以下のように - を入力した時点で補完候補が現れるようになります。

f:id:ktr_0731:20200502181241p:plain

CLI モード

cli コマンドに属するサブコマンドの追加

今回のリリースで導入された大きな機能の一つです。 cli コマンドにサブコマンドが追加されました。今後は cli コマンドに属するサブコマンドを使用してください。詳しくは各サブコマンドのヘルプに使用例が記載されています。

$ echo '{}' | evans -r cli call Unary

以下のような既存のインターフェースは依然として使えますが非推奨となります。v1.0.0 で削除される予定です。

$ echo '{}' | evans -r --cli --call Unary
$ echo '{}' | evans -r cli --call Unary

call コマンドの追加

前述した通りです。

list コマンドの追加

grpc_cligrpcurl に用意されているような、gRPC サーバに対してサービスやメソッドを列挙する機能です。 以下のように使うことができます。

$ evans -r cli list # サービスの列挙
api.Example
grpc.reflection.v1alpha.ServerReflection

$ evans -r cli list api.Example # api.Example サービスに属するメソッドの列挙
api.Example.Unary
...

また、--output (-o) フラグが用意されており、リクエスト・レスポンスの型を含めた詳細を JSON で出力することも可能です。

$ evans -r cli list -o json api.Example.Unary
{
  "name": "Unary",
  "fully_qualified_name": "api.Example.Unary",
  "request_type": "api.SimpleRequest",
  "response_type": "api.SimpleResponse"
}

desc コマンドの追加

grpc_cligrpcurl に用意されているような、gRPC サーバが登録しているサービスやメッセージなどのシンボルの詳細を Protocol Buffers のフォーマットで表示する機能です。 以下のように使うことができます。

$ evans -r cli desc api.Example
api.Example:
service Example {
  rpc Unary ( .api.SimpleRequest ) returns ( .api.SimpleResponse );
  ...
}

$ evans -r cli desc api.Example.Unary
api.Example.Unary:
rpc Unary ( .api.SimpleRequest ) returns ( .api.SimpleResponse );

$ evans -r cli desc api.SimpleRequest
api.SimpleRequest:
message SimpleRequest {
  string name = 1;
}

モード共通

レスポンス表示の強化

今回のリリースで導入された最も大きな機能のもう一つです。v0.9.0 以前では gRPC サービスからのレスポンスのうち、レスポンスコードが OK もしくはそれ以外かの表示、レスポンスボディ、エラーメッセージのみしか表示することができていませんでしたが、新たに ヘッダメタデータ、トレイラーメタデータ、レスポンスコード、エラー詳細 (errdetails など) を表示することができるようになりました。

REPL モードでは call コマンドに --enrich フラグを指定することで有効になります。

f:id:ktr_0731:20200502182325p:plain
正常系の例

f:id:ktr_0731:20200502182541p:plain
異常系の例

CLI モードでも同様に call コマンドに --enrich フラグを指定することで有効になります。

f:id:ktr_0731:20200502182751p:plain

また、CLI モードでは --output (-o) フラグが用意されており、JSON 形式で出力することもできます。

f:id:ktr_0731:20200502182857p:plain

gRPC-Web サービスで正しくヘッダーが送れていない問題の修正

頑張って修正しました。Evans では、gRPC-Web の Improbable 社による実装をサポートしていますが、gRPC-Web は Web ブラウザのみをクライアントとする前提を置いているため JavaScript のクライアント実装しか存在していません。しかし、Evans は pure Go 実装であるため、Evans から gRPC-Web に準拠したリクエストを投げるには Go 実装を作る必要があり、ktr0731/grpc-web-go-client を開発していました。今回の修正は主にこのライブラリの修正となっています。

終わりに

今回の機能追加や変更は v1.0.0 のリリースの前段階といえます。具体的なリリース予定は未定ですが、v1.0.0 では複数の破壊的変更を予定しています。こちらについてはまた別途記事を書ければと思います。

Evans の開発は Issue 報告者、contributor および GitHub Sponsors で支援を頂いている方々から成り立っています。いつもありがとうございます!

*1:これは c-bata/go-prompt の制約によるものです。気力があれば実装して contribution したいけどない 😇