如何使用HttpClient压缩请求到asp.net core 2站点的最佳方法是什么?

14
我正在发送一个请求,它可能非常大(~1Mb),并且在我发出请求和 asp.net core 记录它正在处理请求之间存在很大的延迟。我认为我可以通过使用 gzip 压缩请求来缩短这个时间。
以下是我在没有压缩的情况下进行请求的相当简单的方式。如何在客户端实现 Gzip 请求压缩的正确方式?一旦我在客户端实现了它,服务器端需要做什么?
using (HttpResponseMessage response = client.PostAsync("Controller/Action", httpContent).Result)
{
    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    {

        throw new Exception(string.Format("Invalid responsecode for http request response {0}: {1}", response.StatusCode, response.ReasonPhrase));
    }
}
2个回答

24

所以我通过简单的服务器中间件,并在客户端上不需要太多工作,使其工作起来了。我使用了WebAPIContrib的CompressedContent.cs,正如Rex在他的回答评论中建议的那样,并按下面所示进行了请求。整个抛出异常如果不是OK的原因是因为我在我的请求周围使用了Polly包装,具有重试和等待策略。

客户端:

using (var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json"))
using (var compressedContent = new CompressedContent(httpContent, "gzip"))
using (HttpResponseMessage response = client.PostAsync("Controller/Action", compressedContent).Result)
{
    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    {
        throw new Exception(string.Format("Invalid responsecode for http request response {0}: {1}", response.StatusCode, response.ReasonPhrase));
    }
}

接着在服务器端我创建了一个简单的中间件,用Gzip流包装请求主体流。要使用它,您需要在Startup.csConfigure方法中,在调用app.UseMvc();之前添加以下代码行:app.UseMiddleware<GzipRequestMiddleware>();

public class GzipRequestMiddleware
{
    private readonly RequestDelegate next;
    private const string ContentEncodingHeader = "Content-Encoding";
    private const string ContentEncodingGzip = "gzip";
    private const string ContentEncodingDeflate = "deflate";

    public GzipRequestMiddleware(RequestDelegate next)
    {
        this.next = next ?? throw new ArgumentNullException(nameof(next));
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains(ContentEncodingHeader) && (context.Request.Headers[ContentEncodingHeader] == ContentEncodingGzip || context.Request.Headers[ContentEncodingHeader] == ContentEncodingDeflate))
        {
            var contentEncoding = context.Request.Headers[ContentEncodingHeader];
            var decompressor = contentEncoding == ContentEncodingGzip ? (Stream)new GZipStream(context.Request.Body, CompressionMode.Decompress, true) : (Stream)new DeflateStream(context.Request.Body, CompressionMode.Decompress, true);
            context.Request.Body = decompressor;
        }
        await next(context);
    }
}

1
您可能需要按如下所示启用压缩:

var handler = new HttpClientHandler();  
if (handler.SupportsAutomaticDecompression)  
{
    handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}

var client = new HttpClient(handler);  

MSDN参考: 使用HttpClient自动解压缩


1
一个 MSDN 参考链接会很完美。 - Jeremy Thompson
https://blogs.msdn.microsoft.com/dotnet/2013/06/06/portable-compression-and-httpclient-working-together/ - Rex
5
也许我有所遗漏,但那似乎只处理响应解压缩而不是请求压缩,对吗? - BillHaggerty
@Theyouthis - 没错。这会在客户端向服务器发送请求时添加额外的Accept-Encoding头,指示服务器它支持压缩响应。但是要启用压缩请求,则需要使用WebAPIContrib中的CompressedContent类,并在框架中有一些限制。https://dev59.com/ImQn5IYBdhLWcg3wpYj0#16674884 - Rex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接