Skip to content

Commit 3f8a592

Browse files
committed
feature: allow use of ngx.exit() in the context of header_filter_by_lua*. but in this context ngx.exit() returns immediately.
1 parent 9b76f74 commit 3f8a592

File tree

4 files changed

+141
-36
lines changed

4 files changed

+141
-36
lines changed

src/ngx_http_lua_control.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ ngx_http_lua_ngx_exit(lua_State *L)
303303
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
304304
| NGX_HTTP_LUA_CONTEXT_ACCESS
305305
| NGX_HTTP_LUA_CONTEXT_CONTENT
306-
| NGX_HTTP_LUA_CONTEXT_TIMER);
306+
| NGX_HTTP_LUA_CONTEXT_TIMER
307+
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER);
307308

308309
rc = (ngx_int_t) luaL_checkinteger(L, 1);
309310

@@ -331,12 +332,18 @@ ngx_http_lua_ngx_exit(lua_State *L)
331332
rc = NGX_HTTP_OK;
332333
}
333334

335+
dd("setting exit code: %d", (int) rc);
336+
334337
ctx->exit_code = rc;
335338
ctx->exited = 1;
336339

337340
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
338341
"lua exit with code %i", ctx->exit_code);
339342

343+
if (ctx->context & NGX_HTTP_LUA_CONTEXT_HEADER_FILTER) {
344+
return 0;
345+
}
346+
340347
dd("calling yield");
341348
return lua_yield(L, 0);
342349
}
@@ -415,7 +422,8 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
415422
if (ngx_http_lua_ffi_check_context(ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
416423
| NGX_HTTP_LUA_CONTEXT_ACCESS
417424
| NGX_HTTP_LUA_CONTEXT_CONTENT
418-
| NGX_HTTP_LUA_CONTEXT_TIMER,
425+
| NGX_HTTP_LUA_CONTEXT_TIMER
426+
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER,
419427
err, errlen)
420428
!= NGX_OK)
421429
{
@@ -456,6 +464,10 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
456464
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
457465
"lua exit with code %i", ctx->exit_code);
458466

467+
if (ctx->context & NGX_HTTP_LUA_CONTEXT_HEADER_FILTER) {
468+
return NGX_DONE;
469+
}
470+
459471
return NGX_OK;
460472
}
461473
#endif /* NGX_HTTP_LUA_NO_FFI_API */

src/ngx_http_lua_headerfilterby.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,19 @@ ngx_http_lua_header_filter_by_lua_env(lua_State *L, ngx_http_request_t *r)
8484
ngx_int_t
8585
ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r)
8686
{
87+
int old_exit_code = 0;
8788
ngx_int_t rc;
8889
u_char *err_msg;
8990
size_t len;
9091
#if (NGX_PCRE)
9192
ngx_pool_t *old_pool;
9293
#endif
94+
ngx_http_lua_ctx_t *ctx;
95+
96+
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
97+
if (ctx->exited) {
98+
old_exit_code = ctx->exit_code;
99+
}
93100

94101
/* initialize nginx context in Lua VM, code chunk at stack top sp = 1 */
95102
ngx_http_lua_header_filter_by_lua_env(L, r);
@@ -112,6 +119,8 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r)
112119
ngx_http_lua_pcre_malloc_done(old_pool);
113120
#endif
114121

122+
dd("rc == %d", (int) rc);
123+
115124
if (rc != 0) {
116125
/* error occured when running loaded code */
117126
err_msg = (u_char *) lua_tolstring(L, -1, &len);
@@ -129,6 +138,25 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r)
129138
return NGX_ERROR;
130139
}
131140

141+
dd("exited: %d, exit code: %d, old exit code: %d",
142+
(int) ctx->exited, (int) ctx->exit_code, (int) old_exit_code);
143+
144+
if (ctx->exited && ctx->exit_code != old_exit_code) {
145+
if (ctx->exit_code == NGX_ERROR) {
146+
return NGX_ERROR;
147+
}
148+
149+
dd("finalize request with %d", (int) ctx->exit_code);
150+
151+
rc = ngx_http_filter_finalize_request(r, &ngx_http_lua_module,
152+
ctx->exit_code);
153+
if (rc == NGX_ERROR || rc == NGX_AGAIN) {
154+
return rc;
155+
}
156+
157+
return NGX_DECLINED;
158+
}
159+
132160
/* clear Lua stack */
133161
lua_settop(L, 0);
134162

@@ -156,15 +184,9 @@ ngx_http_lua_header_filter_inline(ngx_http_request_t *r)
156184
return NGX_ERROR;
157185
}
158186

159-
rc = ngx_http_lua_header_filter_by_chunk(L, r);
160-
161-
dd("header filter by chunk returns %d", (int) rc);
187+
dd("calling header filter by chunk");
162188

