Skip to content
Merged
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
82 changes: 81 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,8 @@ Directives
* [set_by_lua](#set_by_lua)
* [set_by_lua_block](#set_by_lua_block)
* [set_by_lua_file](#set_by_lua_file)
* [precontent_by_lua_block](#precontent_by_lua_block)
* [precontent_by_lua_file](#precontent_by_lua_file)
* [content_by_lua](#content_by_lua)
* [content_by_lua_block](#content_by_lua_block)
* [content_by_lua_file](#content_by_lua_file)
Expand Down Expand Up @@ -1196,6 +1198,7 @@ Directives
* [lua_http10_buffering](#lua_http10_buffering)
* [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone)
* [access_by_lua_no_postpone](#access_by_lua_no_postpone)
* [precontent_by_lua_no_postpone](#precontent_by_lua_no_postpone)
* [lua_transform_underscores_in_response_headers](#lua_transform_underscores_in_response_headers)
* [lua_check_client_abort](#lua_check_client_abort)
* [lua_max_pending_timers](#lua_max_pending_timers)
Expand Down Expand Up @@ -1842,6 +1845,70 @@ This directive requires the [ngx_devel_kit](https://github.com/simplresty/ngx_de

[Back to TOC](#directives)

precontent_by_lua_block
--------------------

**syntax:** *precontent_by_lua_block { lua-script }*

**context:** *http, server, location, location if*

**phase:** *precontent tail*

Acts as a precontent phase handler and executes Lua code string specified in `{ <lua-script }` for every request.
The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox).

Note that this handler always runs *after* the standard [ngx_http_mirror_module](https://nginx.org/en/docs/http/ngx_http_mirror_module.html) and [ngx_http_try_files_module](https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files). For example:

```nginx
location /images/ {
try_files $uri /images/default.gif;
precontent_by_lua_block {
ngx.log(ngx.NOTICE, "file found")
}
}

location = /images/default.gif {
expires 30s;
precontent_by_lua_block {
ngx.log(ngx.NOTICE, "file not found, use default.gif instead")
}
}
```

That is, if a request for /images/foo.jpg comes in and the file does not exist, the request will be internally redirected to /images/default.gif before [precontent_by_lua_block](#precontent_by_lua_block), and then the [precontent_by_lua_block](#precontent_by_lua_block) in new location will run and log "file not found, use default.gif instead".

You can use [precontent_by_lua_block](#precontent_by_lua_block) to perform some preparatory functions after the access phase handler but before the proxy or other content handler. Especially some functions that cannot be performed in [balancer_by_lua_block](#balancer_by_lua_block).

you can use the [precontent_by_lua_no_postpone](#precontent_by_lua_no_postpone) directive to control when to run this handler inside the "precontent" request-processing phase
of Nginx.

[Back to TOC](#directives)

precontent_by_lua_file
-------------------

**syntax:** *precontent_by_lua_file &lt;path-to-lua-script-file&gt;*

**context:** *http, server, location, location if*

**phase:** *precontent tail*

Equivalent to [precontent_by_lua_block](#precontent_by_lua_block), except that the file specified by `<path-to-lua-script-file>` contains the Lua code, or, as from the `v0.5.0rc32` release, the [LuaJIT bytecode](#luajit-bytecode-support) to be executed.

Nginx variables can be used in the `<path-to-lua-script-file>` string to provide flexibility. This however carries some risks and is not ordinarily recommended.

When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server.

When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached
and the Nginx config must be reloaded each time the Lua source file is modified.
The Lua code cache can be temporarily disabled during development by switching [lua_code_cache](#lua_code_cache) `off` in `nginx.conf` to avoid repeatedly reloading Nginx.

Nginx variables are supported in the file path for dynamic dispatch just as in [content_by_lua_file](#content_by_lua_file).

But be very careful about malicious user inputs and always carefully validate or filter out the user-supplied path components.

[Back to TOC](#directives)

content_by_lua
--------------

Expand Down Expand Up @@ -2710,7 +2777,7 @@ directive.
This Lua code execution context does not support yielding, so Lua APIs that may yield
(like cosockets and "light threads") are disabled in this context. One can usually work
around this limitation by doing such operations in an earlier phase handler (like
[access_by_lua*](#access_by_lua)) and passing along the result into this context
[precontent_by_lua*](#precontent_by_lua_block)) and passing along the result into this context
via the [ngx.ctx](#ngxctx) table.

This directive was first introduced in the `v0.10.0` release.
Expand Down Expand Up @@ -3647,6 +3714,19 @@ This directive was first introduced in the `v0.9.20` release.

[Back to TOC](#directives)

precontent_by_lua_no_postpone
-------------------------

**syntax:** *precontent_by_lua_no_postpone on|off*

**default:** *precontent_by_lua_no_postpone off*

**context:** *http*

Controls whether or not to disable postponing [precontent_by_lua*](#precontent_by_lua_block) directives to run at the end of the `precontent` request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the `precontent` phase.

[Back to TOC](#directives)

lua_transform_underscores_in_response_headers
---------------------------------------------

Expand Down
2 changes: 2 additions & 0 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ HTTP_LUA_SRCS=" \
$ngx_addon_dir/src/ngx_http_lua_exception.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_precontentby.c \
$ngx_addon_dir/src/ngx_http_lua_contentby.c \
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.c \
$ngx_addon_dir/src/ngx_http_lua_rewriteby.c \
Expand Down Expand Up @@ -327,6 +328,7 @@ HTTP_LUA_DEPS=" \
$ngx_addon_dir/src/ngx_http_lua_exception.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_precontentby.h \
$ngx_addon_dir/src/ngx_http_lua_contentby.h \
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.c \
$ngx_addon_dir/src/ngx_http_lua_rewriteby.h \
Expand Down
65 changes: 65 additions & 0 deletions doc/HttpLuaModule.wiki
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,61 @@ switching [[#lua_code_cache|lua_code_cache]] <code>off</code> in <code>nginx.con

This directive requires the [https://github.com/simplresty/ngx_devel_kit ngx_devel_kit] module.

== precontent_by_lua_block ==

'''syntax:''' ''precontent_by_lua_block { lua-script }''

'''context:''' ''http, server, location, location if''

'''phase:''' ''pre-content tail''

Acts as a precontent phase handler and executes Lua code string specified in <code>{ <lua-script }</code> for every request.
The Lua code may make [[#Nginx API for Lua|API calls]] and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox).

Note that this handler always runs *after* the standard [[HttpMirrorModule]] and [[HttpTryFilesModule]]. For example:

<geshi lang="nginx">
location /images/ {
try_files $uri /images/default.gif;
precontent_by_lua_block {
ngx.log(ngx.NOTICE, "file found")
}
}

location = /images/default.gif {
expires 30s;
precontent_by_lua_block {
ngx.log(ngx.NOTICE, "file not found, use default.gif instead")
}
}
</geshi>

That is, if a request for /images/foo.jpg comes in and the file does not exist, the request will be internally redirected to /images/default.gif before [[#precontent_by_lua_block|precontent_by_lua_block]], and then the [[#precontent_by_lua_block|precontent_by_lua_block]] in new location will run and log "file not found, use default.gif instead".

You can use [[#precontent_by_lua_block|precontent_by_lua_block]] to perform some preparatory functions after the access phase handler but before the proxy or other content handler. Especially some functions that cannot be performed in [[#balancer_by_lua_block|balancer_by_lua_block]].

You can use the [[#precontent_by_lua_no_postpone|precontent_by_lua_no_postpone]] directive to control when to run this handler inside the "precontent" request-processing phase of Nginx.

== precontent_by_lua_file ==

'''syntax:''' ''precontent_by_lua_file <path-to-lua-script-file>''

'''context:''' ''http, server, location, location if''

'''phase:''' ''precontent tail''

Equivalent to [[#precontent_by_lua_block|precontent_by_lua_block]], except that the file specified by <code><path-to-lua-script-file></code> contains the Lua code, or, as from the <code>v0.5.0rc32</code> release, the [[#LuaJIT bytecode support|LuaJIT bytecode]] to be executed.

Nginx variables can be used in the <code><path-to-lua-script-file></code> string to provide flexibility. This however carries some risks and is not ordinarily recommended.

When a relative path like <code>foo/bar.lua</code> is given, they will be turned into the absolute path relative to the <code>server prefix</code> path determined by the <code>-p PATH</code> command-line option while starting the Nginx server.

When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached
and the Nginx config must be reloaded each time the Lua source file is modified.
The Lua code cache can be temporarily disabled during development by switching [[#lua_code_cache|lua_code_cache]] <code>off</code> in <code>nginx.conf</code> to avoid repeatedly reloading Nginx.

Nginx variables are supported in the file path for dynamic dispatch just as in [[#content_by_lua_file|content_by_lua_file]].

== content_by_lua ==

'''syntax:''' ''content_by_lua <lua-script-str>''
Expand Down Expand Up @@ -3017,6 +3072,16 @@ Controls whether or not to disable postponing [[#access_by_lua|access_by_lua*]]

This directive was first introduced in the <code>v0.9.20</code> release.

== precontent_by_lua_no_postpone ==

'''syntax:''' ''precontent_by_lua_no_postpone on|off''

'''default:''' ''precontent_by_lua_no_postpone off''

'''context:''' ''http''

Controls whether or not to disable postponing [[#precontent_by_lua_block|precontent_by_lua_block*]] directives to run at the end of the <code>precontent</code> request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the <code>precontent</code> phase.

== lua_transform_underscores_in_response_headers ==

'''syntax:''' ''lua_transform_underscores_in_response_headers on|off''
Expand Down
21 changes: 16 additions & 5 deletions src/ngx_http_lua_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,8 @@ typedef struct {
#define NGX_HTTP_LUA_CONTEXT_EXIT_WORKER 0x00002000
#define NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO 0x00004000
#define NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE 0x00008000

#ifdef HAVE_PROXY_SSL_PATCH
#define NGX_HTTP_LUA_CONTEXT_PROXY_SSL_VERIFY 0x00010000
#endif
#define NGX_HTTP_LUA_CONTEXT_PRECONTENT 0x00020000


#define NGX_HTTP_LUA_FFI_NO_REQ_CTX -100
Expand Down Expand Up @@ -254,6 +252,7 @@ struct ngx_http_lua_main_conf_s {

ngx_flag_t postponed_to_rewrite_phase_end;
ngx_flag_t postponed_to_access_phase_end;
ngx_flag_t postponed_to_precontent_phase_end;

ngx_http_lua_main_conf_handler_pt init_handler;
ngx_str_t init_src;
Expand Down Expand Up @@ -322,6 +321,7 @@ struct ngx_http_lua_main_conf_s {
unsigned requires_shm:1;
unsigned requires_capture_log:1;
unsigned requires_server_rewrite:1;
unsigned requires_precontent:1;
};


Expand Down Expand Up @@ -414,6 +414,7 @@ struct ngx_http_lua_loc_conf_s {

ngx_http_handler_pt rewrite_handler;
ngx_http_handler_pt access_handler;
ngx_http_handler_pt precontent_handler;
ngx_http_handler_pt content_handler;
ngx_http_handler_pt log_handler;
ngx_http_handler_pt header_filter_handler;
Expand All @@ -438,13 +439,22 @@ struct ngx_http_lua_loc_conf_s {
u_char *access_src_key; /* cached key for access_src */
int access_src_ref;

u_char *precontent_chunkname;
ngx_http_complex_value_t precontent_src; /* precontent_by_lua
inline script/script
file path */

u_char *precontent_src_key; /* cached key for
precontent_src */
int precontent_src_ref;

u_char *content_chunkname;
ngx_http_complex_value_t content_src; /* content_by_lua
inline script/script
file path */

u_char *content_src_key; /* cached key for content_src */
int content_src_ref;
u_char *content_src_key; /* cached key for content_src */
int content_src_ref;


u_char *log_chunkname;
Expand Down Expand Up @@ -683,6 +693,7 @@ typedef struct ngx_http_lua_ctx_s {
unsigned entered_server_rewrite_phase:1;
unsigned entered_rewrite_phase:1;
unsigned entered_access_phase:1;
unsigned entered_precontent_phase:1;
unsigned entered_content_phase:1;

unsigned buffering:1; /* HTTP 1.0 response body buffering flag */
Expand Down
3 changes: 3 additions & 0 deletions src/ngx_http_lua_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ ngx_http_lua_ngx_exec(lua_State *L)
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_PRECONTENT
| NGX_HTTP_LUA_CONTEXT_CONTENT);

ngx_http_lua_check_if_abortable(L, ctx);
Expand Down Expand Up @@ -235,6 +236,7 @@ ngx_http_lua_ngx_redirect(lua_State *L)
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_PRECONTENT
| NGX_HTTP_LUA_CONTEXT_CONTENT);

ngx_http_lua_check_if_abortable(L, ctx);
Expand Down Expand Up @@ -380,6 +382,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
if (ngx_http_lua_ffi_check_context(ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_PRECONTENT
| NGX_HTTP_LUA_CONTEXT_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
Expand Down
Loading