Обработчики сообщений HttpClient в веб-API ASP.NET
Обработчик сообщений — это класс, который получает HTTP-запрос и возвращает HTTP-ответ.
Как правило, ряд обработчиков сообщений объединяются в цепочку. Первый обработчик получает HTTP-запрос, выполняет некоторую обработку и передает запрос следующему обработчику. В какой-то момент создается ответ и возвращается вверх по цепочке. Этот шаблон называется делегированным обработчиком.
На стороне клиента класс HttpClient использует обработчик сообщений для обработки запросов. Обработчик по умолчанию — HttpClientHandler, который отправляет запрос по сети и получает ответ от сервера. Вы можете вставить пользовательские обработчики сообщений в клиентский конвейер:
Примечание
веб-API ASP.NET также использует обработчики сообщений на стороне сервера. Дополнительные сведения см. в разделе Обработчики сообщений 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 . Так как обработчики являются вложенными, ответное сообщение перемещается в другом направлении. То есть последний обработчик является первым, кто получает ответные сообщения.