Nginx 使用参数压缩 mime 类型

Nginx compress mime types with parameters

我让 Nginx 反向代理我的服务,该服务通过 OData 协议工作。我正在尝试通过

来为这些请求启用压缩
#...
gzip on;
gzip_types application/json;
#...
server {
   #...
   location /odata/ {
      proxy_pass http://localhost:7700/odata/;
   }
   #...
}

在 nginx.conf.

有时候我的服务returns

Content-Type: application/json; charset=utf-8; odata.metadata=minimal

Nginx 对其进行压缩。

但有时我的服务returns

Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8

并且 Nginx 不会压缩此类响应。

我应该怎么做才能使 Nginx 压缩此类响应?

通过在我的应用程序中编写中间件解决了这个问题,它更改了 Content-Type header 并将其转换为 application/json; charset=utf-8; odata.metadata=minimal; odata.streaming=true;

之后 Nginx 可以将其识别为 json 内容类型并对其进行压缩。

让我为 ASP.NET Core 添加我的解决方案。

请注意,尽管这些响应是分块的,因此 Nginx 参数 gzip_min_length 将不起作用,小响应将被 gzip 压缩,同时增加大小并降低性能。

/// <summary>
/// Middleware to reorder Content-Type parts for Nginx compression.
/// </summary>
public class FixODataMiddlewareForNginx
{
    readonly RequestDelegate _next;

    public FixODataMiddlewareForNginx(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Response.OnStarting(() =>
        {
            var contentType = context.Response.GetTypedHeaders().ContentType;
            if (contentType != null && 
                contentType.Parameters.Count > 0 && 
                !contentType.Charset.HasValue)
            {
                contentType.Parameters.Insert(0, new NameValueHeaderValue("charset", "utf-8"));
                context.Response.Headers["Content-Type"] = contentType.ToString();
            }
            return Task.CompletedTask;
        });
        await _next.Invoke(context);
    }
}