nginx中g(shù)zip_types匹配content-type的方式
1.背景
我們系統(tǒng)中有一個功能,可以配置content-type類型來決定是否打開gzip壓縮。
這個配置與nginx官方的gzip_type不同的地方在于,nginx官方的是寫死在配置文件中的,所有請求都生效;我們自研的是,不同用戶的gzip_type可以不同。
最近發(fā)現(xiàn)一個問題
content-type配置為:image/jpeg,但是后端響應(yīng)的Content-Type為"
image/jped;charset:UTF-8"時,由于代碼中是將配置的content-type與響應(yīng)頭中字符串作精確比較,因此,上述場景,并不能正確打開gzip功能。
nginx對此是如何處理的呢?
后端響應(yīng)的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頭域內(nèi)容轉(zhuǎn)換為了小寫,并使用了r->headers_out.content_type_len長度的內(nèi)容,與配置的types進行比較。
但是針對第1種情況,配置和實際響應(yīng)頭明明是不相等的啊,是這么匹配成功的?
使用gdb打斷點,發(fā)現(xiàn)
- r->headers_out.content_type為:
- {len = 24, data = “image/jpeg;charset=UTF-8”}
- 但是,
- r->headers_out.content_type_len卻是10!這個與上面為什么不一致呢?
找到設(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; // 此時,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響應(yīng)頭中第一個分號前的內(nèi)容進行匹配。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
NGINX報錯413 Request Entity Too Large的問題解決
Nginx 413錯誤表示請求實體太大,本文主要介紹了NGINX報錯413 Request Entity Too Large的問題解決,具有一定的參考價值,感興趣的可以了解一下2024-08-08Nginx的流式響應(yīng)配置實現(xiàn)小結(jié)
nginx是一款自由的、開源的、高性能的HTTP服務(wù)器和反向代理服務(wù)器,本文主要介紹了Nginx的流式響應(yīng)配置實現(xiàn)小結(jié),具有一定的參考價值,感興趣的可以了解一下2024-04-04Nginx中實現(xiàn)請求的緩存數(shù)據(jù)過期通知
Nginx 作為高性能的反向代理服務(wù)器,緩存機制是其優(yōu)化性能的重要手段之一,本文主要介紹了Nginx中實現(xiàn)請求的緩存數(shù)據(jù)過期通知,感興趣的可以了解一下2024-09-09Nginx HTTP Status 400 – 錯誤的請求問題解決
本文主要介紹了在配置Nginx反向代理兩個Tomcat站點時遇到HTTPStatus400錯誤,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01Nginx 配置TCP代理轉(zhuǎn)發(fā)的實現(xiàn)
本文主要介紹了使用Nginx新版的stream方式,實現(xiàn)TCP/UDP代理轉(zhuǎn)發(fā),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10Nginx服務(wù)器中瀏覽器本地緩存和虛擬機的相關(guān)設(shè)置
這篇文章主要介紹了Nginx服務(wù)器中瀏覽器本地緩存和虛擬機的相關(guān)設(shè)置,是Nginx服務(wù)器搭建過程中的基本配置,需要的朋友可以參考下2015-08-08