nginx中gzip_types匹配content-type的方式

 更新时间:2024年05月14日 10:48:42   作者:u010971572  
这篇文章主要介绍了nginx中gzip_types匹配content-type的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1.背景

我们系统中有一个功能,可以配置content-type类型来决定是否打开gzip压缩。

这个配置与nginx官方的gzip_type不同的地方在于,nginx官方的是写死在配置文件中的,所有请求都生效;我们自研的是,不同用户的gzip_type可以不同。

最近发现一个问题

content-type配置为:image/jpeg,但是后端响应的Content-Type为"

image/jped;charset:UTF-8"时,由于代码中是将配置的content-type与响应头中字符串作精确比较,因此,上述场景,并不能正确打开gzip功能。

nginx对此是如何处理的呢?

后端响应的Content-Type保持为image/jped;charset:UTF-8。

1、配置gzip_type 如下,gzip生效:

gzip_type image/jpeg;

2、配置gzip_type如下,gzip不生效:(nginx官方文档中也没有提及下面的配置方法)

gzip_type "image/jpeg;charset:UTF-8";

2.nginx处理流程

在进行header_filter时,对content-Type做了校验:

static ngx_int_t
ngx_http_gzip_header_filter(ngx_http_request_t *r)
{
    ngx_table_elt_t       *h;
    ngx_http_gzip_ctx_t   *ctx;
    ngx_http_gzip_conf_t  *conf;

    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);

    if (!conf->enable
        || (r->headers_out.status != NGX_HTTP_OK
            && r->headers_out.status != NGX_HTTP_FORBIDDEN
            && r->headers_out.status != NGX_HTTP_NOT_FOUND)
        || (r->headers_out.content_encoding
            && r->headers_out.content_encoding->value.len)
        || (r->headers_out.content_length_n != -1
            && r->headers_out.content_length_n < conf->min_length)
            // ngx_http_test_content_type中对content_type做了校验
        || ngx_http_test_content_type(r, &conf->types) == NULL
        || r->header_only)
    {
        return ngx_http_next_header_filter(r);
    }
    ...
    }

ngx_http_test_content_type定义如下:

void *
ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
{
    u_char      c, *lowcase;
    size_t      len;
    ngx_uint_t  i, hash;

    if (types_hash->size == 0) {
        return (void *) 4;
    }

    if (r->headers_out.content_type.len == 0) {
        return NULL;
    }

    len = r->headers_out.content_type_len;

    if (r->headers_out.content_type_lowcase == NULL) {

        lowcase = ngx_pnalloc(r->pool, len);
        if (lowcase == NULL) {
            return NULL;
        }

        r->headers_out.content_type_lowcase = lowcase;

        hash = 0;

        for (i = 0; i < len; i++) {
            c = ngx_tolower(r->headers_out.content_type.data[i]);
            hash = ngx_hash(hash, c);
            lowcase[i] = c;
        }

        r->headers_out.content_type_hash = hash;
    }

    return ngx_hash_find(types_hash, r->headers_out.content_type_hash,
                         r->headers_out.content_type_lowcase, len);
}

可以看出,将content-type头域内容转换为了小写,并使用了r->headers_out.content_type_len长度的内容,与配置的types进行比较。

但是针对第1种情况,配置和实际响应头明明是不相等的啊,是这么匹配成功的?

使用gdb打断点,发现

  • r->headers_out.content_type为:
  • {len = 24, data = “image/jpeg;charset=UTF-8”}
  • 但是,
  • r->headers_out.content_type_len却是10!这个与上面为什么不一致呢?

找到设置content_type的地方:

static ngx_int_t
ngx_http_set_content_type_header(ngx_http_request_t *r,
    ngx_http_lua_header_val_t *hv, ngx_str_t *value)
{
    ngx_uint_t          i;

	// 此时,r->headers_out.content_type_len与 value->len 还是相等的
    r->headers_out.content_type_len = value->len;


#if 1

    for (i = 0; i < value->len; i++) {
        if (value->data[i] == ';') {
        	// 找到第一个分号,然后修改了r->headers_out.content_type_len
            r->headers_out.content_type_len = i;
            break;
        }
    }
#endif

    r->headers_out.content_type = *value;
    r->headers_out.content_type_hash = hv->hash;
    r->headers_out.content_type_lowcase = NULL;

    value->len = 0;

    return ngx_http_set_header_helper(r, hv, value, NULL, 1);
}

可以看出,nginx只使用了Content-Type响应头中第一个分号前的内容进行匹配。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • NGINX报错413 Request Entity Too Large的问题解决

    NGINX报错413 Request Entity Too Large的问题解决

    Nginx 413错误表示请求实体太大,本文主要介绍了NGINX报错413 Request Entity Too Large的问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08
  • Nginx的流式响应配置实现小结

    Nginx的流式响应配置实现小结

    nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器,本文主要介绍了Nginx的流式响应配置实现小结,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • Nginx中实现请求的缓存数据过期通知

    Nginx中实现请求的缓存数据过期通知

    Nginx 作为高性能的反向代理服务器,缓存机制是其优化性能的重要手段之一,本文主要介绍了Nginx中实现请求的缓存数据过期通知,感兴趣的可以了解一下
    2024-09-09
  • Nginx HTTP Status 400 – 错误的请求问题解决

    Nginx HTTP Status 400 – 错误的请求问题解决

    本文主要介绍了在配置Nginx反向代理两个Tomcat站点时遇到HTTPStatus400错误,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • Nginx 配置TCP代理转发的实现

    Nginx 配置TCP代理转发的实现

    本文主要介绍了使用Nginx新版的stream方式,实现TCP/UDP代理转发,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-10-10
  • nginx设置资源缓存实战详解

    nginx设置资源缓存实战详解

    这篇文章主要介绍了nginx设置资源缓存实战详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Nginx配置Gzip的实现步骤

    Nginx配置Gzip的实现步骤

    本文详细介绍了如何在Nginx中配置Gzip压缩,以减小传输的文件大小,提高网页加载速度,具体步骤包括找到并编辑Nginx配置文件,添加或修改Gzip配置,检查配置并重启Nginx,验证Gzip压缩是否生效等,感兴趣的可以了解一下
    2024-10-10
  • Nginx配置https过程中出现的问题与解决

    Nginx配置https过程中出现的问题与解决

    这篇文章主要为大家详细介绍在Nginx配置https过程中容易出现的问题与解决方法,文中有详细的图文介绍,具有一定的参考价值,需要的朋友可以参考下
    2023-06-06
  • Nginx实现动静分离的示例代码

    Nginx实现动静分离的示例代码

    Nginx动静分离是旨在将静态页面与动态页面或静态内容接口与动态内容接口分开,本文主要介绍了Nginx实现动静分离的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Nginx服务器中浏览器本地缓存和虚拟机的相关设置

    Nginx服务器中浏览器本地缓存和虚拟机的相关设置

    这篇文章主要介绍了Nginx服务器中浏览器本地缓存和虚拟机的相关设置,是Nginx服务器搭建过程中的基本配置,需要的朋友可以参考下
    2015-08-08

最新评论