Skip to content

Commit 83ff3e8

Browse files
rainingmasterjinhua.tan
authored and
jinhua.tan
committed
feature: allow use of ngx.exit() in the context of body_filter_by_lua
1 parent f6ff289 commit 83ff3e8

6 files changed

+86
-25
lines changed

README.markdown

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5460,7 +5460,7 @@ ngx.exit
54605460

54615461
**syntax:** *ngx.exit(status)*
54625462

5463-
**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**
5463+
**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**
54645464

54655465
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.
54665466

@@ -5505,7 +5505,7 @@ Note that while this method accepts all [HTTP status constants](#http-status-con
55055505

55065506
Also note that this method call terminates the processing of the current request and that it is recommended that a coding style that combines this method call with the `return` statement, i.e., `return ngx.exit(...)` be used to reinforce the fact that the request processing is being terminated.
55075507

5508-
When being used in the contexts of [header_filter_by_lua*](#header_filter_by_lua), [balancer_by_lua*](#balancer_by_lua_block), and
5508+
When being used in the contexts of [header_filter_by_lua*](#header_filter_by_lua), [body_filter_by_lua*](#body_filter_by_lua_block), [balancer_by_lua*](#balancer_by_lua_block), and
55095509
[ssl_session_store_by_lua*](#ssl_session_store_by_lua_block), `ngx.exit()` is
55105510
an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use `return` in combination as suggested above.
55115511

doc/HttpLuaModule.wiki

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,7 +4579,7 @@ Since <code>v0.8.3</code> this function returns <code>1</code> on success, or re
45794579
45804580
'''syntax:''' ''ngx.exit(status)''
45814581
4582-
'''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*''
4582+
'''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*''
45834583
45844584
When <code>status >= 200</code> (i.e., <code>ngx.HTTP_OK</code> and above), it will interrupt the execution of the current request and return status code to Nginx.
45854585
@@ -4621,7 +4621,7 @@ Note that while this method accepts all [[#HTTP status constants|HTTP status con
46214621
46224622
Also note that this method call terminates the processing of the current request and that it is recommended that a coding style that combines this method call with the <code>return</code> statement, i.e., <code>return ngx.exit(...)</code> be used to reinforce the fact that the request processing is being terminated.
46234623
4624-
When being used in the contexts of [[#header_filter_by_lua|header_filter_by_lua*]], [[#balancer_by_lua_block|balancer_by_lua*]], and
4624+
When being used in the contexts of [[#header_filter_by_lua|header_filter_by_lua*]], [[#body_filter_by_lua_block|body_filter_by_lua*]], [[#balancer_by_lua_block|balancer_by_lua*]], and
46254625
[[#ssl_session_store_by_lua_block|ssl_session_store_by_lua*]], <code>ngx.exit()</code> is
46264626
an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use <code>return</code> in combination as suggested above.
46274627

src/ngx_http_lua_bodyfilterby.c

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,15 @@ ngx_int_t
8282
ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
8383
ngx_chain_t *in)
8484
{
85-
ngx_int_t rc;
86-
u_char *err_msg;
87-
size_t len;
85+
ngx_int_t rc;
86+
u_char *err_msg;
87+
size_t len;
8888
#if (NGX_PCRE)
89-
ngx_pool_t *old_pool;
89+
ngx_pool_t *old_pool;
9090
#endif
91+
ngx_http_lua_ctx_t *ctx;
92+
93+
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
9194

9295
dd("initialize nginx context in Lua VM, code chunk at stack top sp = 1");
9396
ngx_http_lua_body_filter_by_lua_env(L, r, in);
@@ -110,6 +113,8 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
110113
ngx_http_lua_pcre_malloc_done(old_pool);
111114
#endif
112115

116+
dd("rc == %d", (int) rc);
117+
113118
if (rc != 0) {
114119

115120
/* error occurred */
@@ -136,7 +141,10 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r,
136141

137142
lua_settop(L, 0);
138143

139-
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
144+
if (ctx->body_filter_aborted
145+
|| rc == NGX_ERROR
146+
|| rc >= NGX_HTTP_SPECIAL_RESPONSE)
147+
{
140148
return NGX_ERROR;
141149
}
142150

@@ -166,15 +174,9 @@ ngx_http_lua_body_filter_inline(ngx_http_request_t *r, ngx_chain_t *in)
166174
return NGX_ERROR;
167175
}
168176

169-
rc = ngx_http_lua_body_filter_by_chunk(L, r, in);
170-
171-
dd("body filter by chunk returns %d", (int) rc);
172-
173-
if (rc != NGX_OK) {
174-
return NGX_ERROR;
175-
}
177+
dd("calling body filter by chunk");
176178

177-
return NGX_OK;
179+
return ngx_http_lua_body_filter_by_chunk(L, r, in);
178180
}
179181

180182

@@ -216,13 +218,7 @@ ngx_http_lua_body_filter_file(ngx_http_request_t *r, ngx_chain_t *in)
216218
/* make sure we have a valid code chunk */
217219
ngx_http_lua_assert(lua_isfunction(L, -1));
218220

219-
rc = ngx_http_lua_body_filter_by_chunk(L, r, in);
220-
221-
if (rc != NGX_OK) {
222-
return NGX_ERROR;
223-
}
224-
225-
return NGX_OK;
221+
return ngx_http_lua_body_filter_by_chunk(L, r, in);
226222
}
227223

228224

@@ -262,6 +258,12 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
262258
}
263259
}
264260

261+
if (ctx->body_filter_aborted) {
262+
/* maybe there is a bug in the output body filter caller, other
263+
* outputs will be intercepted here */
264+
return NGX_ERROR;
265+
}
266+
265267
if (ctx->seen_last_in_filter) {
266268
for (/* void */; in; in = in->next) {
267269
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
@@ -559,6 +559,8 @@ typedef struct ngx_http_lua_ctx_s {
559559

560560
unsigned exited:1;
561561

562+
unsigned body_filter_aborted:1;
563+
562564
unsigned eof:1; /* 1: last_buf has been sent;
563565
0: last_buf not sent yet */
564566

src/ngx_http_lua_control.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
365365
| NGX_HTTP_LUA_CONTEXT_CONTENT
366366
| NGX_HTTP_LUA_CONTEXT_TIMER
367367
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
368+
| NGX_HTTP_LUA_CONTEXT_BODY_FILTER
368369
| NGX_HTTP_LUA_CONTEXT_BALANCER
369370
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
370371
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
@@ -375,6 +376,19 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
375376
return NGX_ERROR;
376377
}
377378

379+
if (ctx->context & NGX_HTTP_LUA_CONTEXT_BODY_FILTER) {
380+
381+
if (status != NGX_ERROR && status != NGX_HTTP_CLOSE) {
382+
*errlen = ngx_snprintf(err, *errlen, "attempt to exit with the "
383+
"code not 444 or ngx.ERROR")
384+
- err;
385+
return NGX_ERROR;
386+
}
387+
388+
ctx->body_filter_aborted = 1;
389+
return NGX_DONE;
390+
}
391+
378392
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
379393
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
380394
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH))

t/082-body-filter.t

Lines changed: 44 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();
@@ -838,3 +838,46 @@ GET /lua
838838
--- ignore_response
839839
--- error_log
840840
API disabled in the context of body_filter_by_lua*
841+
842+
843+
844+
=== TEST 27: exit 444
845+
--- config
846+
location = /t {
847+
content_by_lua_block {
848+
ngx.say("111")
849+
ngx.say("222")
850+
ngx.say("333")
851+
}
852+
853+
body_filter_by_lua_block {
854+
ngx.exit(444)
855+
}
856+
}
857+
--- request
858+
GET /t
859+
--- ignore_response
860+
--- no_error_log
861+
[error]
862+
[alert]
863+
864+
865+
866+
=== TEST 28: exit OK
867+
--- config
868+
location = /t {
869+
content_by_lua_block {
870+
ngx.say("111")
871+
ngx.say("222")
872+
ngx.say("333")
873+
}
874+
875+
body_filter_by_lua_block {
876+
ngx.exit(200)
877+
}
878+
}
879+
--- request
880+
GET /t
881+
--- ignore_response
882+
--- error_log
883+
attempt to exit with the code not 444 or ngx.ERROR

0 commit comments

Comments
 (0)