首页 > 解决方案 > 在 HttpClient 中解压 Brotli HttpResponse

问题描述

我有一个 Web Api,它向我发送使用 brotli 压缩的响应,我有一个控制台应用程序,它通过向我的 WebApi 请求数据来使用 HttpClient。我需要解压缩我的 WebApi 发送的数据。

对于 .Net Core 2.2

启动.cs

//Compresión de respuestas del servidor

services.Configure<BrotliCompressionProviderOptions>(opciones =>
                opciones.Level = CompressionLevel.Optimal
);

services.AddResponseCompression(opciones =>
{
    opciones.EnableForHttps = true;
    opciones.Providers.Add<BrotliCompressionProvider>();
});

控制台应用程序

using (var client = new HttpClient(handler)){
    client.BaseAddress = new Uri(BASE_URL);
    client.Timeout = new TimeSpan(0, 0, TIMEOUT_SECONDS);
    HttpRequestHeaders headers = client.DefaultRequestHeaders;
    headers.Add("X-User", Environment.UserName);
    headers.Add("Accept-Encoding", "br"); //gzip
    HttpResponseMessage response = null;

    response = await client.GetAsync($"{requestUrl}");
    if (response.IsSuccessStatusCode)
    {
        string strResult = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<T>(strResult);
    }
}

strResult 不是 JSON。. .

标签: c#.net-coredotnet-httpclient

解决方案


假设您使用的是 .NET Core 2.1 中包含的 HttpClientFactory,那么您只需创建一个委托处理程序,该处理程序将在将完整的有效负载交给您的代码之前拦截并解压缩它。

using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BrotliSharpLib;

public class BrotliCompressionHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        if (!response.Content.Headers.TryGetValues("Content-Encoding", out var ce) || ce.First() != "br")
            return response;
        var buffer = await response.Content.ReadAsByteArrayAsync();
        response.Content = new ByteArrayContent(Brotli.DecompressBuffer(buffer, 0, buffer.Length));
        return response;
    }
}

然后只需将处理程序连接到您需要支持 brotli 的客户端。

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddTransient<BrotliCompressionHandler>()
        .AddHttpClient("github", c =>
        {
            c.BaseAddress = new Uri("https://api.github.com/");
            c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
            c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
        })
        .AddHttpMessageHandler<BrotliCompressionHandler>();
}

推荐阅读