Skip to content

Commit d84ed91

Browse files
committed
feat: server rewrite code
add 2 directive 1. server_rewrite_by_lua_block 2. server_rewrite_by_lua_file
1 parent 66294b9 commit d84ed91

11 files changed

Lines changed: 839 additions & 2 deletions

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ HTTP_LUA_SRCS=" \
261261
$ngx_addon_dir/src/ngx_http_lua_util.c \
262262
$ngx_addon_dir/src/ngx_http_lua_cache.c \
263263
$ngx_addon_dir/src/ngx_http_lua_contentby.c \
264+
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.c \
264265
$ngx_addon_dir/src/ngx_http_lua_rewriteby.c \
265266
$ngx_addon_dir/src/ngx_http_lua_accessby.c \
266267
$ngx_addon_dir/src/ngx_http_lua_setby.c \
@@ -325,6 +326,7 @@ HTTP_LUA_DEPS=" \
325326
$ngx_addon_dir/src/ngx_http_lua_util.h \
326327
$ngx_addon_dir/src/ngx_http_lua_cache.h \
327328
$ngx_addon_dir/src/ngx_http_lua_contentby.h \
329+
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.c \
328330
$ngx_addon_dir/src/ngx_http_lua_rewriteby.h \
329331
$ngx_addon_dir/src/ngx_http_lua_accessby.h \
330332
$ngx_addon_dir/src/ngx_http_lua_setby.h \

