ASP.NET Web API の HttpClient メッセージ ハンドラー
メッセージ ハンドラーは、HTTP 要求を受け取り、HTTP 応答を返すクラスです。
通常、一連のメッセージ ハンドラーは連鎖しています。 最初のハンドラーは HTTP 要求を受け取り、何らかの処理を行って、次のハンドラーにその要求を渡します。 ある時点で応答が作成され、連鎖をさかのぼります。 このパターンは、デリゲート ハンドラーと呼ばれます。
クライアント側では、HttpClient クラスはメッセージ ハンドラーを使用して要求を処理します。 既定のハンドラーは HttpClientHandler で、ネットワーク経由で要求を送信し、サーバーから応答を取得します。 カスタム メッセージ ハンドラーをクライアント パイプラインに挿入できます。
Note
ASP.NET Web API では、サーバー側のメッセージ ハンドラーも使用されます。 詳細については、HTTP メッセージ ハンドラーを参照してください。
カスタム メッセージ ハンドラー
カスタム メッセージ ハンドラーを記述するには、System.Net.Http.DelegatingHandler から派生し、SendAsync メソッドをオーバーライドします。 このメソッド シグネチャを次に示します。
Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken);
このメソッドは、HttpRequestMessage を入力として受け取り、HttpResponseMessage を非同期的に返します。 一般的な実装では、次の処理が行われます。
- 要求メッセージを処理します。
base.SendAsync
を呼び出して、内部ハンドラーに要求を送信します。- 内部ハンドラーは応答メッセージを返します。 (この手順は非同期です。)
- 応答を処理し、呼び出し元に返します。
次の例は、送信要求にカスタム ヘッダーを追加するメッセージ ハンドラーを示しています。
class MessageHandler1 : DelegatingHandler
{
private int _count = 0;
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
System.Threading.Interlocked.Increment(ref _count);
request.Headers.Add("X-Custom-Header", _count.ToString());
return base.SendAsync(request, cancellationToken);
}
}
base.SendAsync
の呼び出しは非同期です。 ハンドラーがこの呼び出しの後に何らかの処理を行う場合は、await キーワードを使用して、メソッドの完了後に実行を再開します。 次の例は、エラー コードをログに記録するハンドラーを示しています。 ログ自体はあまり興味深くはありませんが、この例ではハンドラー内の応答を取得する方法を示しています。
class LoggingHandler : DelegatingHandler
{
StreamWriter _writer;
public LoggingHandler(Stream stream)
{
_writer = new StreamWriter(stream);
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
_writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri,
(int)response.StatusCode, response.Headers.Date);
}
return response;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_writer.Dispose();
}
base.Dispose(disposing);
}
}
クライアント パイプラインへのメッセージ ハンドラーの追加
HttpClient にカスタム ハンドラーを追加するには、HttpClientFactory.Create メソッドを使用します。
HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());
メッセージ ハンドラーは、Create メソッドに渡す順序で呼び出されます。 ハンドラーは入れ子になっているため、応答メッセージは他の方向に移動します。 つまり、最後のハンドラーが最初に応答メッセージを取得します。