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

The*_*his 8 c# asp.net-web-api dotnet-httpclient asp.net-core-2.0

我发送的请求可能非常大(~1Mb),我发现当我发出请求时和asp.net核心日志处理请求时有很大的延迟.我想我可以通过使用gzip压缩对asp的请求来减少这段时间.

下面是我在没有压缩的情况下提出请求的相当直接的方式.在客户端请求端实现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));
    }
}
Run Code Online (Sandbox Code Playgroud)

The*_*his 12

所以我让它在服务器端使用简单的中间件,而在客户端没有太多的工作.我使用了来自WebAPIContrib github项目的CompressedContent.cs,正如Rex在他的回答的评论中所建议的那样,并且如下所示提出了请求.整个抛出异常,如果不行,是因为我正在使用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));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在服务器端我创建了一个简单的中间件,用Gzip流包装请求正文流,我很确定你需要把app.UseMvc()之前的中间件放在configure函数中(我仍然使用ASPcore 1启动风格).

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);
    }
}
Run Code Online (Sandbox Code Playgroud)