doc/HttpLuaModule.wiki

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,88 @@ Nginx variables are supported in the file path for dynamic dispatch, for example
15681568
15691569
But be very careful about malicious user inputs and always carefully validate or filter out the user-supplied path components.
15701570
1571+
== server_rewrite_by_lua_block ==
1572+
1573+
'''syntax:''' ''server_rewrite_by_lua_block { lua-script }''
1574+
1575+
'''context:''' ''http, server''
1576+
1577+
'''phase:''' ''server rewrite''
1578+
1579+
Acts as a server rewrite phase handler and executes Lua code string specified in <code>{ lua-script }</code> for every request.
1580+
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).
1581+
1582+
<geshi lang="nginx">
1583+
server {
1584+
...
1585+
1586+
server_rewrite_by_lua_block {
1587+
ngx.ctx.a = "server_rewrite_by_lua_block in http"
1588+
}
1589+
1590+
location /lua {
1591+
content_by_lua_block {
1592+
ngx.say(ngx.ctx.a)
1593+
ngx.log(ngx.INFO, ngx.ctx.a)
1594+
}
1595+
}
1596+
}
1597+
</geshi>
1598+
1599+
Just as any other rewrite phase handlers, [[#server_rewrite_by_lua_block|server_rewrite_by_lua_block]] also runs in subrequests.
1600+
1601+
<geshi lang="nginx">
1602+
server {
1603+
server_rewrite_by_lua_block {
1604+
ngx.log(ngx.INFO, "is_subrequest:", ngx.is_subrequest)
1605+
}
1606+
1607+
location /lua {
1608+
content_by_lua_block {
1609+
local res = ngx.location.capture("/sub")
1610+
ngx.print(res.body)
1611+
}
1612+
}
1613+
1614+
location /sub {
1615+
content_by_lua_block {
1616+
ngx.say("OK")
1617+
}
1618+
}
1619+
}
1620+
</geshi>
1621+
1622+
Note that when calling <code>ngx.exit(ngx.OK)</code> within a [[#server_rewrite_by_lua_block|server_rewrite_by_lua_block]] handler, the Nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [[#server_rewrite_by_lua_block|server_rewrite_by_lua_block]] handler, call [[#ngx.exit|ngx.exit]] with status >= 200 (<code>ngx.HTTP_OK</code>) and status < 300 (<code>ngx.HTTP_SPECIAL_RESPONSE</code>) for successful quits and <code>ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)</code> (or its friends) for failures.
1623+
1624+
1625+
<geshi lang="nginx">
1626+
server_rewrite_by_lua_block {
1627+
ngx.exit(503)
1628+
}
1629+
1630+
location /bar {
1631+
...
1632+
# never exec
1633+
}
1634+
</geshi>
1635+
1636+
1637+
== server_rewrite_by_lua_file ==
1638+
1639+
'''syntax:''' ''server_rewrite_by_lua_file <path-to-lua-script-file>''
1640+
1641+
'''context:''' ''http, server''
1642+
1643+
'''phase:''' ''server rewrite''
1644+
1645+
Equivalent to [[#server_rewrite_by_lua_block|server_rewrite_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.10.22</code> release, the [[#LuaJIT bytecode support|LuaJIT bytecode]] to be executed.
1646+
1647+
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.
1648+
1649+
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.
1650+
1651+
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 reloading Nginx.
1652+
15711653
== rewrite_by_lua ==
15721654
15731655
'''syntax:''' ''rewrite_by_lua <lua-script-str>''

src/ngx_http_lua_common.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ struct ngx_http_lua_main_conf_s {
305305
unsigned requires_log:1;
306306
unsigned requires_shm:1;
307307
unsigned requires_capture_log:1;
308+
unsigned requires_server_rewrite:1;
308309
};
309310

310311

@@ -368,6 +369,7 @@ typedef struct {
368369

369370
ngx_flag_t http10_buffering;
370371

372+
ngx_http_handler_pt server_rewrite_handler;
371373
ngx_http_handler_pt rewrite_handler;
372374
ngx_http_handler_pt access_handler;
373375
ngx_http_handler_pt content_handler;
@@ -376,6 +378,14 @@ typedef struct {
376378

377379
ngx_http_output_body_filter_pt body_filter_handler;
378380

381+
u_char *server_rewrite_chunkname;
382+
ngx_http_complex_value_t server_rewrite_src; /* server_rewrite_by_lua
383+
inline script/script
384+
file path */
385+
386+
u_char *server_rewrite_src_key; /* cached key for server_rewrite_src */
387+
int server_rewrite_src_ref;
388+
379389
u_char *rewrite_chunkname;
380390
ngx_http_complex_value_t rewrite_src; /* rewrite_by_lua
381391
inline script/script
@@ -629,7 +639,7 @@ typedef struct ngx_http_lua_ctx_s {
629639
response headers */
630640
unsigned mime_set:1; /* whether the user has set Content-Type
631641
response header */
632-
642+
unsigned entered_server_rewrite_phase:1;
633643
unsigned entered_rewrite_phase:1;
634644
unsigned entered_access_phase:1;
635645
unsigned entered_content_phase:1;

src/ngx_http_lua_directive.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "ngx_http_lua_cache.h"
1818
#include "ngx_http_lua_contentby.h"
1919
#include "ngx_http_lua_accessby.h"
20+
#include "ngx_http_lua_server_rewriteby.h"
2021
#include "ngx_http_lua_rewriteby.h"
2122
#include "ngx_http_lua_logby.h"
2223
#include "ngx_http_lua_headerfilterby.h"
@@ -590,6 +591,88 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
590591
}
591592

592593

594+
char *
595+
ngx_http_lua_server_rewrite_by_lua_block(ngx_conf_t *cf,
596+
ngx_command_t *cmd, void *conf)
597+
{
598+
char *rv;
599+
ngx_conf_t save;
600+
save = *cf;
601+
cf->handler = ngx_http_lua_server_rewrite_by_lua;
602+
cf->handler_conf = conf;
603+
604+
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
605+
606+
*cf = save;
607+
608+
return rv;
609+
}
610+
611+
612+
char *
613+
ngx_http_lua_server_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
614+
void *conf)
615+
{
616+
u_char *cache_key = NULL;
617+
ngx_str_t *value;
618+
ngx_http_lua_main_conf_t *lmcf;
619+
ngx_http_lua_loc_conf_t *llcf = conf;
620+
621+
ngx_http_compile_complex_value_t ccv;
622+
623+
dd("enter");
624+
625+
/* must specify a content handler */
626+
if (cmd->post == NULL) {
627+
return NGX_CONF_ERROR;
628+
}
629+
630+
if (llcf->server_rewrite_handler) {
631+
return "is duplicate";
632+
}
633+
634+
value = cf->args->elts;
635+
636+
if (value[1].len == 0) {
637+
/* Oops...Invalid location conf */
638+
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
639+
"invalid location config: no runnable Lua code");
640+
641+
return NGX_CONF_ERROR;
642+
}
643+
644+
/* only for by_file */
645+
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
646+
ccv.cf = cf;
647+
ccv.value = &value[1];
648+
ccv.complex_value = &llcf->server_rewrite_src;
649+
650+
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
651+
return NGX_CONF_ERROR;
652+
}
653+
654+
if (llcf->server_rewrite_src.lengths == NULL) {
655+
/* no variable found */
656+
cache_key = ngx_http_lua_gen_file_cache_key(cf, value[1].data,
657+
value[1].len);
658+
if (cache_key == NULL) {
659+
return NGX_CONF_ERROR;
660+
}
661+
}
662+
663+
664+
llcf->server_rewrite_src_key = cache_key;
665+
llcf->server_rewrite_handler = (ngx_http_handler_pt) cmd->post;
666+
667+
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
668+
669+
lmcf->requires_server_rewrite = 1;
670+
lmcf->requires_capture_filter = 1;
671+
672+
return NGX_CONF_OK;
673+
}
674+
675+
593676
char *
594677
ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
595678
void *conf)

src/ngx_http_lua_directive.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ char *ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
2525
void *conf);
2626
char *ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
2727
void *conf);
28+
char *ngx_http_lua_server_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
29+
void *conf);
30+
char *ngx_http_lua_server_rewrite_by_lua_block(ngx_conf_t *cf,
31+
ngx_command_t *cmd, void *conf);
2832
char *ngx_http_lua_rewrite_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
2933
void *conf);
3034
char *ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,

