access_by_lua and access_by_lua_file are passing tests now.

This commit is contained in:
agentzh (章亦春) 2011-01-07 18:37:46 +08:00
Родитель 2606b2f2fd
Коммит 20e919d612
12 изменённых файлов: 569 добавлений и 50 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -101,3 +101,5 @@ src/headers.c
src/headers.h
go
all.sh
src/accessby.[ch]
src/rewriteby.[ch]

Просмотреть файл

@ -253,7 +253,7 @@ content.
This hook uses exactly the same mechamism as `content_by_lua` so all the nginx APIs defined there
are also available here.
Note that this handler always runs *after* the standard nginx rewrite module. So the following will work as expected:
Note that this handler always runs *after* the standard nginx rewrite module ( http://wiki.nginx.org/NginxHttpRewriteModule ). So the following will work as expected:
location /foo {
set $a 12; # create and initialize $a
@ -295,8 +295,110 @@ The right way of doing this is as follows:
echo "res = $b";
}
It's worth mentioning that, the `ngx_eval` module can be
approximately implemented by `rewrite_by_lua`. For example,
location / {
eval $res {
proxy_pass http://foo.com/check-spam;
}
if ($res = 'spam') {
rewrite ^ /terms-of-use.html redirect;
}
fastcgi_pass ...;
}
can be implemented in terms of `ngx_lua` like this
location = /check-spam {
internal;
proxy_pass http://foo.com/check-spam;
}
location / {
rewrite_by_lua '
local res = ngx.location.capture("/check-spam")
if res.body == "spam" then
ngx.redirect("/terms-of-use.html")
end
';
fastcgi_pass ...;
}
Just as any other rewrite-phase handlers, `rewrite_by_lua` also runs in subrequests.
This directive won't work properly with nginx 0.7.x.
access_by_lua
--------------
* **Syntax:** `access_by_lua <lua-script-str>`
* **Context:** `location | lif`
* **Phase:** `access tail`
Act as an access phase handler and execute user code specified by `<lua-script-str>`
for every request. The user code may call predefined APIs to generate response
content.
This hook uses exactly the same mechamism as `content_by_lua`
so all the nginx APIs defined there
are also available here.
Note that this handler always runs *after* the standard nginx
access module ( http://wiki.nginx.org/NginxHttpAccessModule ).
So the following will work as expected:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
deny all;
access_by_lua '
local res = ngx.location.capture("/mysql", { ... })
...
';
# proxy_pass/fastcgi_pass/...
}
That is, if a client address appears in the blacklist, then
we don't have to bother sending a mysql query to do more
advanced authentication in `access_by_lua`.
It's worth mentioning that, the `ngx_auth_request` module can be
approximately implemented by `access_by_lua`. For example,
location / {
auth_request /auth;
...
}
can be implemented in terms of `ngx_lua` like this
location / {
access_by_lua '
local res = ngx.location.capture("/auth")
if res.status == ngx.HTTP_OK then
return
end
if res.status == ngx.HTTP_FORBIDDEN then
ngx.exit(res.status)
end
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
';
...
}
Just as any other access-phase handlers, `access_by_lua` will NOT run in subrequests.
content_by_lua_file
-------------------
@ -322,6 +424,16 @@ the file specified by `<path-lua-script>`.
This directive won't work properly with nginx 0.7.x.
access_by_lua_file
-------------------
* **Syntax:** `access_by_lua_file <path-to-lua-script>`
* **Context:** `location | lif`
* **Phase:** `access tail`
Same as `access_by_lua`, except the code to be executed is in
the file specified by `<path-lua-script>`.
lua_need_request_body
---------------------
@ -374,7 +486,7 @@ that outputs 88, the sum of 32 and 56.
Read and write Nginx variables
------------------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
value = ngx.var.some_nginx_variable_name
ngx.var.some_nginx_variable_name = value
@ -394,7 +506,7 @@ That is, nginx variables cannot be created on-the-fly.
Core constants
---------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
ngx.OK
ngx.DONE
@ -403,7 +515,7 @@ Core constants
HTTP method constants
---------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
value = ngx.HTTP_GET
value = ngx.HTTP_HEAD
@ -413,7 +525,7 @@ HTTP method constants
HTTP status constants
---------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
value = ngx.HTTP_OK
value = ngx.HTTP_CREATED
@ -430,7 +542,7 @@ HTTP status constants
Nginx log level constants
-------------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
log_level = ngx.STDERR
log_level = ngx.EMERG
@ -444,7 +556,7 @@ Nginx log level constants
print(a, b, ...)
----------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Emit args concatenated to `error.log`, with log level `ngx.NOTICE` and prefix `lua print: `.
@ -456,7 +568,7 @@ Nil arguments are accepted and result in literal "nil".
ngx.location.capture(uri, options?)
-----------------------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Issue a synchronous but still non-blocking "nginx subrequest" using `uri`.
@ -538,7 +650,7 @@ This is functionally identical to the previous examples.
ngx.status
----------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Read and write the response status. This should be called
before sending out the response headers.
@ -548,7 +660,7 @@ before sending out the response headers.
ngx.header.HEADER
-----------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Set/add/clear response headers. Underscores (_) in the header names will be replaced by dashes (-) and the header names will be matched case-insentively.
@ -597,7 +709,7 @@ shouldn't need it.
ngx.exec(uri, args)
-------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Does an internal redirect to uri with args.
@ -630,7 +742,7 @@ directive in the ngx_echo module.
ngx.redirect(uri, status?)
--------------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Issue an HTTP 301 or 302 redirection to `uri`.
@ -671,7 +783,7 @@ is equivalent to
ngx.send_headers()
------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Explicitly send out the response headers.
@ -683,7 +795,7 @@ Headers will also be sent automatically when `content_by_lua` exits normally.
ngx.print(a, b, ...)
--------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Emit args concatenated to the HTTP client (as response body).
@ -691,7 +803,7 @@ Nil arguments are not allowed.
ngx.say(a, b, ...)
------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Just as `ngx.print` but also emit a trailing newline.
@ -699,7 +811,7 @@ Nil arguments are not allowed.
ngx.log(log_level, ...)
-----------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Log args concatenated to error.log with the given logging level.
@ -707,13 +819,13 @@ Nil arguments are accepted and result in literal "nil".
ngx.flush()
-----------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Force flushing the response outputs.
ngx.exit(status)
----------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Interrupts the execution of the current Lua thread and returns
status code to nginx.
@ -724,13 +836,13 @@ or other HTTP status numbers.
ngx.eof()
---------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Explicitly specify the end of the response output stream.
ngx.escape_uri(str)
-------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Escape `str` as a URI component.
@ -738,7 +850,7 @@ Escape `str` as a URI component.
ngx.unescape_uri(str)
---------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Unescape `str` as a escaped URI component.
@ -746,7 +858,7 @@ Unescape `str` as a escaped URI component.
ngx.encode_base64(str)
----------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Encode `str` to a base64 digest
@ -754,7 +866,7 @@ Encode `str` to a base64 digest
ngx.decode_base64(str)
----------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Decode `str` as a base64 digest to the raw form
@ -762,7 +874,7 @@ Decode `str` as a base64 digest to the raw form
ngx.today()
---------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Returns today's date (in the format `yyyy-mm-dd`) from nginx cached time (no syscall involved unlike Lua's date library).
.
@ -771,13 +883,13 @@ This is the local time.
ngx.time()
-------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Returns the elapsed seconds from the epoch for the current timestamp from the nginx cached time (no syscall involved unlike Lua's date library).
ngx.localtime()
---------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Returns the current timestamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's date library).
@ -785,7 +897,7 @@ This is the local time.
ngx.utctime()
-------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Returns the current timestamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's date library).
@ -793,7 +905,7 @@ This is the UTC time.
ngx.cookie_time(sec)
--------------------
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `set_by_lua*`, `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
Returns a formated string can be used as the cookie expiration time. The parameter `sec` is the timestamp in seconds (like those returned from `ngx.time`).
@ -802,7 +914,7 @@ Returns a formated string can be used as the cookie expiration time. The paramet
ndk.set_var.DIRECTIVE
---------------------
* **Context:** `rewrite_by_lua*`, `content_by_lua*`
* **Context:** `rewrite_by_lua*`, `access_by_lua*`, `content_by_lua*`
This mechanism allows calling other nginx C modules' directives that are
implemented by Nginx Devel Kit (NDK)'s set_var submodule's ndk_set_var_value.
@ -836,12 +948,12 @@ Lua can be obtained freely from its project [homepage](http://www.lua.org/).
lua-nginx-module [file list](http://github.com/chaoslawful/lua-nginx-module/downloads).
1. Grab the nginx source code from [nginx.net](http://nginx.net/), for example,
the version 0.8.53 (see nginx compatibility), and then build the source with
the version 0.8.54 (see nginx compatibility), and then build the source with
this module:
$ wget 'http://sysoev.ru/nginx/nginx-0.8.53.tar.gz'
$ tar -xzvf nginx-0.8.53.tar.gz
$ cd nginx-0.8.53/
$ wget 'http://sysoev.ru/nginx/nginx-0.8.54.tar.gz'
$ tar -xzvf nginx-0.8.54.tar.gz
$ cd nginx-0.8.54/
# tell nginx's build system where to find lua:
export LUA_LIB=/path/to/lua/lib
@ -865,7 +977,7 @@ Compatibility
The following versions of Nginx should work with this module:
* 0.9.x (last tested: 0.9.3)
* 0.8.x (last tested: 0.8.53)
* 0.8.x (last tested: 0.8.54)
* 0.7.x >= 0.7.46 (last tested: 0.7.68)
Earlier versions of Nginx like 0.6.x and 0.5.x will **not** work.

4
config
Просмотреть файл

@ -123,8 +123,8 @@ fi
ngx_addon_name=ngx_http_lua_module
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_lua_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_lua_module.c $ngx_addon_dir/src/ngx_http_lua_headers.c $ngx_addon_dir/src/ngx_http_lua_directive.c $ngx_addon_dir/src/ngx_http_lua_hook.c $ngx_addon_dir/src/ngx_http_lua_util.c $ngx_addon_dir/src/ngx_http_lua_cache.c $ngx_addon_dir/src/ngx_http_lua_conf.c $ngx_addon_dir/src/ngx_http_lua_contentby.c $ngx_addon_dir/src/ngx_http_lua_rewriteby.c $ngx_addon_dir/src/ngx_http_lua_setby.c $ngx_addon_dir/src/ngx_http_lua_filter.c $ngx_addon_dir/src/ngx_http_lua_clfactory.c"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_lua_common.h $ngx_addon_dir/src/ngx_http_lua_directive.h $ngx_addon_dir/src/ngx_http_lua_headers.h $ngx_addon_dir/src/ngx_http_lua_hook.h $ngx_addon_dir/src/ngx_http_lua_util.h $ngx_addon_dir/src/ngx_http_lua_cache.h $ngx_addon_dir/src/ngx_http_lua_conf.h $ngx_addon_dir/src/ngx_http_lua_contentby.h $ngx_addon_dir/src/ngx_http_lua_rewriteby.h $ngx_addon_dir/src/ngx_http_lua_setby.h $ngx_addon_dir/src/ngx_http_lua_filter.h $ngx_addon_dir/src/ngx_http_lua_clfactory.h"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_lua_module.c $ngx_addon_dir/src/ngx_http_lua_headers.c $ngx_addon_dir/src/ngx_http_lua_directive.c $ngx_addon_dir/src/ngx_http_lua_hook.c $ngx_addon_dir/src/ngx_http_lua_util.c $ngx_addon_dir/src/ngx_http_lua_cache.c $ngx_addon_dir/src/ngx_http_lua_conf.c $ngx_addon_dir/src/ngx_http_lua_contentby.c $ngx_addon_dir/src/ngx_http_lua_rewriteby.c $ngx_addon_dir/src/ngx_http_lua_accessby.c $ngx_addon_dir/src/ngx_http_lua_setby.c $ngx_addon_dir/src/ngx_http_lua_filter.c $ngx_addon_dir/src/ngx_http_lua_clfactory.c"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_lua_common.h $ngx_addon_dir/src/ngx_http_lua_directive.h $ngx_addon_dir/src/ngx_http_lua_headers.h $ngx_addon_dir/src/ngx_http_lua_hook.h $ngx_addon_dir/src/ngx_http_lua_util.h $ngx_addon_dir/src/ngx_http_lua_cache.h $ngx_addon_dir/src/ngx_http_lua_conf.h $ngx_addon_dir/src/ngx_http_lua_contentby.h $ngx_addon_dir/src/ngx_http_lua_rewriteby.h $ngx_addon_dir/src/ngx_http_lua_accessby.h $ngx_addon_dir/src/ngx_http_lua_setby.h $ngx_addon_dir/src/ngx_http_lua_filter.h $ngx_addon_dir/src/ngx_http_lua_clfactory.h"
CFLAGS="$CFLAGS -DNDK_SET_VAR -DNGX_OPENSSL_MD5 -DNGX_HAVE_OPENSSL_MD5_H -DNGX_HAVE_OPENSSL_SHA1_H -DNDK_SET_VAR -DNDK_HASH -DNDK_SHA1 -DNDK_MD5"
CORE_LIBS="-Wl,-E $CORE_LIBS"

300
src/ngx_http_lua_accessby.c Normal file
Просмотреть файл

@ -0,0 +1,300 @@
/* vim:set ft=c ts=4 sw=4 et fdm=marker: */
#define DDEBUG 0
#include "nginx.h"
#include "ngx_http_lua_accessby.h"
#include "ngx_http_lua_util.h"
#include "ngx_http_lua_hook.h"
#include "ngx_http_lua_cache.h"
ngx_int_t
ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r)
{
int cc_ref;
lua_State *cc;
ngx_http_lua_ctx_t *ctx;
ngx_http_cleanup_t *cln;
/* {{{ new coroutine to handle request */
cc = ngx_http_lua_new_thread(r, L, &cc_ref);
if (cc == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"(lua-content-by-chunk) failed to create new coroutine "
"to handle request");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
/* move code closure to new coroutine */
lua_xmove(L, cc, 1);
/* set closure's env table to new coroutine's globals table */
lua_pushvalue(cc, LUA_GLOBALSINDEX);
lua_setfenv(cc, -2);
/* save reference of code to ease forcing stopping */
lua_pushvalue(cc, -1);
lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE);
/* save nginx request in coroutine globals table */
lua_pushlightuserdata(cc, r);
lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST);
/* }}} */
/* {{{ initialize request context */
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
dd("ctx = %p", ctx);
if (ctx == NULL) {
return NGX_ERROR;
}
ngx_http_lua_reset_ctx(r, L, ctx);
ctx->entered_access_phase = 1;
ctx->cc = cc;
ctx->cc_ref = cc_ref;
/* }}} */
/* {{{ register request cleanup hooks */
if (ctx->cleanup == NULL) {
cln = ngx_http_cleanup_add(r, 0);
if (cln == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
cln->handler = ngx_http_lua_request_cleanup;
cln->data = r;
ctx->cleanup = &cln->handler;
}
/* }}} */
return ngx_http_lua_run_thread(L, r, ctx, 0);
}
ngx_int_t
ngx_http_lua_access_handler_file(ngx_http_request_t *r)
{
lua_State *L;
ngx_int_t rc;
u_char *script_path;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_loc_conf_t *llcf;
char *err;
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
script_path = ngx_http_lua_rebase_path(r->pool, llcf->access_src.data,
llcf->access_src.len);
if (script_path == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to allocate memory to store absolute path: raw path='%v'",
&(llcf->access_src));
return NGX_ERROR;
}
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
L = lmcf->lua;
/* load Lua script file (w/ cache) sp = 1 */
rc = ngx_http_lua_cache_loadfile(L, (char *) script_path, &err);
if (rc != NGX_OK) {
if (err == NULL) {
err = "unknown error";
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to load Lua inlined code: %s", err);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
/* make sure we have a valid code chunk */
assert(lua_isfunction(L, -1));
rc = ngx_http_lua_access_by_chunk(L, r);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
if (rc == NGX_DONE) {
return NGX_DONE;
}
if (rc == NGX_AGAIN) {
return NGX_DONE;
}
return NGX_DECLINED;
}
ngx_int_t
ngx_http_lua_access_handler(ngx_http_request_t *r)
{
ngx_http_lua_loc_conf_t *llcf;
ngx_http_lua_ctx_t *ctx;
ngx_int_t rc;
ngx_http_lua_main_conf_t *lmcf;
dd("in access handler: %.*s", (int) r->uri.len, r->uri.data);
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
if (! lmcf->postponed_to_access_phase_end) {
ngx_http_core_main_conf_t *cmcf;
ngx_http_phase_handler_t tmp;
ngx_http_phase_handler_t *ph;
ngx_http_phase_handler_t *cur_ph;
ngx_http_phase_handler_t *last_ph;
lmcf->postponed_to_access_phase_end = 1;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
ph = cmcf->phase_engine.handlers;
cur_ph = &ph[r->phase_handler];
last_ph = &ph[cur_ph->next - 1];
#if 0
if (cur_ph == last_ph) {
dd("XXX our handler is already the last access phase handler");
}
#endif
if (cur_ph < last_ph) {
dd("swaping the contents of cur_ph and last_ph...");
tmp = *cur_ph;
memmove(cur_ph, cur_ph + 1,
(last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t));
*last_ph = tmp;
r->phase_handler--; /* redo the current ph */
return NGX_DECLINED;
}
}
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
if (llcf->access_handler == NULL) {
dd("no access handler found");
return NGX_DECLINED;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
dd("ctx = %p", ctx);
if (ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
dd("setting new ctx: ctx = %p", ctx);
ctx->cc_ref = LUA_NOREF;
ngx_http_set_ctx(r, ctx, ngx_http_lua_module);
}
dd("entered? %d", (int) ctx->entered_access_phase);
if (ctx->waiting_more_body) {
return NGX_DECLINED;
}
if (ctx->entered_access_phase) {
dd("calling wev handler");
rc = ngx_http_lua_wev_handler(r);
dd("wev handler returns %d", (int) rc);
return rc;
}
if (llcf->force_read_body &&
! ctx->read_body_done &&
((r->method & NGX_HTTP_POST) || (r->method & NGX_HTTP_PUT)))
{
rc = ngx_http_read_client_request_body(r,
ngx_http_lua_generic_phase_post_read);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
if (rc == NGX_AGAIN) {
ctx->waiting_more_body = 1;
return NGX_DONE;
}
}
dd("calling access handler");
return llcf->access_handler(r);
}
ngx_int_t
ngx_http_lua_access_handler_inline(ngx_http_request_t *r)
{
lua_State *L;
ngx_int_t rc;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_loc_conf_t *llcf;
char *err;
dd("HERE");
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
L = lmcf->lua;
/* load Lua inline script (w/ cache) sp = 1 */
rc = ngx_http_lua_cache_loadbuffer(L, llcf->access_src.data,
llcf->access_src.len, "access_by_lua", &err);
if (rc != NGX_OK) {
if (err == NULL) {
err = "unknown error";
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to load Lua inlined code: %s", err);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
rc = ngx_http_lua_access_by_chunk(L, r);
dd("access by chunk returns %d", (int) rc);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
if (rc == NGX_DONE) {
return NGX_DONE;
}
if (rc == NGX_AGAIN) {
return NGX_DONE;
}
return NGX_DECLINED;
}

Просмотреть файл

@ -0,0 +1,17 @@
/* vim:set ft=c ts=4 sw=4 et fdm=marker: */
#ifndef NGX_HTTP_LUA_ACCESS_BY_H__
#define NGX_HTTP_LUA_ACCESS_BY_H__
#include "ngx_http_lua_common.h"
ngx_int_t ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r);
ngx_int_t ngx_http_lua_access_handler(ngx_http_request_t *r);
ngx_int_t ngx_http_lua_access_handler_inline(ngx_http_request_t *r);
ngx_int_t ngx_http_lua_access_handler_file(ngx_http_request_t *r);
#endif

Просмотреть файл

@ -26,7 +26,7 @@ typedef struct {
ngx_str_t lua_cpath;
unsigned postponed_to_rewrite_phase_end:1;
unsigned postponed_to_access_phase_end:1; /* TODO */
unsigned postponed_to_access_phase_end:1;
} ngx_http_lua_main_conf_t;
@ -35,11 +35,12 @@ typedef struct {
0: don't force reading request body */
ngx_http_handler_pt rewrite_handler;
ngx_http_handler_pt access_handler;
ngx_http_handler_pt content_handler;
ngx_str_t rewrite_src; /* rewrite_by_lua
inline script/script file path */
ngx_str_t access_src;
ngx_str_t content_src; /* content_by_lua
inline script/script file path */
@ -87,8 +88,9 @@ typedef struct {
0: no need to wait */
unsigned headers_set:1;
unsigned entered_content_phase:1;
unsigned entered_rewrite_phase:1;
unsigned entered_access_phase:1;
unsigned entered_content_phase:1;
ngx_http_cleanup_pt *cleanup;

Просмотреть файл

@ -10,7 +10,8 @@
#include "ngx_http_lua_contentby.h"
ngx_flag_t ngx_http_lua_requires_rewrite = 0;
unsigned ngx_http_lua_requires_rewrite = 0;
unsigned ngx_http_lua_requires_access = 0;
char *
@ -227,6 +228,62 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_str_t *args;
ngx_http_lua_loc_conf_t *llcf = conf;
dd("enter");
/* must specifiy a content handler */
if (cmd->post == NULL) {
return NGX_CONF_ERROR;
}
if (llcf->access_handler) {
return "is duplicate";
}
/* update lua script data */
/*
* args[0] = "content_by_lua"
* args[1] = lua script to be executed
* */
args = cf->args->elts;
/* prevent variable appearing in Lua inline script/file path */
#if 0
if (ngx_http_lua_has_inline_var(&args[1])) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
"Lua inline script or file path should not has inline "
"variable: %V",
&args[1]);
return NGX_CONF_ERROR;
}
#endif
if (args[1].len == 0) {
/* Oops...Invalid location conf */
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
"Invalid location config: no runnable Lua code");
return NGX_CONF_ERROR;
}
llcf->access_src = args[1];
llcf->access_handler = cmd->post;
if (! ngx_http_lua_requires_access) {
ngx_http_lua_requires_access = 1;
}
return NGX_CONF_OK;
}
char *
ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{

Просмотреть файл

@ -5,7 +5,8 @@
#include "ngx_http_lua_common.h"
extern ngx_flag_t ngx_http_lua_requires_rewrite;
extern unsigned ngx_http_lua_requires_rewrite;
extern unsigned ngx_http_lua_requires_access;
char * ngx_http_lua_package_cpath(ngx_conf_t *cf, ngx_command_t *cmd,
@ -18,7 +19,8 @@ char * ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char * ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
ngx_int_t ngx_http_lua_rewrite_handler_file(ngx_http_request_t *r);
char * ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
ngx_int_t ngx_http_lua_filter_set_by_lua_inline(ngx_http_request_t *r,
ngx_str_t *val, ngx_http_variable_value_t *v, void *data);
ngx_int_t ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r,

Просмотреть файл

@ -5,6 +5,7 @@
#include "ngx_http_lua_filter.h"
#include "ngx_http_lua_contentby.h"
#include "ngx_http_lua_rewriteby.h"
#include "ngx_http_lua_accessby.h"
static ngx_int_t ngx_http_lua_init(ngx_conf_t *cf);
@ -72,6 +73,16 @@ static ngx_command_t ngx_http_lua_cmds[] = {
ngx_http_lua_rewrite_handler_inline
},
/* access_by_lua <inline script> */
{
ngx_string("access_by_lua"),
NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_http_lua_access_by_lua,
NGX_HTTP_LOC_CONF_OFFSET,
0,
ngx_http_lua_access_handler_inline
},
/* content_by_lua <inline script> */
{
ngx_string("content_by_lua"),
@ -91,6 +102,15 @@ static ngx_command_t ngx_http_lua_cmds[] = {
ngx_http_lua_rewrite_handler_file
},
{
ngx_string("access_by_lua_file"),
NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_http_lua_access_by_lua,
NGX_HTTP_LOC_CONF_OFFSET,
0,
ngx_http_lua_access_handler_file
},
/* content_by_lua_file rel/or/abs/path/to/script */
{
ngx_string("content_by_lua_file"),
@ -146,9 +166,9 @@ ngx_http_lua_init(ngx_conf_t *cf)
return rc;
}
if (ngx_http_lua_requires_rewrite) {
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
if (ngx_http_lua_requires_rewrite) {
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
@ -157,6 +177,15 @@ ngx_http_lua_init(ngx_conf_t *cf)
*h = ngx_http_lua_rewrite_handler;
}
if (ngx_http_lua_requires_access) {
h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_lua_access_handler;
}
return NGX_OK;
}

Просмотреть файл

@ -53,9 +53,9 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r)
return NGX_ERROR;
}
#if 0
ngx_http_lua_reset_ctx(r, L, ctx);
#endif
ctx->entered_rewrite_phase = 1;
ctx->cc = cc;
ctx->cc_ref = cc_ref;
@ -243,10 +243,6 @@ ngx_http_lua_rewrite_handler(ngx_http_request_t *r)
}
}
dd("setting entered");
ctx->entered_rewrite_phase = 1;
dd("calling rewrite handler");
return llcf->rewrite_handler(r);
}

Просмотреть файл

@ -10,6 +10,7 @@
ngx_int_t ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r);
ngx_int_t ngx_http_lua_rewrite_handler(ngx_http_request_t *r);
ngx_int_t ngx_http_lua_rewrite_handler_inline(ngx_http_request_t *r);
ngx_int_t ngx_http_lua_rewrite_handler_file(ngx_http_request_t *r);
#endif

Просмотреть файл

@ -807,6 +807,7 @@ ngx_http_lua_reset_ctx(ngx_http_request_t *r, lua_State *L,
ctx->waiting = 0;
ctx->done = 0;
ctx->entered_rewrite_phase = 0;
ctx->entered_access_phase = 0;
ctx->exit_code = 0;
ctx->exited = 0;
ctx->exec_uri.data = NULL;