163-
if (rc != NGX_OK) {
164-
return NGX_ERROR;
165-
}
166-
167-
return NGX_OK;
189+
return ngx_http_lua_header_filter_by_chunk(L, r);
168190
}
169191

170192

@@ -205,13 +227,7 @@ ngx_http_lua_header_filter_file(ngx_http_request_t *r)
205227
/* make sure we have a valid code chunk */
206228
assert(lua_isfunction(L, -1));
207229

208-
rc = ngx_http_lua_header_filter_by_chunk(L, r);
209-
210-
if (rc != NGX_OK) {
211-
return NGX_ERROR;
212-
}
213-
214-
return NGX_OK;
230+
return ngx_http_lua_header_filter_by_chunk(L, r);
215231
}
216232

217233

@@ -268,9 +284,12 @@ ngx_http_lua_header_filter(ngx_http_request_t *r)
268284

269285
ctx->context = old_context;
270286

271-
if (rc != NGX_OK) {
272-
dd("calling header filter handler rc %d", (int)rc);
273-
return NGX_ERROR;
287+
if (rc == NGX_DECLINED) {
288+
return NGX_OK;
289+
}
290+
291+
if (rc == NGX_AGAIN || rc == NGX_ERROR) {
292+
return rc;
274293
}
275294

276295
return ngx_http_next_header_filter(r);

t/005-exit.t

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repeat_each(2);
1111
#log_level('warn');
1212
#worker_connections(1024);
1313

14-
plan tests => repeat_each() * (blocks() * 3 + 1);
14+
plan tests => repeat_each() * (blocks() * 3 + 2);
1515

1616
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
1717
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
@@ -637,3 +637,91 @@ lua sending HTTP 1.0 response headers
637637
[error]
638638
[alert]
639639
640+
641+
642+
=== TEST 21: exit 403 in header filter
643+
--- config
644+
location = /t {
645+
content_by_lua "ngx.say('hi');";
646+
header_filter_by_lua '
647+
return ngx.exit(403)
648+
';
649+
}
650+
--- request
651+
GET /t
652+
--- error_code: 403
653+
--- response_body_like: 403 Forbidden
654+
--- no_error_log
655+
[error]
656+
657+
658+
659+
=== TEST 22: exit 201 in header filter
660+
--- config
661+
lingering_close always;
662+
location = /t {
663+
content_by_lua "ngx.say('hi');";
664+
header_filter_by_lua '
665+
return ngx.exit(201)
666+
';
667+
}
668+
--- request
669+
GET /t
670+
--- error_code: 201
671+
--- response_body
672+
--- no_error_log
673+
[error]
674+
675+
676+
677+
=== TEST 23: exit both in header filter and content handler
678+
--- config
679+
location = /t {
680+
content_by_lua "ngx.status = 201 ngx.say('hi') ngx.exit(201)";
681+
header_filter_by_lua '
682+
return ngx.exit(201)
683+
';
684+
}
685+
--- request
686+
GET /t
687+
--- error_code: 201
688+
--- stap2
689+
/*
690+
F(ngx_http_send_header) {
691+
printf("=== %d\n", $r->headers_out->status)
692+
print_ubacktrace()
693+
}
694+
*/
695+
F(ngx_http_lua_header_filter_inline) {
696+
printf("=== %d\n", $r->headers_out->status)
697+
print_ubacktrace()
698+
}
699+
F(ngx_http_lua_header_filter_by_chunk).return {
700+
if ($return == -1) {
701+
printf("====== header filter by chunk\n")
702+
print_ubacktrace()
703+
}
704+
}
705+
--- stap_out
706+
--- response_body
707+
--- no_error_log
708+
[error]
709+
[alert]
710+
711+
712+
713+
=== TEST 24: exit 444 in header filter
714+
--- config
715+
location = /t {
716+
content_by_lua "ngx.say('hello world');";
717+
header_filter_by_lua '
718+
return ngx.exit(444)
719+
';
720+
}
721+
--- request
722+
GET /t
723+
--- error_code: 444
724+
--- response_body
725+
--- no_error_log
726+
[error]
727+

t/041-header-filter.t

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ log_level('debug');
1111

1212
repeat_each(2);
1313

14-
plan tests => repeat_each() * 92;
14+
plan tests => repeat_each() * 91;
1515

1616
#no_diff();
1717
#no_long_string();
@@ -589,20 +589,6 @@ API disabled in the context of header_filter_by_lua*
589589

590590

591591

592-
=== TEST 30: no ngx.exit
593-
--- config
594-
location /lua {
595-
header_filter_by_lua 'ngx.exit(0)';
596-
echo ok;
597-
}
598-
--- request
599-
GET /lua
600-
--- ignore_response
601-
--- error_log
602-
API disabled in the context of header_filter_by_lua*
603-
604-
605-
606592
=== TEST 31: no ngx.redirect
607593
--- config
608594
location /lua {

0 commit comments

Comments
 (0)