src/ngx_http_lua_module.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ngx_http_lua_directive.h"
1515
#include "ngx_http_lua_capturefilter.h"
1616
#include "ngx_http_lua_contentby.h"
17+
#include "ngx_http_lua_server_rewriteby.h"
1718
#include "ngx_http_lua_rewriteby.h"
1819
#include "ngx_http_lua_accessby.h"
1920
#include "ngx_http_lua_logby.h"
@@ -290,6 +291,22 @@ static ngx_command_t ngx_http_lua_cmds[] = {
290291
(void *) ngx_http_lua_filter_set_by_lua_file },
291292
#endif
292293

294+
/* server_rewrite_by_lua_block { <inline script> } */
295+
{ ngx_string("server_rewrite_by_lua_block"),
296+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
297+
ngx_http_lua_server_rewrite_by_lua_block,
298+
NGX_HTTP_LOC_CONF_OFFSET,
299+
0,
300+
(void *) ngx_http_lua_server_rewrite_handler_inline },
301+
302+
/* server_rewrite_by_lua_file filename; */
303+
{ ngx_string("server_rewrite_by_lua_file"),
304+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
305+
ngx_http_lua_server_rewrite_by_lua,
306+
NGX_HTTP_LOC_CONF_OFFSET,
307+
0,
308+
(void *) ngx_http_lua_server_rewrite_handler_file },
309+
293310
/* rewrite_by_lua "<inline script>" */
294311
{ ngx_string("rewrite_by_lua"),
295312
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
@@ -752,6 +769,16 @@ ngx_http_lua_init(ngx_conf_t *cf)
752769

753770
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
754771

772+
if (lmcf->requires_server_rewrite) {
773+
h = ngx_array_push(
774+
&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers);
775+
if (h == NULL) {
776+
return NGX_ERROR;
777+
}
778+
779+
*h = ngx_http_lua_server_rewrite_handler;
780+
}
781+
755782
if (lmcf->requires_rewrite) {
756783
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
757784
if (h == NULL) {
@@ -1366,6 +1393,14 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
13661393
ngx_http_lua_loc_conf_t *prev = parent;
13671394
ngx_http_lua_loc_conf_t *conf = child;
13681395

1396+
if (conf->server_rewrite_src.value.len == 0) {
1397+
conf->server_rewrite_src = prev->server_rewrite_src;
1398+
conf->server_rewrite_handler = prev->server_rewrite_handler;
1399+
conf->server_rewrite_src_ref = prev->server_rewrite_src_ref;
1400+
conf->server_rewrite_src_key = prev->server_rewrite_src_key;
1401+
conf->server_rewrite_chunkname = prev->server_rewrite_chunkname;
1402+
}
1403+
13691404
if (conf->rewrite_src.value.len == 0) {
13701405
conf->rewrite_src = prev->rewrite_src;
13711406
conf->rewrite_handler = prev->rewrite_handler;

0 commit comments

Comments
 (0)