nginx中g(shù)zip_types匹配content-type的方式
1.背景
我們系統(tǒng)中有一個(gè)功能,可以配置content-type類型來(lái)決定是否打開(kāi)gzip壓縮。
這個(gè)配置與nginx官方的gzip_type不同的地方在于,nginx官方的是寫(xiě)死在配置文件中的,所有請(qǐng)求都生效;我們自研的是,不同用戶的gzip_type可以不同。
最近發(fā)現(xiàn)一個(gè)問(wèn)題
content-type配置為:image/jpeg,但是后端響應(yīng)的Content-Type為"
image/jped;charset:UTF-8"時(shí),由于代碼中是將配置的content-type與響應(yīng)頭中字符串作精確比較,因此,上述場(chǎng)景,并不能正確打開(kāi)gzip功能。
nginx對(duì)此是如何處理的呢?
后端響應(yīng)的Content-Type保持為image/jped;charset:UTF-8。
1、配置gzip_type 如下,gzip生效:
gzip_type image/jpeg;
2、配置gzip_type如下,gzip不生效:(nginx官方文檔中也沒(méi)有提及下面的配置方法)
gzip_type "image/jpeg;charset:UTF-8";
2.nginx處理流程
在進(jìn)行header_filter時(shí),對(duì)content-Type做了校驗(yàn):
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中對(duì)content_type做了校驗(yàn)
|| 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頭域內(nèi)容轉(zhuǎn)換為了小寫(xiě),并使用了r->headers_out.content_type_len長(zhǎng)度的內(nèi)容,與配置的types進(jìn)行比較。
但是針對(duì)第1種情況,配置和實(shí)際響應(yīng)頭明明是不相等的啊,是這么匹配成功的?
使用gdb打斷點(diǎn),發(fā)現(xiàn)
- r->headers_out.content_type為:
- {len = 24, data = “image/jpeg;charset=UTF-8”}
- 但是,
- r->headers_out.content_type_len卻是10!這個(gè)與上面為什么不一致呢?
找到設(shè)置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;
// 此時(shí),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] == ';') {
// 找到第一個(gè)分號(hào),然后修改了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響應(yīng)頭中第一個(gè)分號(hào)前的內(nèi)容進(jìn)行匹配。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Nginx配置中root和alias的區(qū)別及說(shuō)明
這篇文章主要介紹了Nginx配置中root和alias的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Nginx反向代理如何到訪問(wèn)者機(jī)器上(后端調(diào)試)
這篇文章主要介紹了Nginx反向代理如何到訪問(wèn)者機(jī)器上(后端調(diào)試),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Nginx 解決504錯(cuò)誤超時(shí)問(wèn)題小結(jié)
本文主要介紹了ginx出現(xiàn)504 Gateway Timeout錯(cuò)誤的原因,通常是因?yàn)槌绦驁?zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致響應(yīng)超時(shí),下面就來(lái)介紹一下解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
Nginx 配置前端后端服務(wù)的實(shí)現(xiàn)步驟
本文主要介紹了Nginx 配置前端后端服務(wù)的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03
如何通過(guò)nginx負(fù)載均衡跳轉(zhuǎn)https
這篇文章主要介紹了如何通過(guò)nginx負(fù)載均衡跳轉(zhuǎn)https的相關(guān)資料,需要的朋友可以參考下2018-09-09
Nginx隱藏server頭信息的實(shí)現(xiàn)
本文主要介紹了Nginx隱藏server頭信息的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
nginx proxy_pass 路徑拼接的具體實(shí)現(xiàn)
本文主要介紹了nginx proxy_pass 路徑拼接的具體實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-05-05
ubuntu16.04下徹底卸載nginx的相關(guān)命令
nginx是一款自由的、開(kāi)源的、高性能的HTTP服務(wù)器和反向代理服務(wù)器;這篇文章主要介紹了ubuntu16.04下徹底卸載nginx的相關(guān)命令,需要的朋友可以參考下2018-12-12
Nginx代理導(dǎo)致請(qǐng)求頭某些內(nèi)容丟失的問(wèn)題解決
本文主要介紹了在使用NGINX代理時(shí)請(qǐng)求頭中的下劃線被自動(dòng)忽略的問(wèn)題,通過(guò)兩種方法解決了這個(gè)問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02

