feature: implemented the *_by_lua_block {...} directives that do not require extra escaping when inlining Lua code in nginx.conf.

This commit is contained in:
Yichun Zhang (agentzh) 2015-09-14 22:33:34 +08:00
Родитель b5de0c2f9d
Коммит 6b558cd4bd
9 изменённых файлов: 9286 добавлений и 3 удалений

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

@ -153,6 +153,7 @@ src/uthread.[ch]
src/timer.[ch]
src/config.[ch]
src/worker.[ch]
src/lex.[ch]
*.plist
lua
ttimer

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

@ -283,6 +283,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/src/ngx_http_lua_timer.c \
$ngx_addon_dir/src/ngx_http_lua_config.c \
$ngx_addon_dir/src/ngx_http_lua_worker.c \
$ngx_addon_dir/src/ngx_http_lua_lex.c \
"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
@ -336,6 +337,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ngx_addon_dir/src/ngx_http_lua_timer.h \
$ngx_addon_dir/src/ngx_http_lua_config.h \
$ngx_addon_dir/src/ngx_http_lua_worker.h \
$ngx_addon_dir/src/ngx_http_lua_lex.h \
"
CFLAGS="$CFLAGS -DNDK_SET_VAR"

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

@ -24,6 +24,11 @@
#include "ngx_http_lua_initby.h"
#include "ngx_http_lua_initworkerby.h"
#include "ngx_http_lua_shdict.h"
#include "ngx_http_lua_lex.h"
typedef struct ngx_http_lua_block_parser_ctx_s
ngx_http_lua_block_parser_ctx_t;
#if defined(NDK) && NDK
@ -35,6 +40,17 @@ static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r);
static u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag,
size_t tag_len);
static char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf,
ngx_command_t *cmd);
static ngx_int_t ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
ngx_http_lua_block_parser_ctx_t *ctx);
struct ngx_http_lua_block_parser_ctx_s {
ngx_uint_t start_line;
int token_len;
int expect_right_lbracket;
};
char *
@ -372,6 +388,25 @@ ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, ngx_str_t *val,
#endif /* defined(NDK) && NDK */
char *
ngx_http_lua_rewrite_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_rewrite_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -467,6 +502,25 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_access_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -558,6 +612,25 @@ ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_content_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -583,6 +656,9 @@ ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
dd("value[0]: %.*s", (int) value[0].len, value[0].data);
dd("value[1]: %.*s", (int) value[1].len, value[1].data);
if (value[1].len == 0) {
/* Oops...Invalid location conf */
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
@ -659,6 +735,25 @@ ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_log_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_log_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -749,6 +844,25 @@ ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_header_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_header_filter_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
@ -830,6 +944,25 @@ ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
}
char *
ngx_http_lua_body_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_body_filter_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
@ -912,6 +1045,25 @@ ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
}
char *
ngx_http_lua_init_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_init_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
@ -960,6 +1112,25 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
}
char *
ngx_http_lua_init_worker_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
char *rv;
ngx_conf_t save;
save = *cf;
cf->handler = ngx_http_lua_init_worker_by_lua;
cf->handler_conf = conf;
rv = ngx_http_lua_conf_lua_block_parse(cf, cmd);
*cf = save;
return rv;
}
char *
ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
@ -1078,4 +1249,361 @@ found:
}
/* a specialized version of the standard ngx_conf_parse() function */
static char *
ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd)
{
ngx_http_lua_block_parser_ctx_t ctx;
int level = 1;
char *rv;
u_char *p;
size_t len;
ngx_str_t *src, *dst;
ngx_int_t rc;
ngx_uint_t i, start_line;
ngx_array_t *saved;
enum {
parse_block = 0,
parse_param
} type;
enum {
found_left_curly = 0,
found_right_curly,
found_left_lbracket_str,
found_left_lbracket_cmt,
found_right_lbracket,
found_comment_line,
found_double_quoted,
found_single_quoted
};
if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
type = parse_block;
} else {
type = parse_param;
}
saved = cf->args;
cf->args = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
if (cf->args == NULL) {
return NGX_CONF_ERROR;
}
ctx.token_len = 0;
ctx.expect_right_lbracket = 0;
start_line = cf->conf_file->line;
dd("init start line: %d", (int) start_line);
ctx.start_line = start_line;
for ( ;; ) {
rc = ngx_http_lua_conf_read_lua_token(cf, &ctx);
dd("parser start line: %d", (int) start_line);
switch (rc) {
case NGX_ERROR:
goto done;
case found_left_curly:
if (ctx.expect_right_lbracket) {
break;
}
ctx.start_line = cf->conf_file->line;
if (type == parse_param) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"block directives are not supported "
"in -g option");
goto failed;
}
level++;
dd("seen block start: level=%d", (int) level);
break;
case found_right_curly:
if (ctx.expect_right_lbracket) {
break;
}
level--;
dd("seen block done: level=%d", (int) level);
if (type != parse_block || level < 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected \"}\": level %d, "
"starting at line %ui", level,
start_line);
goto failed;
}
if (level == 0) {
ngx_http_lua_assert(cf->handler);
src = cf->args->elts;
for (len = 0, i = 0; i < cf->args->nelts; i++) {
len += src[i].len;
}
dd("saved nelts: %d", (int) saved->nelts);
dd("temp nelts: %d", (int) cf->args->nelts);
ngx_http_lua_assert(saved->nelts == 1);
dst = ngx_array_push(saved);
if (dst == NULL) {
return NGX_CONF_ERROR;
}
dst->len = len;
dst->len--; /* skip the trailing '}' block terminator */
p = ngx_palloc(cf->pool, len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
dst->data = p;
for (i = 0; i < cf->args->nelts; i++) {
p = ngx_copy(p, src[i].data, src[i].len);
}
p[-1] = '\0'; /* override the last '}' char to null */
cf->args = saved;
rv = (*cf->handler)(cf, cmd, cf->handler_conf);
if (rv == NGX_CONF_OK) {
goto done;
}
if (rv == NGX_CONF_ERROR) {
goto failed;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
goto failed;
}
break;
case found_left_lbracket_str:
if (ctx.expect_right_lbracket) {
break;
}
ctx.expect_right_lbracket = ctx.token_len;
ctx.start_line = cf->conf_file->line;
break;
case found_left_lbracket_cmt:
if (ctx.expect_right_lbracket) {
break;
}
ctx.expect_right_lbracket = ctx.token_len - (sizeof("--") - 1);
ctx.start_line = cf->conf_file->line;
break;
case found_right_lbracket:
if (!ctx.expect_right_lbracket) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected lua closing long-bracket");
goto failed;
}
if (ctx.token_len != ctx.expect_right_lbracket) {
/* unmatched long brackets */
break;
}
ctx.expect_right_lbracket = 0;
break;
case found_comment_line:
case found_double_quoted:
case found_single_quoted:
if (ctx.expect_right_lbracket) {
break;
}
break;
default:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown return value from the lexer: %i", rc);
goto failed;
}
}
failed:
rc = NGX_ERROR;
done:
if (rc == NGX_ERROR) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
ngx_http_lua_block_parser_ctx_t *ctx)
{
enum {
OVEC_SIZE = 2
};
int i, rc;
int ovec[OVEC_SIZE];
u_char *start, ch;
off_t file_size;
size_t len, buf_size;
ssize_t n, size;
ngx_uint_t start_line;
ngx_str_t *word;
ngx_buf_t *b;
#if nginx_version >= 1009002
ngx_buf_t *dump;
#endif
b = cf->conf_file->buffer;
#if nginx_version >= 1009002
dump = cf->conf_file->dump;
#endif
start = b->pos;
start_line = cf->conf_file->line;
buf_size = b->end - b->start;
dd("lexer start line: %d", (int) start_line);
file_size = ngx_file_size(&cf->conf_file->file.info);
for ( ;; ) {
if (b->pos >= b->last) {
if (cf->conf_file->file.offset >= file_size) {
cf->conf_file->line = ctx->start_line;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of file, expecting "
"terminating characters for lua code "
"block");
return NGX_ERROR;
}
len = b->pos - start;
if (len == buf_size) {
cf->conf_file->line = start_line;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"too long lua code block, probably "
"missing terminating characters");
return NGX_ERROR;
}
if (len) {
ngx_memmove(b->start, start, len);
}
size = (ssize_t) (file_size - cf->conf_file->file.offset);
if (size > b->end - (b->start + len)) {
size = b->end - (b->start + len);
}
n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
cf->conf_file->file.offset);
if (n == NGX_ERROR) {
return NGX_ERROR;
}
if (n != size) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
ngx_read_file_n " returned "
"only %z bytes instead of %z",
n, size);
return NGX_ERROR;
}
b->pos = b->start + len;
b->last = b->pos + n;
start = b->start;
#if nginx_version >= 1009002
if (dump) {
dump->last = ngx_cpymem(dump->last, b->pos, size);
}
#endif
}
rc = ngx_http_lua_lex(b->pos, b->last - b->pos, ovec);
if (rc < 0) { /* no match */
if (ctx->expect_right_lbracket) {
cf->conf_file->line = ctx->start_line;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Lua code block missing the closing "
"long bracket");
} else {
cf->conf_file->line = start_line;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"Lua code block missing the \"}\" "
"character");
}
return NGX_ERROR;
}
for (i = 0; i < ovec[1]; i++) {
ch = b->pos[i];
if (ch == LF) {
cf->conf_file->line++;
}
}
b->pos += ovec[1];
ctx->token_len = ovec[1] - ovec[0];
break;
}
word = ngx_array_push(cf->args);
if (word == NULL) {
return NGX_ERROR;
}
word->data = ngx_pnalloc(cf->temp_pool, b->pos - start);
if (word->data == NULL) {
return NGX_ERROR;
}
len = b->pos - start;
ngx_memcpy(word->data, start, len);
word->len = len;
return rc;
}
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

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

