Skip to content

Commit c8694c1

Browse files
committed
feature: add access_by_lua* directives
2 parents 889cb58 + 0e2e7b3 commit c8694c1

21 files changed

Lines changed: 956 additions & 23 deletions

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ behavior.
141141
* [init_worker_by_lua_file](https://github.com/openresty/lua-nginx-module#init_worker_by_lua_file)
142142
* [preread_by_lua_block](#preread_by_lua_block)
143143
* [preread_by_lua_file](#preread_by_lua_file)
144+
* [access_by_lua_block](https://github.com/openresty/lua-nginx-module#access_by_lua_block)
145+
* [access_by_lua_file](https://github.com/openresty/lua-nginx-module#access_by_lua_file)
144146
* [content_by_lua_block](https://github.com/openresty/lua-nginx-module#content_by_lua_block)
145147
* [content_by_lua_file](https://github.com/openresty/lua-nginx-module#content_by_lua_file)
146148
* [balancer_by_lua_block](https://github.com/openresty/lua-nginx-module#balancer_by_lua_block)
@@ -178,6 +180,7 @@ behavior.
178180
* [lua_add_variable](#lua_add_variable)
179181
* [lua_capture_error_log](https://github.com/openresty/lua-nginx-module#lua_capture_error_log)
180182
* [preread_by_lua_no_postpone](#preread_by_lua_no_postpone)
183+
* [access_by_lua_no_postpone](#access_by_lua_no_postpone)
181184

182185
The [send_timeout](https://nginx.org/r/send_timeout) directive in the Nginx
183186
"http" subsystem is missing in the "stream" subsystem. As such,
@@ -308,6 +311,19 @@ This directive was first introduced in the `v0.0.4` release.
308311

309312
[Back to TOC](#directives)
310313

314+
access_by_lua_no_postpone
315+
--------------------------
316+
317+
**syntax:** *access_by_lua_no_postpone on|off*
318+
319+
**context:** *stream*
320+
321+
Controls whether or not to disable postponing [access\_by\_lua*](#access_by_lua_block) directives
322+
to run at the end of the `access` processing phase. By default, this directive is turned off
323+
and the Lua code is postponed to run at the end of the `access` phase.
324+
325+
[Back to TOC](#directives)
326+
311327
Nginx API for Lua
312328
-----------------
313329

@@ -537,7 +553,6 @@ output to be completely flushed out (to the system socket send buffers).
537553
TODO
538554
====
539555

540-
* Add new directives `access_by_lua_block` and `access_by_lua_file`.
541556
* Add `lua_postpone_output` to emulate the [postpone_output](https://nginx.org/r/postpone_output) directive.
542557

543558
[Back to TOC](#table-of-contents)

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ STREAM_LUA_SRCS=" \
282282
$ngx_addon_dir/src/ngx_stream_lua_proxy_ssl_verifyby.c \
283283
$ngx_addon_dir/src/ngx_stream_lua_log_ringbuf.c \
284284
$ngx_addon_dir/src/ngx_stream_lua_input_filters.c \
285+
$ngx_addon_dir/src/ngx_stream_lua_accessby.c \
285286
"
286287

287288
STREAM_LUA_DEPS=" \
@@ -328,6 +329,7 @@ STREAM_LUA_DEPS=" \
328329
$ngx_addon_dir/src/ngx_stream_lua_proxy_ssl_verifyby.h \
329330
$ngx_addon_dir/src/ngx_stream_lua_log_ringbuf.h \
330331
$ngx_addon_dir/src/ngx_stream_lua_input_filters.h \
332+
$ngx_addon_dir/src/ngx_stream_lua_accessby.h \
331333
"
332334

333335
# ----------------------------------------

src/ngx_stream_lua_accessby.c

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
2+
/*
3+
* Copyright (C) Hanada <im@hanada.info>
4+
* Copyright (C) Arcadiy Ivanov (arcivanov)
5+
* Copyright (C) OpenResty Inc.
6+
*/
7+
8+
9+
#ifndef DDEBUG
10+
#define DDEBUG 0
11+
#endif
12+
#include "ddebug.h"
13+
14+
15+
#include <nginx.h>
16+
#include "ngx_stream_lua_accessby.h"
17+
#include "ngx_stream_lua_util.h"
18+
#include "ngx_stream_lua_exception.h"
19+
#include "ngx_stream_lua_cache.h"
20+
21+
22+
static ngx_int_t ngx_stream_lua_access_by_chunk(lua_State *L,
23+
ngx_stream_lua_request_t *r);
24+
25+
26+
ngx_int_t
27+
ngx_stream_lua_access_handler(ngx_stream_session_t *s)
28+
{
29+
ngx_int_t rc;
30+
ngx_stream_lua_ctx_t *ctx;
31+
ngx_stream_lua_srv_conf_t *lscf;
32+
ngx_stream_lua_main_conf_t *lmcf;
33+
ngx_stream_lua_request_t *r;
34+
35+
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
36+
"lua access handler");
37+
38+
lmcf = ngx_stream_get_module_main_conf(s, ngx_stream_lua_module);
39+
40+
if (!lmcf->postponed_to_access_phase_end) {
41+
ngx_stream_core_main_conf_t *cmcf;
42+
ngx_stream_phase_handler_t tmp;
43+
ngx_stream_phase_handler_t *ph;
44+
ngx_stream_phase_handler_t *cur_ph;
45+
ngx_stream_phase_handler_t *last_ph;
46+
47+
lmcf->postponed_to_access_phase_end = 1;
48+
49+
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
50+
51+
ph = cmcf->phase_engine.handlers;
52+
cur_ph = &ph[s->phase_handler];
53+
last_ph = &ph[cur_ph->next - 1];
54+
55+
if (cur_ph < last_ph) {
56+
tmp = *cur_ph;
57+
58+
ngx_memmove(cur_ph, cur_ph + 1, (last_ph - cur_ph)
59+
* sizeof (ngx_stream_phase_handler_t));
60+
61+
*last_ph = tmp;
62+
63+
s->phase_handler--; /* redo the current ph */
64+
65+
return NGX_DECLINED;
66+
}
67+
}
68+
69+
lscf = ngx_stream_get_module_srv_conf(s, ngx_stream_lua_module);
70+
71+
if (lscf->access_handler == NULL) {
72+
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
73+
"no acces handler found");
74+
return NGX_DECLINED;
75+
}
76+
77+
ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module);
78+
79+
dd("ctx = %p", ctx);
80+
81+
if (ctx == NULL) {
82+
ctx = ngx_stream_lua_create_ctx(s);
83+
if (ctx == NULL) {
84+
return NGX_STREAM_INTERNAL_SERVER_ERROR;
85+
}
86+
}
87+
88+
r = ctx->request;
89+
90+
dd("entered? %d", (int) ctx->entered_access_phase);
91+
92+
if (ctx->entered_access_phase) {
93+
dd("calling wev handler");
94+
rc = ctx->resume_handler(r);
95+
dd("wev handler returns %d", (int) rc);
96+
97+
if (rc == NGX_ERROR || rc > NGX_OK) {
98+
ngx_stream_lua_finalize_request(ctx->request, rc);
99+
return NGX_DONE;
100+
}
101+
102+
if (rc == NGX_OK || rc == NGX_DONE) {
103+
return rc;
104+
}
105+
106+
return NGX_DECLINED;
107+
}
108+
109+
r->connection->read->handler = ngx_stream_lua_request_handler;
110+
r->connection->write->handler = ngx_stream_lua_request_handler;
111+
112+
dd("calling access handler");
113+
rc = lscf->access_handler(r);
114+
115+
if (rc == NGX_ERROR || rc > NGX_OK) {
116+
ngx_stream_lua_finalize_request(ctx->request, rc);
117+
return NGX_DONE;
118+
}
119+
120+
return rc;
121+
}
122+
123+
124+
ngx_int_t
125+
ngx_stream_lua_access_handler_inline(ngx_stream_lua_request_t *r)
126+
{
127+
ngx_int_t rc;
128+
lua_State *L;
129+
ngx_stream_lua_srv_conf_t *lscf;
130+
131+
lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);
132+
133+
L = ngx_stream_lua_get_lua_vm(r, NULL);
134+
135+
/* load Lua inline script (w/ cache) sp = 1 */
136+
rc = ngx_stream_lua_cache_loadbuffer(r->connection->log, L,
137+
lscf->access_src.value.data,
138+
lscf->access_src.value.len,
139+
lscf->access_src_key,
140+
(const char *) lscf->access_chunkname);
141+
142+
if (rc != NGX_OK) {
143+
return NGX_STREAM_INTERNAL_SERVER_ERROR;
144+
}
145+
146+
return ngx_stream_lua_access_by_chunk(L, r);
147+
}
148+
149+
150+
ngx_int_t
151+
ngx_stream_lua_access_handler_file(ngx_stream_lua_request_t *r)
152+
{
153+
u_char *script_path;
154+
ngx_int_t rc;
155+
ngx_str_t eval_src;
156+
lua_State *L;
157+
ngx_stream_lua_srv_conf_t *lscf;
158+
159+
lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);
160+
161+
/* Eval nginx variables in code path string first */
162+
if (ngx_stream_complex_value(r->session, &lscf->access_src, &eval_src)
163+
!= NGX_OK)
164+
{
165+
return NGX_ERROR;
166+
}
167+
168+
script_path = ngx_stream_lua_rebase_path(r->pool, eval_src.data,
169+
eval_src.len);
170+
171+
if (script_path == NULL) {
172+
return NGX_ERROR;
173+
}
174+
175+
L = ngx_stream_lua_get_lua_vm(r, NULL);
176+
177+
/* load Lua script file (w/ cache) sp = 1 */
178+
rc = ngx_stream_lua_cache_loadfile(r->connection->log, L, script_path,
179+
lscf->access_src_key);
180+
if (rc != NGX_OK) {
181+
return rc;
182+
}
183+
184+
/* make sure we have a valid code chunk */
185+
ngx_stream_lua_assert(lua_isfunction(L, -1));
186+
187+
return ngx_stream_lua_access_by_chunk(L, r);
188+
}
189+
190+
191+
static ngx_int_t
192+
ngx_stream_lua_access_by_chunk(lua_State *L, ngx_stream_lua_request_t *r)
193+
{
194+
int co_ref;
195+
ngx_int_t rc;
196+
lua_State *co;
197+
ngx_event_t *rev;
198+
ngx_connection_t *c;
199+
ngx_stream_lua_ctx_t *ctx;
200+
ngx_stream_lua_cleanup_t *cln;
201+
202+
ngx_stream_lua_srv_conf_t *lscf;
203+
204+
/* {{{ new coroutine to handle request */
205+
co = ngx_stream_lua_new_thread(r, L, &co_ref);
206+
207+
if (co == NULL) {
208+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
209+
"lua: failed to create new coroutine "
210+
"to handle request");
211+
212+
return NGX_STREAM_INTERNAL_SERVER_ERROR;
213+
}
214+
215+
/* move code closure to new coroutine */
216+
lua_xmove(L, co, 1);
217+
218+
#ifndef OPENRESTY_LUAJIT
219+
/* set closure's env table to new coroutine's globals table */
220+
ngx_stream_lua_get_globals_table(co);
221+
lua_setfenv(co, -2);
222+
#endif
223+
224+
/* save nginx request in coroutine globals table */
225+
ngx_stream_lua_set_req(co, r);
226+
227+
/* {{{ initialize request context */
228+
ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_lua_module);
229+
230+
dd("ctx = %p", ctx);
231+
232+
if (ctx == NULL) {
233+
return NGX_ERROR;
234+
}
235+
236+
ngx_stream_lua_reset_ctx(r, L, ctx);
237+
238+
ctx->entered_access_phase = 1;
239+
240+
ctx->cur_co_ctx = &ctx->entry_co_ctx;
241+
ctx->cur_co_ctx->co = co;
242+
ctx->cur_co_ctx->co_ref = co_ref;
243+
#ifdef NGX_LUA_USE_ASSERT
244+
ctx->cur_co_ctx->co_top = 1;
245+
#endif
246+
247+
ngx_stream_lua_attach_co_ctx_to_L(co, ctx->cur_co_ctx);
248+
249+
/* }}} */
250+
251+
/* {{{ register request cleanup hooks */
252+
if (ctx->cleanup == NULL) {
253+
cln = ngx_stream_lua_cleanup_add(r, 0);
254+
if (cln == NULL) {
255+
return NGX_STREAM_INTERNAL_SERVER_ERROR;
256+
}
257+
258+
cln->handler = ngx_stream_lua_request_cleanup_handler;
259+
cln->data = ctx;
260+
ctx->cleanup = &cln->handler;
261+
}
262+
/* }}} */
263+
264+
ctx->context = NGX_STREAM_LUA_CONTEXT_ACCESS;
265+
266+
lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);
267+
268+
if (lscf->check_client_abort) {
269+
r->read_event_handler = ngx_stream_lua_rd_check_broken_connection;
270+
271+
rev = r->connection->read;
272+
273+
if (!rev->active) {
274+
if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
275+
return NGX_ERROR;
276+
}
277+
}
278+
279+
} else {
280+
r->read_event_handler = ngx_stream_lua_block_reading;
281+
}
282+
283+
rc = ngx_stream_lua_run_thread(L, r, ctx, 0);
284+
285+
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
286+
"access run thread returned %d", (int) rc);
287+
288+
if (rc == NGX_ERROR || rc > NGX_OK) {
289+
return rc;
290+
}
291+
292+
c = r->connection;
293+
294+
if (rc == NGX_AGAIN) {
295+
rc = ngx_stream_lua_run_posted_threads(c, L, r, ctx, 0);
296+
297+
if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) {
298+
return rc;
299+
}
300+
301+
if (rc != NGX_OK) {
302+
return NGX_DECLINED;
303+
}
304+
305+
} else if (rc == NGX_DONE) {
306+
ngx_stream_lua_finalize_request(r, NGX_DONE);
307+
308+
rc = ngx_stream_lua_run_posted_threads(c, L, r, ctx, 0);
309+
310+
if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) {
311+
return rc;
312+
}
313+
314+
if (rc != NGX_OK) {
315+
return NGX_DECLINED;
316+
}
317+
}
318+
319+
if (rc == NGX_OK) {
320+
return NGX_OK;
321+
}
322+
323+
return NGX_DECLINED;
324+
}
325+
326+
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

0 commit comments

Comments
 (0)