在 HttpClient 中解压 Brotli HttpResponse

Posted

技术标签:

【中文标题】在 HttpClient 中解压 Brotli HttpResponse【英文标题】:Decompress Brotli HttpResponse in a HttpClient 【发布时间】:2019-07-15 11:27:34 【问题描述】:

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

对于 .Net Core 2.2

Startup.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>();
);

ConseleApp

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。 . .

【问题讨论】:

看看这里:***.com/a/27327208/4035472 同样适用于 brotli。 我需要brotli解压 Brotli 可从 .net core 3.0+ 获得,请参阅 docs.microsoft.com/en-us/dotnet/api/… 我使用.Net Core 2.2 好吧,要么升级你的项目,自己实现 brotli 解压,要么如果你不接受就不要发送 Accept-Encoding: br 标头。 【参考方案1】:

假设您使用的是 .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>();

【讨论】:

【参考方案2】:

我使用 Brotli.NET 实现如下:

static async Task<string> GetLinkTitle(string link) => await Task.Run(async () =>

    using (var httpGet = new System.Net.Http.HttpClient())
    
        httpGet.DefaultRequestHeaders.Add("Accept-Encoding", "br");
        var response = await httpGet.GetAsync($"http://www.youtube.com/oembed?url=link&format=xml");
        
        string responseContent;
        using(var brotli = new Brotli.BrotliStream(await response.Content.ReadAsStreamAsync(), System.IO.Compression.CompressionMode.Decompress, true))
        
            var streamReader = new StreamReader(brotli);
            responseContent = streamReader.ReadToEnd();
        

        var doc = XDocument.Parse(responseContent);
        return !response.IsSuccessStatusCode ? $"ERROR: response.StatusCode - link".Dump() : doc.Descendants("title").FirstOrDefault().Value;
    
);

【讨论】:

【参考方案3】:

您是否尝试过以下 .Net 库之一:

    https://www.nuget.org/packages/Brotli.NET/ https://www.nuget.org/packages/BrotliSharpLib/

两者都支持 Brotli 压缩和解压缩,无需 .Net 原生支持。他们声称也比 .Net 实现更快。

【讨论】:

以上是关于在 HttpClient 中解压 Brotli HttpResponse的主要内容,如果未能解决你的问题,请参考以下文章

使用 brotli 压缩文件和目录列表

请求接口返回数据的Content-type为br解析

从 HTTPClient 响应中解压 GZip 流

启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%

启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%

如何使用 DirectAdmin 在 Debian 10 上启用 Brotli?