@ -17,20 +17,36 @@ char *ngx_http_lua_package_cpath(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_package_path(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_rewrite_by_lua_block(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);
char *ngx_http_lua_access_by_lua_block(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);
char *ngx_http_lua_log_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_header_filter_by_lua_block(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
char *ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_body_filter_by_lua_block(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
char *ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_init_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_init_worker_by_lua_block(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
char *ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

8251
src/ngx_http_lua_lex.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

17
src/ngx_http_lua_lex.h Normal file
Просмотреть файл

@ -0,0 +1,17 @@
/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef _NGX_HTTP_LUA_LEX_H_INCLUDED_
#define _NGX_HTTP_LUA_LEX_H_INCLUDED_
#include "ngx_http_lua_common.h"
int ngx_http_lua_lex(const u_char *const s, size_t len, int *const ovec);
#endif

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

@ -149,6 +149,13 @@ static ngx_command_t ngx_http_lua_cmds[] = {
offsetof(ngx_http_lua_loc_conf_t, log_socket_errors),
NULL },
{ ngx_string("init_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_init_by_lua_block,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
(void *) ngx_http_lua_init_by_inline },
{ ngx_string("init_by_lua"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_lua_init_by_lua,
@ -163,6 +170,13 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_init_by_file },
{ ngx_string("init_worker_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_init_worker_by_lua_block,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
(void *) ngx_http_lua_init_worker_by_inline },
{ ngx_string("init_worker_by_lua"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_lua_init_worker_by_lua,
@ -197,7 +211,7 @@ static ngx_command_t ngx_http_lua_cmds[] = {
(void *) ngx_http_lua_filter_set_by_lua_file },
#endif
/* rewrite_by_lua <inline script> */
/* rewrite_by_lua "<inline script>" */
{ ngx_string("rewrite_by_lua"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
@ -206,7 +220,16 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_rewrite_handler_inline },
/* access_by_lua <inline script> */
/* rewrite_by_lua_block { <inline script> } */
{ ngx_string("rewrite_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_rewrite_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_rewrite_handler_inline },
/* access_by_lua "<inline script>" */
{ ngx_string("access_by_lua"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
@ -215,7 +238,16 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_access_handler_inline },
/* content_by_lua <inline script> */
/* access_by_lua_block { <inline script> } */
{ ngx_string("access_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_access_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_access_handler_inline },
/* content_by_lua "<inline script>" */
{ ngx_string("content_by_lua"),
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
ngx_http_lua_content_by_lua,
@ -223,6 +255,14 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_content_handler_inline },
/* content_by_lua_block { <inline script> } */
{ ngx_string("content_by_lua_block"),
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_content_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_content_handler_inline },
/* log_by_lua <inline script> */
{ ngx_string("log_by_lua"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
@ -232,6 +272,15 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_log_handler_inline },
/* log_by_lua_block { <inline script> } */
{ ngx_string("log_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_log_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_log_handler_inline },
{ ngx_string("rewrite_by_lua_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
@ -280,6 +329,15 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_header_filter_inline },
/* header_filter_by_lua_block { <inline script> } */
{ ngx_string("header_filter_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_header_filter_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_header_filter_inline },
{ ngx_string("header_filter_by_lua_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
@ -296,6 +354,15 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_body_filter_inline },
/* body_filter_by_lua_block { <inline script> } */
{ ngx_string("body_filter_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_body_filter_by_lua_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
(void *) ngx_http_lua_body_filter_inline },
{ ngx_string("body_filter_by_lua_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,

383
t/132-lua-blocks.t Normal file
Просмотреть файл

@ -0,0 +1,383 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 3 + 2);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: content_by_lua_block (simplest)
--- config
location = /t {
content_by_lua_block {
ngx.say("hello, world")
}
}
--- request
GET /t
--- response_body
hello, world
--- no_error_log
[error]
=== TEST 2: content_by_lua_block (nested curly braces)
--- config
location = /t {
content_by_lua_block {
local a = {
dogs = {32, 78, 96},
cat = "kitty",
}
ngx.say("a.dogs[1] = ", a.dogs[1])
ngx.say("a.dogs[2] = ", a.dogs[2])
ngx.say("a.dogs[3] = ", a.dogs[3])
ngx.say("a.cat = ", a.cat)
}
}
--- request
GET /t
--- response_body
a.dogs[1] = 32
a.dogs[2] = 78
a.dogs[3] = 96
a.cat = kitty
--- no_error_log
[error]
=== TEST 3: content_by_lua_block (curly braces in strings)
--- config
location = /t {
content_by_lua_block {
ngx.say("}1, 2)")
ngx.say('{1, 2)')
}
}
--- request
GET /t
--- response_body
}1, 2)
{1, 2)
--- no_error_log
[error]
=== TEST 4: content_by_lua_block (curly braces in strings, with escaped terminators)
--- config
location = /t {
content_by_lua_block {
ngx.say("\"}1, 2)")
ngx.say('\'{1, 2)')
}
}
--- request
GET /t
--- response_body
"}1, 2)
'{1, 2)
--- no_error_log
[error]
=== TEST 5: content_by_lua_block (curly braces in long brackets)
--- config
location = /t {
content_by_lua_block {
--[[
{{{
}
]]
--[==[
}}}
{
]==]
ngx.say("ok")
}
}
--- request
GET /t
--- response_body
ok
--- no_error_log
[error]
=== TEST 6: content_by_lua_block ("nested" long brackets)
--- config
location = /t {
content_by_lua_block {
--[[
]=]
' "
}
]]
ngx.say("ok")
}
}
--- request
GET /t
--- response_body
ok
--- no_error_log
[error]
=== TEST 7: content_by_lua_block (curly braces in line comments)
--- config
location = /t {
content_by_lua_block {
--}} {}
ngx.say("ok")
}
}
--- request
GET /t
--- response_body
ok
--- no_error_log
[error]
=== TEST 8: content_by_lua_block (cosockets)
--- config
server_tokens off;
location = /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect('127.0.0.1', tonumber(ngx.var.server_port))
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say('connected: ', ok)
local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
local line, err, part = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err, " [", part, "]")
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
}
}
location /foo {
content_by_lua_block { ngx.say("foo") }
more_clear_headers Date;
}
--- request
GET /t
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed []
close: 1 nil
--- no_error_log
[error]
=== TEST 9: all in one
--- http_config
init_by_lua_block {
glob = "init by lua }here{"
}
init_worker_by_lua_block {
glob = glob .. ", init worker }here{"
}
--- config
location = /t {
set $a '';
rewrite_by_lua_block {
local s = ngx.var.a
s = s .. "}rewrite{\n"
ngx.var.a = s
}
access_by_lua_block {
local s = ngx.var.a
s = s .. '}access{\n'
ngx.var.a = s
}
content_by_lua_block {
local s = ngx.var.a
s = s .. [[}content{]]
ngx.say(s)
ngx.say("glob: ", glob)
}
log_by_lua_block {
print("log by lua running \"}{!\"")
}
header_filter_by_lua_block {
ngx.header["Foo"] = "\"Hello, world\""
ngx.header["Content-Length"] = nil
}
body_filter_by_lua_block {
local data, eof = ngx.arg[1], ngx.arg[2]
print("eof = ", eof)
if eof then
if not data then
data = ""
end
data = data .. "}body filter{\n"
print("data: ", data)
ngx.arg[1] = data
end
}
}
--- request
GET /t
--- response_body
}rewrite{
}access{
}content{
glob: init by lua }here{, init worker }here{
}body filter{
--- response_headers
Foo: "Hello, world"
--- error_log
log by lua running "}{!"
--- no_error_log
[error]
=== TEST 10: missing ]] (string)
--- config
location = /t {
content_by_lua_block {
ngx.say([[hello, world")
}
}
--- request
GET /t
--- response_body
hello, world
--- no_error_log
[error]
--- must_die
--- error_log eval
qr/\[emerg\] .*? Lua code block missing the closing long bracket in .*?\bnginx\.conf:40/
=== TEST 11: missing ]] (comment)
--- config
location = /t {
content_by_lua_block {
ngx.say(--[[hello, world")
}
}
--- request
GET /t
--- response_body
hello, world
--- no_error_log
[error]
--- must_die
--- error_log eval
qr/\[emerg\] .*? Lua code block missing the closing long bracket in .*?\bnginx\.conf:40/
=== TEST 12: missing }
FIXME: we need better diagnostics by actually loading the inlined Lua code while parsing
the *_by_lua_block directive.
--- config
location = /t {
content_by_lua_block {
ngx.say("hello")
--- request
GET /t
--- response_body
hello, world
--- no_error_log
[error]
--- error_log
"events" directive is not allowed here
--- must_die
=== TEST 13: content_by_lua_block (compact)
--- config
location = /t {
content_by_lua_block {ngx.say("hello, world", {"!"})}
}
--- request
GET /t
--- response_body
hello, world!
--- no_error_log
[error]
=== TEST 14: content_by_lua_block (unexpected closing long brackets)
--- config
location = /t {
content_by_lua_block {
]=]
}
}
--- request
GET /t
--- no_error_log
[error]
--- error_log eval
qr{\[emerg\] .*? unexpected lua closing long-bracket in .*?/nginx\.conf:40}
--- must_die

18
util/gen-lexer-c Executable file
Просмотреть файл

@ -0,0 +1,18 @@
#!/usr/bin/env bash
if [ -z "$1" ]; then
level=0
else
level="$1"
fi
#echo '{' '}' '\[=*\[' '--\[=*\[' '\]=*\]' '--[^\n]*' '"(?:\\[^\n]|[^"\n\\])*"' $'\'(?:\\\\[^\\n]|[^\'\\n\\\\])*\''
# we need the re.pl script here:
# https://github.com/openresty/sregex/blob/dfa-multi-re/re.pl
re.pl -W --no-main -c --cc="clang -O2" \
--func-name ngx_http_lua_lex \
--header ngx_http_lua_lex.h -o src/ngx_http_lua_lex.c \
--debug=$level -n 8 \
-- '{' '}' '\[=*\[' '--\[=*\[' '\]=*\]' '--[^\n]*' '"(?:\\[^\n]|[^"\n\\])*"' $'\'(?:\\\\[^\\n]|[^\'\\n\\\\])*\'' \
|| exit 1