HTTP/2 をベースとする gRPC にもヘッダーがあり、そこに任意のデータを含めて通信することができます。今回はそんなヘッダーをどうやって利用するのか、その方法について解説します。
ヘッダーにデータを詰めて送信する
ヘッダーは Key-Value 形式となっており、文字列か byte 配列 のいずれかの値を詰めることができます。データは以下のように Metadata
型に格納し、WithHeaders
メソッドでヘッダーに追加します。
using System; using System.Threading.Tasks; using Grpc.Core; using MagicOnion.Client; using MagicOnionSample.ServiceDefinition; namespace MagicOnionSample.Client { class Program { static void Main() => MainAsync().Wait(); static async Task MainAsync() { var channel = new Channel("localhost", 12345, ChannelCredentials.Insecure); //--- ヘッダーに詰めるメタデータを生成 var metadata = new Metadata(); metadata.Add("Key", "Value"); metadata.Add("Key-bin", new byte[]{ 1, 2 }); /* //--- この書き方でも OK var metadata = new Metadata() { new Metadata.Entry("Key", "Value"), new Metadata.Entry("Key-bin", new byte[]{ 1, 2 }), }; */ //--- ヘッダーにメタデータを追加 var client = MagicOnionClient.Create<ISampleApi>(channel).WithHeaders(metadata); //--- あとはいつも通り通信しましょう var result = await client.Sample(); //--- アプリが終了しないように Console.ReadLine(); } } }
サーバー側でヘッダーに格納されたデータを取り出す場合は CallContext.RequestHeaders
を利用します。例えば以下のようになります。
using System; using MagicOnion; using MagicOnion.Server; using MagicOnionSample.ServiceDefinition; using MessagePack; namespace MagicOnionSample.Service { public class SampleApi : ServiceBase<ISampleApi>, ISampleApi { public async UnaryResult<Nil> Sample() { //--- ヘッダーから値を取り出す var header = this.Context.CallContext.RequestHeaders; var value1 = header.Get("Key").Value; var value2 = header.Get("Key-bin").ValueBytes; Console.WriteLine(value1); Console.WriteLine($"{{{value2[0]}, {value2[1]}}}"); return Nil.Default; } } }
たったこれだけでヘッダーを経由したデータの送受信ができました。簡単ですね!
バイナリデータを送信する場合の注意
ヘッダーに文字列を詰めて送信する場合は特に何も気にしなくて良いのですが、バイナリ (byte 配列) を扱う場合はキー名に -bin
の接尾辞を付けるというルールがあるので注意が必要です。-bin
なしでキーを設定すると以下のような例外が発生します。
Key for binary valued metadata entry needs to have suffix indicating binary value.
ちなみに -bin
という文字列は gRPC のライブラリに Metadata.BinaryHeaderSuffix
として定義されているので、それを利用しても OK です。
metadata.Add("Key-bin", new byte[]{ 1, 2 }); metadata.Add($"Key{Metadata.BinaryHeaderSuffix}", new byte[]{ 1, 2 });
ヘッダーの使いどころ
そんなヘッダーの利用タイミングですが、たとえば以下のようなときに便利です。困ったときの最終手段として覚えておくと良さそうです。