Skip to content

Commit c623044

Browse files
authored
feat: support gzip (#16)
1 parent 5a2fd9c commit c623044

File tree

5 files changed

+309
-0
lines changed

5 files changed

+309
-0
lines changed

lib/resty/apisix/response.lua

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
local ffi = require("ffi")
2+
local base = require("resty.core.base")
3+
local get_request = base.get_request
4+
local C = ffi.C
5+
local NGX_ERROR = ngx.ERROR
6+
7+
8+
base.allows_subsystem("http")
9+
10+
11+
ffi.cdef[[
12+
typedef intptr_t ngx_int_t;
13+
ngx_int_t
14+
ngx_http_apisix_set_gzip(ngx_http_request_t *r, ngx_int_t num, size_t size,
15+
ngx_int_t level);
16+
]]
17+
18+
19+
local _M = {}
20+
21+
22+
-- opts contains
23+
-- * buffer_num
24+
-- * buffer_size
25+
-- * compress_level
26+
function _M.set_gzip(opts)
27+
local r = get_request()
28+
local rc = C.ngx_http_apisix_set_gzip(r, opts.buffer_num, opts.buffer_size, opts.compress_level)
29+
if rc == NGX_ERROR then
30+
return nil, "no memory"
31+
end
32+
return true
33+
end
34+
35+
36+
return _M

patch/1.19.3/nginx-gzip.patch

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
diff --git src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_gzip_filter_module.c
2+
index c75169c..35b8433 100644
3+
--- src/http/modules/ngx_http_gzip_filter_module.c
4+
+++ src/http/modules/ngx_http_gzip_filter_module.c
5+
@@ -8,6 +8,9 @@
6+
#include <ngx_config.h>
7+
#include <ngx_core.h>
8+
#include <ngx_http.h>
9+
+#if (NGX_HTTP_APISIX)
10+
+#include <ngx_http_apisix_module.h>
11+
+#endif
12+
13+
#include <zlib.h>
14+
15+
@@ -225,6 +228,26 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
16+
17+
conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
18+
19+
+#if (NGX_HTTP_APISIX)
20+
+ if ((r->headers_out.status != NGX_HTTP_OK
21+
+ && r->headers_out.status != NGX_HTTP_FORBIDDEN
22+
+ && r->headers_out.status != NGX_HTTP_NOT_FOUND)
23+
+ || (r->headers_out.content_encoding
24+
+ && r->headers_out.content_encoding->value.len)
25+
+ || r->header_only)
26+
+ {
27+
+ return ngx_http_next_header_filter(r);
28+
+ }
29+
+
30+
+ if (!ngx_http_apisix_is_gzip_set(r)
31+
+ && (!conf->enable
32+
+ || (r->headers_out.content_length_n != -1
33+
+ && r->headers_out.content_length_n < conf->min_length)
34+
+ || ngx_http_test_content_type(r, &conf->types) == NULL))
35+
+ {
36+
+ return ngx_http_next_header_filter(r);
37+
+ }
38+
+#else
39+
if (!conf->enable
40+
|| (r->headers_out.status != NGX_HTTP_OK
41+
&& r->headers_out.status != NGX_HTTP_FORBIDDEN
42+
@@ -238,6 +261,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
43+
{
44+
return ngx_http_next_header_filter(r);
45+
}
46+
+#endif
47+
48+
r->gzip_vary = 1;
49+
50+
@@ -515,7 +539,18 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
51+
* 16-byte padding in one out of the two window-sized buffers.
52+
*/
53+
54+
+#if (NGX_HTTP_APISIX)
55+
+ ngx_int_t level;
56+
+
57+
+ level = ngx_http_apisix_get_gzip_compress_level(r);
58+
+ if (level == NGX_DECLINED) {
59+
+ level = conf->level;
60+
+ }
61+
+
62+
+ if (level == 1) {
63+
+#else
64+
if (conf->level == 1) {
65+
+#endif
66+
wbits = ngx_max(wbits, 13);
67+
}
68+
69+
@@ -615,6 +650,21 @@ ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
70+
ctx->zstream.zfree = ngx_http_gzip_filter_free;
71+
ctx->zstream.opaque = ctx;
72+
73+
+#if (NGX_HTTP_APISIX)
74+
+ ngx_int_t level;
75+
+
76+
+ level = ngx_http_apisix_get_gzip_compress_level(r);
77+
+ if (level == NGX_DECLINED) {
78+
+ level = conf->level;
79+
+ }
80+
+
81+
+ rc = deflateInit2(&ctx->zstream, (int) level, Z_DEFLATED,
82+
+ ctx->wbits + 16, ctx->memlevel, Z_DEFAULT_STRATEGY);
83+
+#else
84+
+ rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED,
85+
+ ctx->wbits + 16, ctx->memlevel, Z_DEFAULT_STRATEGY);
86+
+#endif
87+
+
88+
rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED,
89+
ctx->wbits + 16, ctx->memlevel, Z_DEFAULT_STRATEGY);
90+
91+
@@ -705,6 +755,16 @@ ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
92+
93+
conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
94+
95+
+#if (NGX_HTTP_APISIX)
96+
+ ngx_int_t num;
97+
+ size_t size;
98+
+
99+
+ if (ngx_http_apisix_get_gzip_buffer_conf(r, &num, &size) == NGX_DECLINED) {
100+
+ num = conf->bufs.num;
101+
+ size = conf->bufs.size;
102+
+ }
103+
+#endif
104+
+
105+
if (ctx->free) {
106+
107+
cl = ctx->free;
108+
@@ -713,9 +773,15 @@ ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
109+
110+
ngx_free_chain(r->pool, cl);
111+
112+
+#if (NGX_HTTP_APISIX)
113+
+ } else if (ctx->bufs < num) {
114+
+
115+
+ ctx->out_buf = ngx_create_temp_buf(r->pool, size);
116+
+#else
117+
} else if (ctx->bufs < conf->bufs.num) {
118+
119+
ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
120+
+#endif
121+
if (ctx->out_buf == NULL) {
122+
return NGX_ERROR;
123+
}
124+
diff --git src/http/ngx_http_core_module.c src/http/ngx_http_core_module.c
125+
index b900467..160e512 100644
126+
--- src/http/ngx_http_core_module.c
127+
+++ src/http/ngx_http_core_module.c
128+
@@ -2065,9 +2065,16 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
129+
return NGX_DECLINED;
130+
}
131+
132+
+#if (NGX_HTTP_APISIX)
133+
+ if (!ngx_http_apisix_is_gzip_set(r)
134+
+ && r->http_version < clcf->gzip_http_version) {
135+
+ return NGX_DECLINED;
136+
+ }
137+
+#else
138+
if (r->http_version < clcf->gzip_http_version) {
139+
return NGX_DECLINED;
140+
}
141+
+#endif
142+
143+
if (r->headers_in.via == NULL) {
144+
goto ok;

src/ngx_http_apisix_module.c

+80
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,83 @@ ngx_http_apisix_client_max_body_size(ngx_http_request_t *r)
329329

330330
return clcf->client_max_body_size;
331331
}
332+
333+
334+
ngx_int_t
335+
ngx_http_apisix_is_gzip_set(ngx_http_request_t *r)
336+
{
337+
ngx_http_apisix_ctx_t *ctx;
338+
339+
ctx = ngx_http_apisix_get_module_ctx(r->main);
340+
if (ctx == NULL || ctx->gzip == NULL) {
341+
return 0;
342+
}
343+
344+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "apisix gzip set");
345+
346+
return 1;
347+
}
348+
349+
350+
ngx_int_t
351+
ngx_http_apisix_get_gzip_buffer_conf(ngx_http_request_t *r, ngx_int_t *num,
352+
size_t *size)
353+
{
354+
ngx_http_apisix_ctx_t *ctx;
355+
356+
ctx = ngx_http_apisix_get_module_ctx(r->main);
357+
if (ctx == NULL || ctx->gzip == NULL) {
358+
return NGX_DECLINED;
359+
}
360+
361+
*num = ctx->gzip->buffer_num;
362+
*size = ctx->gzip->buffer_size;
363+
364+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
365+
"apisix gzip num:%i size:%z", *num, *size);
366+
367+
return NGX_OK;
368+
}
369+
370+
371+
ngx_int_t
372+
ngx_http_apisix_get_gzip_compress_level(ngx_http_request_t *r)
373+
{
374+
ngx_http_apisix_ctx_t *ctx;
375+
376+
ctx = ngx_http_apisix_get_module_ctx(r->main);
377+
if (ctx == NULL || ctx->gzip == NULL) {
378+
return NGX_DECLINED;
379+
}
380+
381+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
382+
"apisix gzip level:%i", ctx->gzip->level);
383+
384+
return ctx->gzip->level;
385+
}
386+
387+
388+
ngx_int_t
389+
ngx_http_apisix_set_gzip(ngx_http_request_t *r, ngx_int_t num, size_t size,
390+
ngx_int_t level)
391+
{
392+
ngx_http_apisix_ctx_t *ctx;
393+
ngx_http_apisix_gzip_t *gzip;
394+
395+
ctx = ngx_http_apisix_get_module_ctx(r->main);
396+
if (ctx == NULL) {
397+
return NGX_ERROR;
398+
}
399+
400+
gzip = ngx_palloc(r->pool, sizeof(ngx_http_apisix_gzip_t));
401+
if (gzip == NULL) {
402+
return NGX_ERROR;
403+
}
404+
405+
gzip->level = level;
406+
gzip->buffer_num = num;
407+
gzip->buffer_size = size;
408+
409+
ctx->gzip = gzip;
410+
return NGX_OK;
411+
}

