Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add access_by_lua(_block/_file) and access_by_lua_no_postpone #217

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 Down Expand Up @@ -170,6 +173,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 @@ -527,7 +531,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 @@ -280,6 +280,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 @@ -324,6 +325,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
320 changes: 320 additions & 0 deletions src/ngx_stream_lua_accessby.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@

/*
* 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 (rc == NGX_OK) {
return NGX_OK;
}

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