如何在 Azure Functions (v2) 上启用 GZIP 压缩?

问题描述 投票:0回答:2

如何在 Azure Functions (v2) 上启用 GZIP 压缩?

我与邮递员检查过,它没有显示 GZIP

POST /api/values HTTP/1.1
Host: HOSTNAMEHERE.azurewebsites.net
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: e2c3967b-f562-df35-a3d1-01bd56cb4b76
azure azure-functions
2个回答
3
投票

这是我的错误。

当达到该功能时,GZip 似乎默认配置为 ON :)

就我而言,我使用的是本地功能,它没有附带 Gzip:

Content-Type →application/json; charset=utf-8
Date →Mon, 19 Mar 2018 00:55:06 GMT
Server →Kestrel
Transfer-Encoding →chunked

我注意到,当我在 Azure 上调用正确的 URL 时,就会出现:

Content-Encoding →gzip
Content-Type →application/json; charset=utf-8
Date →Sat, 17 Mar 2018 17:29:46 GMT
Server →Kestrel
Transfer-Encoding →chunked
Vary →Accept-Encoding
X-Powered-By →ASP.NET

0
投票

对于任何寻求相同答案但使用 AzFunc Linux 部署 的人来说,上述自动处理似乎仍未得到完全支持。

更多信息。 Github 问题仍然开放:https://github.com/Azure/azure-functions-host/issues/7285

但是,可以在代码中手动启用它,假设您可以调整代码以在启用压缩后直接写入响应正文...

我在这里提供了一个带有实现的要点:https://gist.github.com/cajuncoding/a4a7b590986fd848b5040da83979796c

这样就可以实现如下:

[FunctionName(nameof(MyHttpTriggerWithResponseCompressionSuppport))]
public Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "compressed-response-api")] HttpRequest req, ILogger logger)
{
    req.EnableResponseCompression();

    var httpResponse = req.HttpContext.Response;
    httpResponse.Headers.ContentType = "application/json";

    //DO some work and write to the HttpContext Response Body stream... all content will be compressed...
    await using var responseWriter = new StreamWriter(httpResponse.Body, Encoding.UTF8, leaveOpen: true);
    await responseWriter.WriteAsync(JsonSerializer.Serialize<object>(new
    {
        Topic = "Hello World...I'm Compressed!",
        Body = "If I was some big JSON then I'd be nicely packed for transmission!"
    }, new JsonSerializerOptions() {WriteIndented = true}));

    return new EmptyResult();
}

以下是供后代使用的要点的来源:

using System.IO.Compression;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;

namespace AzureFunctionsInProcessCompressionExtensions
{
    /// <summary>
    /// BBernard / CajunCoding (MIT License)
    /// Original Gist: https://gist.github.com/cajuncoding/a4a7b590986fd848b5040da83979796c
    /// Extension method for the HttpContext & HttpRequest to enable response compression within Azure Functions using the In Process Model -- which
    ///     does not support custom Middleware so it cannot easily intercept & handle all requests.
    /// There are many issues reported with response compression not always working, particularly with Linux deployments,
    ///     therefore this helps to easily enable this for any request by simply calling the extension method in the Function invocation.
    /// It works by simply inspecting the AcceptEncoding header to determine which, if any, compression encodings are supported (Gzip, Brotli, Deflate)
    ///     and then wrapping the Response Body Stream with the correct implementation to encode the response while also setting the correct Response Header
    ///     for the Client to correctly decode the response.
    ///
    /// This works great with GraphQL via Azure Functions (In Process Model) using HotChocolate GraphQL server allowing for compression of large
    ///     GraphQL Query results which can significantly improve performance in use cases with large query result sets.
    /// </summary>
    internal static class AzureFunctionsInProcessCompressionExtensions
    {        
        public static class AcceptCompressionNames
        {
            public const string Gzip = "gzip";
            public const string Brotli = "br";
            public const string Deflate = "deflate";
        }

        public static HttpRequest EnableResponseCompression(this HttpRequest httpRequest)
            => httpRequest.HttpContext.EnableResponseCompression().Request;
        public static HttpContext EnableResponseCompression(this HttpContext httpContext, CompressionLevel compressionLevel = CompressionLevel.Fastest)
        {
            var acceptCompressionTypes = httpContext.Request.Headers.AcceptEncoding
                .SelectMany(v => v.Split(','))
                .Select(v => v.Trim().ToLower())
                .ToArray();

            if (acceptCompressionTypes.Length <= 0)
                return httpContext;

            var httpResponse = httpContext.Response;
            var responseStream = httpResponse.Body;
            var responseHeaders = httpResponse.Headers;

            foreach (var compressionType in acceptCompressionTypes)
            {
                switch (compressionType)
                {
                    case AcceptCompressionNames.Gzip:
                        httpResponse.Body = new GZipStream(responseStream, compressionLevel, leaveOpen: false);
                        responseHeaders.ContentEncoding = new StringValues(AcceptCompressionNames.Gzip);
                        return httpContext;
                    case AcceptCompressionNames.Brotli:
                        httpResponse.Body = new BrotliStream(responseStream, compressionLevel, leaveOpen: false);
                        responseHeaders.ContentEncoding = new StringValues(AcceptCompressionNames.Brotli);
                        return httpContext;
                    case AcceptCompressionNames.Deflate:
                        httpResponse.Body = new DeflateStream(responseStream, compressionLevel, leaveOpen: false);
                        responseHeaders.ContentEncoding = new StringValues(AcceptCompressionNames.Deflate);
                        return httpContext;
                }
            }

            return httpContext;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.