Ожидает ли HttpClient всё Тело Ответа?
Если вы вызываете HttpClient.GetAsync или HttpClient.PostAsync, а затем ожидаете результат, ожидается получение только заголовков или всего тела ответа?
Сервер
Создадим простой сервер, который отправляет ответ с заголовком и телом. Тело будет отправляться частями, чтобы мы могли видеть, когда оно будет получено.
app.MapGet("/", async ctx =>
{
await ctx.Response.WriteAsync("1");
await Task.Delay(500);
await ctx.Response.WriteAsync("2");
await Task.Delay(500);
await ctx.Response.WriteAsync("3");
await ctx.Response.CompleteAsync();
});Таким образом, весь запрос занимает не менее 1 секунды. Напишем простой вызов этой конечной точки.
Клиент
using var client = new HttpClient();
// измерим время до получения ответа
var sw = Stopwatch.StartNew();
await client.GetAsync("https://localhost:5001");
Console.WriteLine(
$"Время отклика: {sw.ElapsedMilliseconds}мс");
Если выполнить этот код, мы увидим, что время ответа составляет около 1 секунды. Таким образом, await ожидает получения всего тела:
Время отклика: 1088мс
Теперь посмотрим, как можно не ждать тела. Используем опцию HttpCompletionOption.ResponseHeadersRead:
var sw = Stopwatch.StartNew();
await client.GetAsync("https://localhost:5001",
HttpCompletionOption.ResponseHeadersRead);
Console.WriteLine(
$"Время отклика: {sw.ElapsedMilliseconds}мс");
Мы добавили флаг в вызов GetAsync. Теперь время отклика значительно меньше:
Время отклика: 78мс
Таким образом await ожидает только получения заголовков, и вы можете исследовать их сразу, как они будут получены. Тело всё ещё принимается в фоновом режиме. Если вы хотите дождаться получения тела, можно использовать метод ReadAsStringAsync:
using var response =
await client.GetAsync("https://localhost:5001",
HttpCompletionOption.ResponseHeadersRead);
var body = await response.Content.ReadAsStringAsync();
Важно! Мы здесь используем using var response. Объект response продолжит удерживать ресурсы после await, поэтому необходимо удалять его как можно скорее.
Итого
Использование HttpCompletionOption.ResponseHeadersRead даёт выигрыш в производительности и памяти, и вы всё равно можете прочитать тело, если захотите. Но будьте осторожны с объектом ответа, так как он может по-прежнему удерживать ресурсы, что усложняет код. Так что это не должно быть выбором по умолчанию, если в этом нет необходимости.
Источник: https://steven-giesel.com/blogPost/e2c3bcba-4f81-42b0-9b25-060da5e819fa/does-an-httpclient-await-the-header-and-the-body