Skip to content

Commit 060e767

Browse files
committed
feature: allow use of ngx.exit() in the context of body_filter_by_lua
1 parent 2fd7daa commit 060e767

File tree

5 files changed

+109
-17
lines changed

5 files changed

+109
-17
lines changed

README.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5223,7 +5223,7 @@ ngx.exit
52235223
--------
52245224
**syntax:** *ngx.exit(status)*
52255225

5226-
**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua**
5226+
**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua**
52275227

52285228
When `status >= 200` (i.e., `ngx.HTTP_OK` and above), it will interrupt the execution of the current request and return status code to nginx.
52295229

src/ngx_http_lua_bodyfilterby.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,15 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
8787
ngx_chain_t *in)
8888
{
8989
ngx_int_t rc;
90+
ngx_chain_t *cl;
9091
u_char *err_msg;
9192
size_t len;
9293
#if (NGX_PCRE)
9394
ngx_pool_t *old_pool;
9495
#endif
96+
ngx_http_lua_ctx_t *ctx;
97+
98+
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
9599

96100
dd("initialize nginx context in Lua VM, code chunk at stack top sp = 1");
97101
ngx_http_lua_body_filter_by_lua_env(L, r, in);
@@ -114,6 +118,8 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
114118
ngx_http_lua_pcre_malloc_done(old_pool);
115119
#endif
116120

121+
dd("rc == %d", (int) rc);
122+
117123
if (rc != 0) {
118124

119125
/* error occurred */
@@ -140,6 +146,19 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
140146

141147
lua_settop(L, 0);
142148

149+
if (ctx->body_exited) {
150+
/* send last content */
151+
for (cl = in; cl->next; cl = cl->next) {
152+
/* do nothing */
153+
}
154+
/* make ngx_http_write_filter_module happy */
155+
cl->buf->last_buf = 1;
156+
157+
ctx->eof = 1;
158+
159+
return NGX_OK;
160+
}
161+
143162
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
144163
return NGX_ERROR;
145164
}
@@ -169,15 +188,9 @@ ngx_http_lua_body_filter_inline(ngx_http_request_t *r, ngx_chain_t *in)
169188
return NGX_ERROR;
170189
}
171190

172-
rc = ngx_http_lua_body_filter_by_chunk(L, r, in);
191+
dd("calling body filter by chunk");
173192

174-
dd("body filter by chunk returns %d", (int) rc);
175-
176-
if (rc != NGX_OK) {
177-
return NGX_ERROR;
178-
}
179-
180-
return NGX_OK;
193+
return ngx_http_lua_body_filter_by_chunk(L, r, in);
181194
}
182195

183196

@@ -218,13 +231,7 @@ ngx_http_lua_body_filter_file(ngx_http_request_t *r, ngx_chain_t *in)
218231
/* make sure we have a valid code chunk */
219232
ngx_http_lua_assert(lua_isfunction(L, -1));
220233

221-
rc = ngx_http_lua_body_filter_by_chunk(L, r, in);
222-
223-
if (rc != NGX_OK) {
224-
return NGX_ERROR;
225-
}
226-
227-
return NGX_OK;
234+
return ngx_http_lua_body_filter_by_chunk(L, r, in);
228235
}
229236

230237

@@ -264,6 +271,10 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
264271
}
265272
}
266273

274+
if (ctx->body_exited) {
275+
return NGX_OK;
276+
}
277+
267278
if (ctx->seen_last_in_filter) {
268279
for (/* void */; in; in = in->next) {
269280
dd("mark the buf as consumed: %d", (int) ngx_buf_size(in->buf));

src/ngx_http_lua_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ typedef struct ngx_http_lua_ctx_s {
487487

488488
unsigned exited:1;
489489

490+
unsigned body_exited:1;
491+
490492
unsigned eof:1; /* 1: last_buf has been sent;
491493
0: last_buf not sent yet */
492494

src/ngx_http_lua_control.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,18 @@ ngx_http_lua_ngx_exit(lua_State *L)
319319
| NGX_HTTP_LUA_CONTEXT_CONTENT
320320
| NGX_HTTP_LUA_CONTEXT_TIMER
321321
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
322+
| NGX_HTTP_LUA_CONTEXT_BODY_FILTER
322323
| NGX_HTTP_LUA_CONTEXT_BALANCER
323324
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
324325
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
325326
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH);
326327

328+
/* rc is useless in bodyfilter phase */
329+
if (ctx->context & NGX_HTTP_LUA_CONTEXT_BODY_FILTER) {
330+
ctx->body_exited = 1;
331+
return 0;
332+
}
333+
327334
rc = (ngx_int_t) luaL_checkinteger(L, 1);
328335

329336
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
@@ -470,6 +477,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
470477
| NGX_HTTP_LUA_CONTEXT_CONTENT
471478
| NGX_HTTP_LUA_CONTEXT_TIMER
472479
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
480+
| NGX_HTTP_LUA_CONTEXT_BODY_FILTER
473481
| NGX_HTTP_LUA_CONTEXT_BALANCER
474482
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
475483
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
@@ -541,6 +549,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
541549
"lua exit with code %i", ctx->exit_code);
542550

543551
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
552+
| NGX_HTTP_LUA_CONTEXT_BODY_FILTER
544553
| NGX_HTTP_LUA_CONTEXT_BALANCER))
545554
{
546555
return NGX_DONE;

t/082-body-filter.t

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ log_level('debug');
1010

1111
repeat_each(2);
1212

13-
plan tests => repeat_each() * (blocks() * 3 + 11);
13+
plan tests => repeat_each() * (blocks() * 3 + 8);
1414

1515
#no_diff();
1616
no_long_string();
@@ -837,3 +837,73 @@ GET /lua
837837
--- ignore_response
838838
--- error_log
839839
API disabled in the context of body_filter_by_lua*
840+
841+
842+
843+
=== TEST 27: exit 444
844+
--- config
845+
location = /t {
846+
content_by_lua_block {
847+
ngx.say("111")
848+
ngx.say("222")
849+
ngx.say("333")
850+
}
851+
852+
body_filter_by_lua_block {
853+
ngx.exit(444)
854+
}
855+
}
856+
--- request
857+
GET /t
858+
--- response_body
859+
111
860+
--- error_code: 200
861+
--- no_error_log
862+
863+
864+
865+
=== TEST 28: exit OK
866+
--- config
867+
location = /t {
868+
content_by_lua_block {
869+
ngx.say("111")
870+
ngx.say("222")
871+
ngx.say("333")
872+
}
873+
874+
body_filter_by_lua_block {
875+
ngx.exit(200)
876+
}
877+
}
878+
--- request
879+
GET /t
880+
--- response_body
881+
111
882+
--- error_code: 200
883+
--- no_error_log
884+
885+
886+
887+
=== TEST 29: in 2nd times
888+
--- config
889+
location = /t {
890+
content_by_lua_block {
891+
ngx.say("111")
892+
ngx.say("222")
893+
ngx.say("333")
894+
}
895+
896+
body_filter_by_lua_block {
897+
ngx.ctx.times = (ngx.ctx.times or 0) + 1
898+
if ngx.ctx.times == 2 then
899+
ngx.exit(444)
900+
end
901+
}
902+
}
903+
--- request
904+
GET /t
905+
--- response_body
906+
111
907+
222
908+
--- error_code: 200
909+
--- no_error_log

0 commit comments

Comments
 (0)