Skip to content

Commit

Permalink
Add access_by_lua(_block/_file) and access_by_lua_no_postpone
Browse files Browse the repository at this point in the history
Some rudimentary tests
  • Loading branch information
arcivanov committed Nov 9, 2020
1 parent 1a1e49b commit 7b9c916
Show file tree
Hide file tree
Showing 22 changed files with 747 additions and 32 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ behavior.
* [init_worker_by_lua_file](https://github.com/openresty/lua-nginx-module#init_worker_by_lua_file)
* [preread_by_lua_block](#preread_by_lua_block)
* [preread_by_lua_file](#preread_by_lua_file)
* [access_by_lua](https://github.com/openresty/lua-nginx-module#access_by_lua)
* [access_by_lua_block](https://github.com/openresty/lua-nginx-module#access_by_lua_block)
* [access_by_lua_file](https://github.com/openresty/lua-nginx-module#access_by_lua_file)
* [content_by_lua_block](https://github.com/openresty/lua-nginx-module#content_by_lua_block)
* [content_by_lua_file](https://github.com/openresty/lua-nginx-module#content_by_lua_file)
* [balancer_by_lua_block](https://github.com/openresty/lua-nginx-module#balancer_by_lua_block)
Expand All @@ -167,6 +170,7 @@ behavior.
* [lua_add_variable](#lua_add_variable)
* [lua_capture_error_log](https://github.com/openresty/lua-nginx-module#lua_capture_error_log)
* [preread_by_lua_no_postpone](#preread_by_lua_no_postpone)
* [access_by_lua_no_postpone](https://github.com/openresty/lua-nginx-module#access_by_lua_no_postpone)

The [send_timeout](https://nginx.org/r/send_timeout) directive in the Nginx
"http" subsystem is missing in the "stream" subsystem. As such,
Expand Down Expand Up @@ -524,7 +528,6 @@ output to be completely flushed out (to the system socket send buffers).
TODO
====

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

[Back to TOC](#table-of-contents)
Expand Down
2 changes: 2 additions & 0 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ STREAM_LUA_SRCS=" \
$ngx_addon_dir/src/ngx_stream_lua_ssl_certby.c \
$ngx_addon_dir/src/ngx_stream_lua_log_ringbuf.c \
$ngx_addon_dir/src/ngx_stream_lua_input_filters.c \
$ngx_addon_dir/src/ngx_stream_lua_accessby.c \
"

STREAM_LUA_DEPS=" \
Expand Down Expand Up @@ -322,6 +323,7 @@ STREAM_LUA_DEPS=" \
$ngx_addon_dir/src/ngx_stream_lua_ssl_certby.h \
$ngx_addon_dir/src/ngx_stream_lua_log_ringbuf.h \
$ngx_addon_dir/src/ngx_stream_lua_input_filters.h \
$ngx_addon_dir/src/ngx_stream_lua_accessby.h \
"

# ----------------------------------------
Expand Down
322 changes: 322 additions & 0 deletions src/ngx_stream_lua_accessby.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@

/*
* Copyright (C) Xiaozhe Wang (chaoslawful)
* Copyright (C) Yichun Zhang (agentzh)
* Copyright (C) Arcadiy Ivanov (arcivanov)
*/


#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"


#include <nginx.h>
#include "ngx_stream_lua_accessby.h"
#include "ngx_stream_lua_util.h"
#include "ngx_stream_lua_exception.h"
#include "ngx_stream_lua_cache.h"


static ngx_int_t ngx_stream_lua_access_by_chunk(lua_State *L,
ngx_stream_lua_request_t *r);


ngx_int_t
ngx_stream_lua_access_handler(ngx_stream_session_t *s)
{
ngx_int_t rc;
ngx_stream_lua_ctx_t *ctx;
ngx_stream_lua_srv_conf_t *lscf;
ngx_stream_lua_main_conf_t *lmcf;
ngx_stream_lua_request_t *r;

dd("entered");

ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
"lua access handler");

lmcf = ngx_stream_get_module_main_conf(s, ngx_stream_lua_module);

if (!lmcf->postponed_to_access_phase_end) {
ngx_stream_phase_handler_t tmp, *ph, *cur_ph, *last_ph;
ngx_stream_core_main_conf_t *cmcf;
lmcf->postponed_to_access_phase_end = 1;

cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

ph = cmcf->phase_engine.handlers;
cur_ph = &ph[s->phase_handler];
/* we should skip the post_access phase handler here too */
last_ph = &ph[cur_ph->next - 2];

dd("ph cur: %d, ph next: %d", (int) s->phase_handler,
(int) (cur_ph->next - 2));

if (cur_ph < last_ph) {
dd("swapping the contents of cur_ph and last_ph...");

tmp = *cur_ph;

memmove(cur_ph, cur_ph + 1,
(last_ph - cur_ph) * sizeof (ngx_stream_phase_handler_t));

*last_ph = tmp;

s->phase_handler--; /* redo the current ph */

return NGX_DECLINED;
}
}

lscf = ngx_stream_get_module_srv_conf(s, ngx_stream_lua_module);

if (lscf->access_handler == NULL) {
dd("no access handler found");
return NGX_DECLINED;
}

ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module);

dd("ctx = %p", ctx);

if (ctx == NULL) {
ctx = ngx_stream_lua_create_ctx(s);
if (ctx == NULL) {
return NGX_STREAM_INTERNAL_SERVER_ERROR;
}
}

r = ctx->request;

dd("entered? %d", (int) ctx->entered_access_phase);

if (ctx->entered_access_phase) {
dd("calling wev handler");
rc = ctx->resume_handler(r);
dd("wev handler returns %d", (int) rc);

if (rc == NGX_ERROR || rc == NGX_DONE || rc == NGX_OK || rc > NGX_OK) {
return rc;
}

return NGX_DECLINED;
}

dd("calling access handler");
return lscf->access_handler(r);
}


ngx_int_t
ngx_stream_lua_access_handler_inline(ngx_stream_lua_request_t *r)
{
ngx_int_t rc;
lua_State *L;
ngx_stream_lua_srv_conf_t *lscf;

dd("entered");

lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);

L = ngx_stream_lua_get_lua_vm(r, NULL);

/* load Lua inline script (w/ cache) sp = 1 */
rc = ngx_stream_lua_cache_loadbuffer(r->connection->log, L,
lscf->access_src.value.data,
lscf->access_src.value.len,
lscf->access_src_key,
(const char *) lscf->access_chunkname);

if (rc != NGX_OK) {
return NGX_STREAM_INTERNAL_SERVER_ERROR;
}

return ngx_stream_lua_access_by_chunk(L, r);
}


ngx_int_t
ngx_stream_lua_access_handler_file(ngx_stream_lua_request_t *r)
{
u_char *script_path;
ngx_int_t rc;
ngx_str_t eval_src;
lua_State *L;
ngx_stream_lua_srv_conf_t *lscf;

dd("entered");

lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);

/* Eval nginx variables in code path string first */
if (ngx_stream_complex_value(r->session, &lscf->access_src, &eval_src) != NGX_OK) {
return NGX_ERROR;
}

script_path = ngx_stream_lua_rebase_path(r->pool, eval_src.data,
eval_src.len);

if (script_path == NULL) {
return NGX_ERROR;
}

L = ngx_stream_lua_get_lua_vm(r, NULL);

/* load Lua script file (w/ cache) sp = 1 */
rc = ngx_stream_lua_cache_loadfile(r->connection->log, L, script_path,
lscf->access_src_key);
if (rc != NGX_OK) {
if (rc < NGX_STREAM_SPECIAL_RESPONSE) {
return NGX_STREAM_INTERNAL_SERVER_ERROR;
}

return rc;
}

/* make sure we have a valid code chunk */
ngx_stream_lua_assert(lua_isfunction(L, -1));

return ngx_stream_lua_access_by_chunk(L, r);
}


static ngx_int_t
ngx_stream_lua_access_by_chunk(lua_State *L, ngx_stream_lua_request_t *r)
{
int co_ref;
ngx_int_t rc;
lua_State *co;
ngx_event_t *rev;
ngx_connection_t *c;
ngx_stream_lua_ctx_t *ctx;
ngx_stream_lua_cleanup_t *cln;

ngx_stream_lua_srv_conf_t *lscf;

/* {{{ new coroutine to handle request */
co = ngx_stream_lua_new_thread(r, L, &co_ref);

if (co == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"lua: failed to create new coroutine "
"to handle request");

return NGX_STREAM_INTERNAL_SERVER_ERROR;
}

/* move code closure to new coroutine */
lua_xmove(L, co, 1);

#ifndef OPENRESTY_LUAJIT
/* set closure's env table to new coroutine's globals table */
ngx_stream_lua_get_globals_table(co);
lua_setfenv(co, -2);
#endif

/* save nginx request in coroutine globals table */
ngx_stream_lua_set_req(co, r);

/* {{{ initialize request context */
ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_lua_module);

dd("ctx = %p", ctx);

if (ctx == NULL) {
return NGX_ERROR;
}

ngx_stream_lua_reset_ctx(r, L, ctx);

ctx->entered_access_phase = 1;

ctx->cur_co_ctx = &ctx->entry_co_ctx;
ctx->cur_co_ctx->co = co;
ctx->cur_co_ctx->co_ref = co_ref;
#ifdef NGX_LUA_USE_ASSERT
ctx->cur_co_ctx->co_top = 1;
#endif

// ngx_stream_lua_attach_co_ctx_to_L(co, ctx->cur_co_ctx);

/* }}} */

/* {{{ register request cleanup hooks */
if (ctx->cleanup == NULL) {
cln = ngx_stream_lua_cleanup_add(r, 0);
if (cln == NULL) {
return NGX_STREAM_INTERNAL_SERVER_ERROR;
}

cln->handler = ngx_stream_lua_request_cleanup_handler;
cln->data = ctx;
ctx->cleanup = &cln->handler;
}
/* }}} */

ctx->context = NGX_STREAM_LUA_CONTEXT_ACCESS;

lscf = ngx_stream_lua_get_module_srv_conf(r, ngx_stream_lua_module);

if (lscf->check_client_abort) {
r->read_event_handler = ngx_stream_lua_rd_check_broken_connection;

rev = r->connection->read;

if (!rev->active) {
if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
return NGX_ERROR;
}
}

} else {
r->read_event_handler = ngx_stream_lua_block_reading;
}

rc = ngx_stream_lua_run_thread(L, r, ctx, 0);

ngx_log_debug1(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
"access run thread returned %d", (int) rc);

if (rc == NGX_ERROR || rc > NGX_OK) {
return rc;
}

c = r->connection;

if (rc == NGX_AGAIN) {
rc = ngx_stream_lua_run_posted_threads(c, L, r, ctx, 0);

if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) {
return rc;
}

if (rc != NGX_OK) {
return NGX_DECLINED;
}

} else if (rc == NGX_DONE) {
ngx_stream_lua_finalize_request(r, NGX_DONE);

rc = ngx_stream_lua_run_posted_threads(c, L, r, ctx, 0);

if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) {
return rc;
}

if (rc != NGX_OK) {
return NGX_DECLINED;
}
}

#if 1
if (rc == NGX_OK) {
return NGX_OK;
}
#endif

return NGX_DECLINED;
}

/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
22 changes: 22 additions & 0 deletions src/ngx_stream_lua_accessby.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

/*
* Copyright (C) Xiaozhe Wang (chaoslawful)
* Copyright (C) Yichun Zhang (agentzh)
*/


#ifndef _NGX_STREAM_LUA_ACCESSBY_H_INCLUDED_
#define _NGX_STREAM_LUA_ACCESSBY_H_INCLUDED_


#include "ngx_stream_lua_common.h"


ngx_int_t ngx_stream_lua_access_handler(ngx_stream_session_t *s);
ngx_int_t ngx_stream_lua_access_handler_inline(ngx_stream_lua_request_t *r);
ngx_int_t ngx_stream_lua_access_handler_file(ngx_stream_lua_request_t *r);


#endif /* _NGX_STREAM_LUA_ACCESSBY_H_INCLUDED_ */

/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
Loading

0 comments on commit 7b9c916

Please sign in to comment.