src/ngx_http_apisix_module.h

+14
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,21 @@ typedef struct {
1010
} ngx_http_apisix_loc_conf_t;
1111

1212

13+
typedef struct {
14+
ngx_int_t buffer_num;
15+
size_t buffer_size;
16+
ngx_int_t level;
17+
} ngx_http_apisix_gzip_t;
18+
19+
1320
typedef struct {
1421
STACK_OF(X509) *upstream_cert;
1522
EVP_PKEY *upstream_pkey;
1623

1724
off_t client_max_body_size;
1825

26+
ngx_http_apisix_gzip_t *gzip;
27+
1928
unsigned client_max_body_size_set:1;
2029
} ngx_http_apisix_ctx_t;
2130

@@ -25,5 +34,10 @@ void ngx_http_apisix_set_upstream_ssl(ngx_http_request_t *r, ngx_connection_t *c
2534
ngx_flag_t ngx_http_apisix_delay_client_max_body_check(ngx_http_request_t *r);
2635
off_t ngx_http_apisix_client_max_body_size(ngx_http_request_t *r);
2736

37+
ngx_int_t ngx_http_apisix_is_gzip_set(ngx_http_request_t *r);
38+
ngx_int_t ngx_http_apisix_get_gzip_buffer_conf(ngx_http_request_t *r,
39+
ngx_int_t *num, size_t *size);
40+
ngx_int_t ngx_http_apisix_get_gzip_compress_level(ngx_http_request_t *r);
41+
2842

2943
#endif /* _NGX_HTTP_APISIX_H_INCLUDED_ */

t/gzip.t

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use t::APISIX_NGINX 'no_plan';
2+
3+
run_tests();
4+
5+
__DATA__
6+
7+
=== TEST 1: set gzip
8+
--- config
9+
location /t {
10+
content_by_lua_block {
11+
ngx.say(("1024"):rep(1024))
12+
}
13+
header_filter_by_lua_block {
14+
local response = require "resty.apisix.response"
15+
local ok, err = response.set_gzip({
16+
buffer_num = 4,
17+
buffer_size = 8192,
18+
compress_level = 2,
19+
})
20+
if not ok then
21+
ngx.log(ngx.ERR, err)
22+
end
23+
}
24+
log_by_lua_block {
25+
ngx.log(ngx.WARN, "content-encoding: ", ngx.var.sent_http_content_encoding)
26+
}
27+
}
28+
--- more_headers
29+
Accept-Encoding: gzip
30+
--- error_log
31+
apisix gzip level:2
32+
apisix gzip num:4 size:8192
33+
content-encoding: gzip
34+
--- no_error_log
35+
[error]

0 commit comments

Comments
 (0)