diff --git a/lib/resty/apisix/response.lua b/lib/resty/apisix/response.lua index 8a1b15e..29ec858 100644 --- a/lib/resty/apisix/response.lua +++ b/lib/resty/apisix/response.lua @@ -13,6 +13,10 @@ typedef intptr_t ngx_int_t; ngx_int_t ngx_http_apisix_set_gzip(ngx_http_request_t *r, ngx_int_t num, size_t size, ngx_int_t level); +ngx_int_t +ngx_http_apisix_skip_header_filter_by_lua(ngx_http_request_t *r); +ngx_int_t +ngx_http_apisix_skip_body_filter_by_lua(ngx_http_request_t *r); ]] @@ -33,4 +37,26 @@ function _M.set_gzip(opts) end +-- The skip_* methods must be called before any output is generated, +-- so the flag can take effect +function _M.skip_header_filter_by_lua() + local r = get_request() + local rc = C.ngx_http_apisix_skip_header_filter_by_lua(r) + if rc == NGX_ERROR then + return nil, "no memory" + end + return true +end + + +function _M.skip_body_filter_by_lua() + local r = get_request() + local rc = C.ngx_http_apisix_skip_body_filter_by_lua(r) + if rc == NGX_ERROR then + return nil, "no memory" + end + return true +end + + return _M diff --git a/patch/1.21.4/ngx_lua-skip_filter.patch b/patch/1.21.4/ngx_lua-skip_filter.patch new file mode 100644 index 0000000..e65f72a --- /dev/null +++ b/patch/1.21.4/ngx_lua-skip_filter.patch @@ -0,0 +1,54 @@ +diff --git src/ngx_http_lua_bodyfilterby.c src/ngx_http_lua_bodyfilterby.c +index 9024889..88af761 100644 +--- src/ngx_http_lua_bodyfilterby.c ++++ src/ngx_http_lua_bodyfilterby.c +@@ -22,6 +22,9 @@ + #include "ngx_http_lua_misc.h" + #include "ngx_http_lua_consts.h" + #include "ngx_http_lua_output.h" ++#if (NGX_HTTP_APISIX) ++#include "ngx_http_apisix_module.h" ++#endif + + + static void ngx_http_lua_body_filter_by_lua_env(lua_State *L, +@@ -241,6 +244,12 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua body filter for user lua code, uri \"%V\"", &r->uri); + ++#if (NGX_HTTP_APISIX) ++ if (ngx_http_apisix_is_body_filter_by_lua_skipped(r)) { ++ return ngx_http_next_body_filter(r, in); ++ } ++#endif ++ + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + + if (llcf->body_filter_handler == NULL || r->header_only) { +diff --git src/ngx_http_lua_headerfilterby.c src/ngx_http_lua_headerfilterby.c +index ed0c3a6..5f04992 100644 +--- src/ngx_http_lua_headerfilterby.c ++++ src/ngx_http_lua_headerfilterby.c +@@ -19,6 +19,9 @@ + #include "ngx_http_lua_string.h" + #include "ngx_http_lua_misc.h" + #include "ngx_http_lua_consts.h" ++#if (NGX_HTTP_APISIX) ++#include "ngx_http_apisix_module.h" ++#endif + + + static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +@@ -80,6 +83,12 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r) + #endif + ngx_http_lua_ctx_t *ctx; + ++#if (NGX_HTTP_APISIX) ++ if (ngx_http_apisix_is_header_filter_by_lua_skipped(r)) { ++ return NGX_OK; ++ } ++#endif ++ + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx->exited) { + old_exit_code = ctx->exit_code; diff --git a/src/ngx_http_apisix_module.c b/src/ngx_http_apisix_module.c index ad8d39a..3802c60 100644 --- a/src/ngx_http_apisix_module.c +++ b/src/ngx_http_apisix_module.c @@ -574,3 +574,69 @@ ngx_http_apisix_mark_request_header_set(ngx_http_request_t *r) ctx->request_header_set = 1; } + + +ngx_int_t +ngx_http_apisix_skip_header_filter_by_lua(ngx_http_request_t *r) +{ + ngx_http_apisix_ctx_t *ctx; + + ctx = ngx_http_apisix_get_module_ctx(r); + if (ctx == NULL) { + return NGX_ERROR; + } + + ctx->header_filter_by_lua_skipped = 1; + return NGX_OK; +} + + +ngx_int_t +ngx_http_apisix_is_header_filter_by_lua_skipped(ngx_http_request_t *r) +{ + ngx_http_apisix_ctx_t *ctx; + + ctx = ngx_http_apisix_get_module_ctx(r); + if (ctx != NULL) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "apisix header_filter_by_lua %p skipped: %d", + ctx, ctx->header_filter_by_lua_skipped); + + return ctx->header_filter_by_lua_skipped; + } + + return 0; +} + + +ngx_int_t +ngx_http_apisix_skip_body_filter_by_lua(ngx_http_request_t *r) +{ + ngx_http_apisix_ctx_t *ctx; + + ctx = ngx_http_apisix_get_module_ctx(r); + if (ctx == NULL) { + return NGX_ERROR; + } + + ctx->body_filter_by_lua_skipped = 1; + return NGX_OK; +} + + +ngx_int_t +ngx_http_apisix_is_body_filter_by_lua_skipped(ngx_http_request_t *r) +{ + ngx_http_apisix_ctx_t *ctx; + + ctx = ngx_http_apisix_get_module_ctx(r); + if (ctx != NULL) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "apisix body_filter_by_lua %p skipped: %d", + ctx, ctx->body_filter_by_lua_skipped); + + return ctx->body_filter_by_lua_skipped; + } + + return 0; +} diff --git a/src/ngx_http_apisix_module.h b/src/ngx_http_apisix_module.h index eb33cb8..68bd25b 100644 --- a/src/ngx_http_apisix_module.h +++ b/src/ngx_http_apisix_module.h @@ -30,6 +30,8 @@ typedef struct { unsigned request_buffering:1; unsigned request_buffering_set:1; unsigned request_header_set:1; + unsigned header_filter_by_lua_skipped:1; + unsigned body_filter_by_lua_skipped:1; } ngx_http_apisix_ctx_t; @@ -50,4 +52,8 @@ ngx_int_t ngx_http_apisix_is_request_buffering(ngx_http_request_t *r, ngx_flag_t void ngx_http_apisix_mark_request_header_set(ngx_http_request_t *r); +ngx_int_t ngx_http_apisix_is_header_filter_by_lua_skipped(ngx_http_request_t *r); +ngx_int_t ngx_http_apisix_is_body_filter_by_lua_skipped(ngx_http_request_t *r); + + #endif /* _NGX_HTTP_APISIX_H_INCLUDED_ */ diff --git a/t/skip_filter.t b/t/skip_filter.t new file mode 100644 index 0000000..14d45df --- /dev/null +++ b/t/skip_filter.t @@ -0,0 +1,41 @@ +use t::APISIX_NGINX 'no_plan'; + +run_tests; + +__DATA__ + +=== TEST 1: skip header_filter_by_lua +--- config + location /t { + access_by_lua_block { + local resp = require("resty.apisix.response") + assert(resp.skip_header_filter_by_lua()) + + ngx.header["Test"] = "one" + ngx.say("ok") + } + header_filter_by_lua_block { + ngx.header["Test"] = "two" + } + } +--- response_headers +Test: one + + + +=== TEST 2: skip body_filter_by_lua +--- config + location /t { + access_by_lua_block { + local resp = require("resty.apisix.response") + assert(resp.skip_body_filter_by_lua()) + + ngx.say("ok") + } + body_filter_by_lua_block { + ngx.arg[1] = "no" + ngx.arg[2] = true + } + } +--- response_body +ok