update resty core and http lua to support latest version of stream lua and various fixes related to ci/cd

This commit is contained in:
bunkerity 2023-03-07 15:31:41 +01:00
parent a62ef9f543
commit c7d8b7dc18
169 changed files with 9228 additions and 1544 deletions

View File

@ -201,7 +201,7 @@ jobs:
needs: [code-security, build-ui]
uses: ./.github/workflows/staging-tests-ui.yml
with:
MODE: STAGING
MODE: staging
secrets:
PRIVATE_REGISTRY: ${{ secrets.PRIVATE_REGISTRY }}
PRIVATE_REGISTRY_TOKEN: ${{ secrets.PRIVATE_REGISTRY_TOKEN }}

View File

@ -93,6 +93,8 @@ spec:
periodSeconds: 1
timeoutSeconds: 1
failureThreshold: 3
#imagePullSecrets:
#- name: secret-registry
---
apiVersion: apps/v1
kind: Deployment
@ -120,6 +122,8 @@ spec:
value: "yes"
- name: "DATABASE_URI"
value: "mariadb+pymysql://bunkerweb:changeme@svc-bunkerweb-db:3306/db"
#imagePullSecrets:
#- name: secret-registry
---
apiVersion: apps/v1
kind: Deployment
@ -146,6 +150,8 @@ spec:
value: "yes"
- name: "DATABASE_URI"
value: "mariadb+pymysql://bunkerweb:changeme@svc-bunkerweb-db:3306/db"
#imagePullSecrets:
#- name: secret-registry
---
apiVersion: apps/v1
kind: Deployment

View File

@ -152,13 +152,13 @@ fi
echo " Downloading LuaJIT"
git_secure_clone "https://github.com/openresty/luajit2.git" "8384278b14988390cf030b787537aa916a9709bb"
# lua-nginx-module v0.10.22
# lua-nginx-module v0.10.23
echo " Downloading lua-nginx-module"
git_secure_clone "https://github.com/openresty/lua-nginx-module.git" "8d9032298ef542aef058fa02940a6ecd9cf25423"
git_secure_clone "https://github.com/openresty/lua-nginx-module.git" "5e05fa3adb0d2492ecaaf2cb76498e23765aa6ab"
# lua-resty-core v0.1.24
# lua-resty-core v0.1.25
echo " Downloading lua-resty-core"
git_secure_clone "https://github.com/openresty/lua-resty-core.git" "c48e90a8fc9d974d8a6a369e031940cedf473789"
git_secure_clone "https://github.com/openresty/lua-resty-core.git" "0173d96c9eb77b513b989b765716fd2498f09dd9"
# lua-resty-lrucache v0.13
echo " Downloading lua-resty-lrucache"

View File

@ -0,0 +1,30 @@
name: "Lint PR"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Configure which types are allowed.
# Default: https://github.com/commitizen/conventional-commit-types
types: |
bugfix # bug fixes
change # backward incompatible changes
doc # documentation changes including code comments
editor # code editor related configurations
feature # implementing a new feature
optimize # performance optimizations
refactor # code refactoring and other code rearrangement
style # coding style changes
tests # test suite changes

View File

@ -14,6 +14,7 @@ compiler:
addons:
apt:
packages:
- ack
- axel
- cpanminus
- libtest-base-perl
@ -36,7 +37,7 @@ env:
- LUAJIT_LIB=$LUAJIT_PREFIX/lib
- LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1
- LUA_INCLUDE_DIR=$LUAJIT_INC
- PCRE_VER=8.44
- PCRE_VER=8.45
- PCRE_PREFIX=/opt/pcre
- PCRE_LIB=$PCRE_PREFIX/lib
- PCRE_INC=$PCRE_PREFIX/include
@ -51,7 +52,7 @@ env:
- TEST_NGINX_SLEEP=0.006
jobs:
- NGINX_VERSION=1.21.4 OPENSSL_VER=1.1.0l OPENSSL_PATCH_VER=1.1.0d
- NGINX_VERSION=1.21.4 OPENSSL_VER=1.1.1l OPENSSL_PATCH_VER=1.1.1f
- NGINX_VERSION=1.21.4 OPENSSL_VER=1.1.1s OPENSSL_PATCH_VER=1.1.1f
services:
- memcached
@ -129,8 +130,12 @@ script:
- sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1)
- cd ..
- export NGX_BUILD_CC=$CC
- sh util/build-without-ssl.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
- sh util/build-with-dd.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
- rm -fr buildroot
- sh util/build.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
- nginx -V
- python3 ./util/nc_server.py &
- ldd `which nginx`|grep -E 'luajit|ssl|pcre'
- export LD_PRELOAD=$PWD/mockeagain/mockeagain.so
- export LD_LIBRARY_PATH=$PWD/mockeagain:$LD_LIBRARY_PATH
@ -138,4 +143,4 @@ script:
- dig +short myip.opendns.com @resolver1.opendns.com || exit 0
- dig +short @$TEST_NGINX_RESOLVER openresty.org || exit 0
- dig +short @$TEST_NGINX_RESOLVER agentzh.org || exit 0
- prove -I. -Itest-nginx/lib -r t
- prove -I. -Itest-nginx/lib -r t/

File diff suppressed because it is too large Load Diff

View File

@ -94,7 +94,7 @@ END
case "$NGX_PLATFORM" in
Darwin:*)
case "$NGX_MACHINE" in
amd64 | x86_64 | i386)
amd64 | arm64 | x86_64 | i386)
echo "adding extra linking options needed by LuaJIT on $NGX_MACHINE"
luajit_ld_opt="$luajit_ld_opt -pagezero_size 10000 -image_base 100000000"
ngx_feature_libs="$ngx_feature_libs -pagezero_size 10000 -image_base 100000000"
@ -261,6 +261,7 @@ HTTP_LUA_SRCS=" \
$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_contentby.c \
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.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 \
@ -325,6 +326,7 @@ HTTP_LUA_DEPS=" \
$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_contentby.h \
$ngx_addon_dir/src/ngx_http_lua_server_rewriteby.c \
$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 \

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
/* Public API for other Nginx modules */
#define ngx_http_lua_version 10022
#define ngx_http_lua_version 10023
typedef struct {

View File

@ -90,7 +90,7 @@ ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r,
lscf->balancer.src.len,
&lscf->balancer.src_ref,
lscf->balancer.src_key,
"=balancer_by_lua");
(const char *) lscf->balancer.chunkname);
if (rc != NGX_OK) {
return rc;
}
@ -125,6 +125,8 @@ char *
ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key = NULL;
u_char *name;
ngx_str_t *value;
@ -172,8 +174,16 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "balancer_by_lua",
sizeof("balancer_by_lua") - 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->balancer.src = value[1];
lscf->balancer.chunkname = chunkname;
}
lscf->balancer.src_key = cache_key;

View File

@ -161,7 +161,8 @@ ngx_http_lua_body_filter_inline(ngx_http_request_t *r, ngx_chain_t *in)
llcf->body_filter_src.value.len,
&llcf->body_filter_src_ref,
llcf->body_filter_src_key,
"=body_filter_by_lua");
(const char *)
llcf->body_filter_chunkname);
if (rc != NGX_OK) {
return NGX_ERROR;
}
@ -298,7 +299,7 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
out = NULL;
ngx_chain_update_chains(r->pool,
&ctx->free_bufs, &ctx->filter_busy_bufs, &out,
(ngx_buf_tag_t) &ngx_http_lua_module);
(ngx_buf_tag_t) &ngx_http_lua_body_filter);
if (rc != NGX_OK
&& ctx->filter_busy_bufs != NULL
&& (r->connection->buffered
@ -377,7 +378,7 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_chain_update_chains(r->pool,
&ctx->free_bufs, &ctx->filter_busy_bufs, &out,
(ngx_buf_tag_t) &ngx_http_lua_module);
(ngx_buf_tag_t) &ngx_http_lua_body_filter);
return rc;
}
@ -395,51 +396,48 @@ ngx_http_lua_body_filter_init(void)
int
ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r)
ngx_http_lua_ffi_get_body_filter_param_eof(ngx_http_request_t *r)
{
u_char *data, *p;
size_t size;
ngx_chain_t *cl;
ngx_buf_t *b;
int idx;
ngx_chain_t *in;
ngx_http_lua_main_conf_t *lmcf;
idx = luaL_checkint(L, 2);
dd("index: %d", idx);
if (idx != 1 && idx != 2) {
lua_pushnil(L);
return 1;
}
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
in = lmcf->body_filter_chain;
if (idx == 2) {
/* asking for the eof argument */
/* asking for the eof argument */
for (cl = in; cl; cl = cl->next) {
if (cl->buf->last_buf || cl->buf->last_in_chain) {
lua_pushboolean(L, 1);
return 1;
}
for (cl = in; cl; cl = cl->next) {
if (cl->buf->last_buf || cl->buf->last_in_chain) {
return 1;
}
lua_pushboolean(L, 0);
return 1;
}
/* idx == 1 */
return 0;
}
int
ngx_http_lua_ffi_get_body_filter_param_body(ngx_http_request_t *r,
u_char **data_p, size_t *len_p)
{
size_t size;
ngx_chain_t *cl;
ngx_buf_t *b;
ngx_chain_t *in;
ngx_http_lua_main_conf_t *lmcf;
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
in = lmcf->body_filter_chain;
size = 0;
if (in == NULL) {
/* being a cleared chain on the Lua land */
lua_pushliteral(L, "");
return 1;
*len_p = 0;
return NGX_OK;
}
if (in->next == NULL) {
@ -447,8 +445,9 @@ ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r)
dd("seen only single buffer");
b = in->buf;
lua_pushlstring(L, (char *) b->pos, b->last - b->pos);
return 1;
*data_p = b->pos;
*len_p = b->last - b->pos;
return NGX_OK;
}
dd("seen multiple buffers");
@ -463,7 +462,26 @@ ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r)
}
}
data = (u_char *) lua_newuserdata(L, size);
/* the buf is need and is not allocated from Lua land yet, return with
* the actual size */
*len_p = size;
return NGX_AGAIN;
}
int
ngx_http_lua_ffi_copy_body_filter_param_body(ngx_http_request_t *r,
u_char *data)
{
u_char *p;
ngx_chain_t *cl;
ngx_buf_t *b;
ngx_chain_t *in;
ngx_http_lua_main_conf_t *lmcf;
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
in = lmcf->body_filter_chain;
for (p = data, cl = in; cl; cl = cl->next) {
b = cl->buf;
@ -474,8 +492,7 @@ ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r)
}
}
lua_pushlstring(L, (char *) data, size);
return 1;
return NGX_OK;
}
@ -640,6 +657,7 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r,
return luaL_error(L, "no memory");
}
cl->buf->tag = (ngx_buf_tag_t) &ngx_http_lua_body_filter;
if (type == LUA_TTABLE) {
cl->buf->last = ngx_http_lua_copy_str_in_table(L, 3, cl->buf->last);
@ -657,6 +675,8 @@ done:
if (cl == NULL) {
return luaL_error(L, "no memory");
}
cl->buf->tag = (ngx_buf_tag_t) &ngx_http_lua_body_filter;
}
if (last) {

View File

@ -21,7 +21,6 @@ ngx_int_t ngx_http_lua_body_filter_inline(ngx_http_request_t *r,
ngx_chain_t *in);
ngx_int_t ngx_http_lua_body_filter_file(ngx_http_request_t *r,
ngx_chain_t *in);
int ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r);
int ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r,
ngx_http_lua_ctx_t *ctx);

View File

@ -307,7 +307,13 @@ ngx_http_lua_cache_loadfile(ngx_log_t *log, lua_State *L,
break;
case LUA_ERRFILE:
errcode = NGX_HTTP_NOT_FOUND;
if (errno == ENOENT) {
errcode = NGX_HTTP_NOT_FOUND;
} else {
errcode = NGX_HTTP_SERVICE_UNAVAILABLE;
}
/* fall through */
default:

View File

@ -31,6 +31,7 @@ typedef struct {
size_t size;
int ref;
u_char *key;
u_char *chunkname;
ngx_str_t script;
} ngx_http_lua_set_var_data_t;
#endif
@ -140,6 +141,7 @@ typedef struct {
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x1000
#define NGX_HTTP_LUA_CONTEXT_EXIT_WORKER 0x2000
#define NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO 0x4000
#define NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE 0x8000
#define NGX_HTTP_LUA_FFI_NO_REQ_CTX -100
@ -213,6 +215,8 @@ struct ngx_http_lua_main_conf_s {
ngx_int_t lua_thread_cache_max_entries;
ngx_hash_t builtin_headers_out;
#if (NGX_PCRE)
ngx_int_t regex_cache_entries;
ngx_int_t regex_cache_max_entries;
@ -233,12 +237,15 @@ struct ngx_http_lua_main_conf_s {
ngx_http_lua_main_conf_handler_pt init_handler;
ngx_str_t init_src;
u_char *init_chunkname;
ngx_http_lua_main_conf_handler_pt init_worker_handler;
ngx_str_t init_worker_src;
u_char *init_worker_chunkname;
ngx_http_lua_main_conf_handler_pt exit_worker_handler;
ngx_str_t exit_worker_src;
u_char *exit_worker_chunkname;
ngx_http_lua_balancer_peer_data_t *balancer_peer_data;
/* neither yielding nor recursion is possible in
@ -276,6 +283,8 @@ struct ngx_http_lua_main_conf_s {
of requests */
ngx_uint_t malloc_trim_req_count;
ngx_uint_t directive_line;
#if (nginx_version >= 1011011)
/* the following 2 fields are only used by ngx.req.raw_headers() for now */
ngx_buf_t **busy_buf_ptrs;
@ -299,38 +308,50 @@ struct ngx_http_lua_main_conf_s {
unsigned requires_log:1;
unsigned requires_shm:1;
unsigned requires_capture_log:1;
unsigned requires_server_rewrite:1;
};
union ngx_http_lua_srv_conf_u {
#if (NGX_HTTP_SSL)
struct {
#if (NGX_HTTP_SSL)
ngx_http_lua_srv_conf_handler_pt ssl_cert_handler;
ngx_str_t ssl_cert_src;
u_char *ssl_cert_src_key;
u_char *ssl_cert_chunkname;
int ssl_cert_src_ref;
ngx_http_lua_srv_conf_handler_pt ssl_sess_store_handler;
ngx_str_t ssl_sess_store_src;
u_char *ssl_sess_store_src_key;
u_char *ssl_sess_store_chunkname;
int ssl_sess_store_src_ref;
ngx_http_lua_srv_conf_handler_pt ssl_sess_fetch_handler;
ngx_str_t ssl_sess_fetch_src;
u_char *ssl_sess_fetch_src_key;
u_char *ssl_sess_fetch_chunkname;
int ssl_sess_fetch_src_ref;
ngx_http_lua_srv_conf_handler_pt ssl_client_hello_handler;
ngx_str_t ssl_client_hello_src;
u_char *ssl_client_hello_src_key;
u_char *ssl_client_hello_chunkname;
int ssl_client_hello_src_ref;
} srv;
#endif
ngx_http_lua_srv_conf_handler_pt server_rewrite_handler;
ngx_http_complex_value_t server_rewrite_src;
u_char *server_rewrite_src_key;
u_char *server_rewrite_chunkname;
int server_rewrite_src_ref;
} srv;
struct {
ngx_http_lua_srv_conf_handler_pt handler;
ngx_str_t src;
u_char *src_key;
u_char *chunkname;
int src_ref;
} balancer;
};
@ -365,6 +386,8 @@ typedef struct {
ngx_http_output_body_filter_pt body_filter_handler;
u_char *rewrite_chunkname;
ngx_http_complex_value_t rewrite_src; /* rewrite_by_lua
inline script/script
@ -401,6 +424,7 @@ typedef struct {
inline script/script
file path */
u_char *header_filter_chunkname;
u_char *header_filter_src_key;
/* cached key for header_filter_src */
int header_filter_src_ref;
@ -408,6 +432,7 @@ typedef struct {
ngx_http_complex_value_t body_filter_src;
u_char *body_filter_src_key;
u_char *body_filter_chunkname;
int body_filter_src_ref;
ngx_msec_t keepalive_timeout;
@ -620,7 +645,7 @@ typedef struct ngx_http_lua_ctx_s {
response headers */
unsigned mime_set:1; /* whether the user has set Content-Type
response header */
unsigned entered_server_rewrite_phase:1;
unsigned entered_rewrite_phase:1;
unsigned entered_access_phase:1;
unsigned entered_content_phase:1;

View File

@ -176,6 +176,10 @@ ngx_http_lua_inject_http_consts(lua_State *L)
lua_pushinteger(L, NGX_HTTP_INTERNAL_SERVER_ERROR);
lua_setfield(L, -2, "HTTP_INTERNAL_SERVER_ERROR");
lua_pushinteger(L, NGX_HTTP_NOT_IMPLEMENTED);
lua_setfield(L, -2, "HTTP_NOT_IMPLEMENTED");
/* keep for backward compatibility */
lua_pushinteger(L, NGX_HTTP_NOT_IMPLEMENTED);
lua_setfield(L, -2, "HTTP_METHOD_NOT_IMPLEMENTED");

View File

@ -91,6 +91,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_CONTENT);
@ -232,6 +233,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_CONTENT);
@ -358,6 +360,14 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
{
ngx_http_lua_ctx_t *ctx;
if (status == NGX_AGAIN || status == NGX_DONE) {
*errlen = ngx_snprintf(err, *errlen,
"bad argument to 'ngx.exit': does not accept "
"NGX_AGAIN or NGX_DONE")
- err;
return NGX_ERROR;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
*errlen = ngx_snprintf(err, *errlen, "no request ctx found") - err;
@ -365,6 +375,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_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER

View File

@ -17,6 +17,7 @@
#include "ngx_http_lua_cache.h"
#include "ngx_http_lua_contentby.h"
#include "ngx_http_lua_accessby.h"
#include "ngx_http_lua_server_rewriteby.h"
#include "ngx_http_lua_rewriteby.h"
#include "ngx_http_lua_logby.h"
#include "ngx_http_lua_headerfilterby.h"
@ -32,6 +33,12 @@
#include "ngx_http_lua_log.h"
/* the max length is 60, after deducting the fixed four characters "=(:)"
* only 56 left.
*/
#define LJ_CHUNKNAME_MAX_LEN 56
typedef struct ngx_http_lua_block_parser_ctx_s
ngx_http_lua_block_parser_ctx_t;
@ -43,8 +50,6 @@ typedef struct ngx_http_lua_block_parser_ctx_s
static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r);
#endif
static u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag,
size_t tag_len, size_t *chunkname_len);
static ngx_int_t ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf,
ngx_http_lua_block_parser_ctx_t *ctx);
static u_char *ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2,
@ -280,6 +285,8 @@ ngx_http_lua_set_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
char *
ngx_http_lua_set_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key;
ngx_str_t *value;
ngx_str_t target;
@ -312,7 +319,15 @@ ngx_http_lua_set_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "set_by_lua",
sizeof("set_by_lua") - 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
filter_data->key = cache_key;
filter_data->chunkname = chunkname;
filter_data->ref = LUA_REFNIL;
filter_data->script = value[2];
filter_data->size = filter.size;
@ -375,6 +390,7 @@ ngx_http_lua_set_by_lua_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
filter_data->key = cache_key;
filter_data->ref = LUA_REFNIL;
filter_data->size = filter.size;
filter_data->chunkname = NULL;
ngx_str_null(&filter_data->script);
@ -404,7 +420,8 @@ ngx_http_lua_filter_set_by_lua_inline(ngx_http_request_t *r, ngx_str_t *val,
filter_data->script.data,
filter_data->script.len,
&filter_data->ref,
filter_data->key, "=set_by_lua");
filter_data->key,
(const char *) filter_data->chunkname);
if (rc != NGX_OK) {
return NGX_ERROR;
}
@ -574,6 +591,111 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
char *
ngx_http_lua_server_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_server_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_server_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
size_t chunkname_len;
u_char *cache_key = NULL, *chunkname;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_srv_conf_t *lscf = conf;
ngx_http_compile_complex_value_t ccv;
dd("enter");
/* must specify a content handler */
if (cmd->post == NULL) {
return NGX_CONF_ERROR;
}
if (lscf->srv.server_rewrite_handler) {
return "is duplicate";
}
value = cf->args->elts;
if (value[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;
}
if (cmd->post == ngx_http_lua_server_rewrite_handler_inline) {
chunkname =
ngx_http_lua_gen_chunk_name(cf, "server_rewrite_by_lua",
sizeof("server_rewrite_by_lua") - 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
cache_key =
ngx_http_lua_gen_chunk_cache_key(cf, "server_rewrite_by_lua",
value[1].data,
value[1].len);
if (cache_key == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->srv.server_rewrite_src.value = value[1];
lscf->srv.server_rewrite_chunkname = chunkname;
} else {
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &value[1];
ccv.complex_value = &lscf->srv.server_rewrite_src;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (lscf->srv.server_rewrite_src.lengths == NULL) {
/* no variable found */
cache_key = ngx_http_lua_gen_file_cache_key(cf, value[1].data,
value[1].len);
if (cache_key == NULL) {
return NGX_CONF_ERROR;
}
}
}
lscf->srv.server_rewrite_src_key = cache_key;
lscf->srv.server_rewrite_handler =
(ngx_http_lua_srv_conf_handler_pt) cmd->post;
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
lmcf->requires_server_rewrite = 1;
lmcf->requires_capture_filter = 1;
return NGX_CONF_OK;
}
char *
ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
@ -912,7 +1034,8 @@ char *
ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
u_char *cache_key = NULL;
size_t chunkname_len;
u_char *cache_key = NULL, *chunkname;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_loc_conf_t *llcf = conf;
@ -947,8 +1070,15 @@ ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "header_filter_by_lua",
sizeof("header_filter_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
llcf->header_filter_src.value = value[1];
llcf->header_filter_chunkname = chunkname;
} else {
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
@ -1004,7 +1134,8 @@ char *
ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
u_char *cache_key = NULL;
size_t chunkname_len;
u_char *cache_key = NULL, *chunkname;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_loc_conf_t *llcf = conf;
@ -1039,8 +1170,16 @@ ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "body_filter_by_lua",
sizeof("body_filter_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
llcf->body_filter_src.value = value[1];
llcf->body_filter_chunkname = chunkname;
} else {
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
@ -1100,6 +1239,8 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
u_char *name;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf = conf;
size_t chunkname_len;
u_char *chunkname;
dd("enter");
@ -1135,6 +1276,15 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
} else {
lmcf->init_src = value[1];
chunkname = ngx_http_lua_gen_chunk_name(cf, "init_by_lua",
sizeof("init_by_lua") - 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
lmcf->init_chunkname = chunkname;
}
return NGX_CONF_OK;
@ -1167,6 +1317,8 @@ ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
u_char *name;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf = conf;
size_t chunkname_len;
u_char *chunkname;
dd("enter");
@ -1195,6 +1347,14 @@ ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
} else {
lmcf->init_worker_src = value[1];
chunkname = ngx_http_lua_gen_chunk_name(cf, "init_worker_by_lua",
sizeof("init_worker_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
lmcf->init_worker_chunkname = chunkname;
}
return NGX_CONF_OK;
@ -1227,6 +1387,8 @@ ngx_http_lua_exit_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
u_char *name;
ngx_str_t *value;
ngx_http_lua_main_conf_t *lmcf = conf;
size_t chunkname_len;
u_char *chunkname;
/* must specify a content handler */
if (cmd->post == NULL) {
@ -1253,6 +1415,15 @@ ngx_http_lua_exit_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
} else {
lmcf->exit_worker_src = value[1];
chunkname = ngx_http_lua_gen_chunk_name(cf, "exit_worker_by_lua",
sizeof("exit_worker_by_lua")- 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
lmcf->exit_worker_chunkname = chunkname;
}
return NGX_CONF_OK;
@ -1296,12 +1467,20 @@ ngx_http_lua_set_by_lua_init(ngx_http_request_t *r)
#endif
static u_char *
u_char *
ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag, size_t tag_len,
size_t *chunkname_len)
{
u_char *p, *out;
size_t len;
ngx_uint_t start_line;
ngx_str_t *conf_prefix;
ngx_str_t *filename;
u_char *filename_end;
const char *pre_str = "";
ngx_uint_t reserve_len;
ngx_http_lua_main_conf_t *lmcf;
len = sizeof("=(:)") - 1 + tag_len + cf->conf_file->file.name.len
+ NGX_INT64_LEN + 1;
@ -1311,27 +1490,56 @@ ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag, size_t tag_len,
return NULL;
}
if (cf->conf_file->file.name.len) {
p = cf->conf_file->file.name.data + cf->conf_file->file.name.len;
while (--p >= cf->conf_file->file.name.data) {
if (*p == '/' || *p == '\\') {
p++;
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
start_line = lmcf->directive_line > 0
? lmcf->directive_line : cf->conf_file->line;
p = ngx_snprintf(out, len, "%d", start_line);
reserve_len = tag_len + p - out;
filename = &cf->conf_file->file.name;
filename_end = filename->data + filename->len;
if (filename->len > 0) {
if (filename->len >= 11) {
p = filename_end - 11;
if ((*p == '/' || *p == '\\')
&& ngx_memcmp(p, "/nginx.conf", 11) == 0)
{
p++; /* now p is nginx.conf */
goto found;
}
}
p++;
conf_prefix = &cf->cycle->conf_prefix;
p = filename->data + conf_prefix->len;
if ((conf_prefix->len < filename->len)
&& ngx_memcmp(conf_prefix->data,
filename->data, conf_prefix->len) == 0)
{
/* files in conf_prefix directory, use the relative path */
if (filename_end - p + reserve_len > LJ_CHUNKNAME_MAX_LEN) {
p = filename_end - LJ_CHUNKNAME_MAX_LEN + reserve_len + 3;
pre_str = "...";
}
} else {
p = cf->conf_file->file.name.data;
goto found;
}
}
p = filename->data;
if (filename->len + reserve_len <= LJ_CHUNKNAME_MAX_LEN) {
goto found;
}
p = filename_end - LJ_CHUNKNAME_MAX_LEN + reserve_len + 3;
pre_str = "...";
found:
p = ngx_snprintf(out, len, "=%*s(%*s:%d)%Z",
tag_len, tag, cf->conf_file->file.name.data
+ cf->conf_file->file.name.len - p,
p, cf->conf_file->line);
p = ngx_snprintf(out, len, "=%*s(%s%*s:%d)%Z",
tag_len, tag, pre_str, filename_end - p,
p, start_line);
*chunkname_len = p - out - 1; /* exclude the trailing '\0' byte */
@ -1343,6 +1551,7 @@ found:
char *
ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd)
{
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_block_parser_ctx_t ctx;
int level = 1;
@ -1376,6 +1585,9 @@ ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd)
ctx.token_len = 0;
start_line = cf->conf_file->line;
lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
lmcf->directive_line = start_line;
dd("init start line: %d", (int) start_line);
ctx.start_line = start_line;
@ -1494,6 +1706,8 @@ failed:
done:
lmcf->directive_line = 0;
if (rc == NGX_ERROR) {
return NGX_CONF_ERROR;
}

View File

@ -25,6 +25,10 @@ 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_server_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
char *ngx_http_lua_server_rewrite_by_lua_block(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,
@ -81,7 +85,8 @@ char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf,
ngx_command_t *cmd);
char *ngx_http_lua_capture_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag,
size_t tag_len, size_t *chunkname_len);
#endif /* _NGX_HTTP_LUA_DIRECTIVE_H_INCLUDED_ */

View File

@ -95,9 +95,17 @@ ngx_http_lua_exit_worker_by_inline(ngx_log_t *log,
ngx_http_lua_main_conf_t *lmcf, lua_State *L)
{
int status;
const char *chunkname;
if (lmcf->exit_worker_chunkname == NULL) {
chunkname = "=exit_worker_by_lua";
} else {
chunkname = (const char *) lmcf->exit_worker_chunkname;
}
status = luaL_loadbuffer(L, (char *) lmcf->exit_worker_src.data,
lmcf->exit_worker_src.len, "=exit_worker_by_lua")
lmcf->exit_worker_src.len, chunkname)
|| ngx_http_lua_do_call(log, L);
return ngx_http_lua_report(log, L, status, "exit_worker_by_lua");

View File

@ -171,7 +171,8 @@ ngx_http_lua_header_filter_inline(ngx_http_request_t *r)
llcf->header_filter_src.value.len,
&llcf->header_filter_src_ref,
llcf->header_filter_src_key,
"=header_filter_by_lua");
(const char *)
llcf->header_filter_chunkname);
if (rc != NGX_OK) {
return NGX_ERROR;
}

View File

@ -84,6 +84,12 @@ ngx_http_lua_ngx_req_http_version(lua_State *L)
break;
#endif
#ifdef NGX_HTTP_VERSION_30
case NGX_HTTP_VERSION_30:
lua_pushnumber(L, 3.0);
break;
#endif
default:
lua_pushnil(L);
break;
@ -167,6 +173,12 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L)
size = 0;
b = c->buffer;
if (mr->request_line.len == 0) {
/* return empty string on invalid request */
lua_pushlstring(L, "", 0);
return 1;
}
if (mr->request_line.data[mr->request_line.len] == CR) {
line_break_len = 2;
@ -1068,6 +1080,7 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r,
{
int found;
u_char c, *p;
time_t last_modified;
ngx_uint_t i;
ngx_table_elt_t *h;
ngx_list_part_t *part;
@ -1134,6 +1147,28 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r,
break;
case 13:
if (ngx_strncasecmp(key_buf, (u_char *) "Last-Modified", 13) == 0) {
last_modified = r->headers_out.last_modified_time;
if (last_modified >= 0) {
p = ngx_palloc(r->pool,
sizeof("Mon, 28 Sep 1970 06:00:00 GMT"));
if (p == NULL) {
*errmsg = "no memory";
return NGX_ERROR;
}
values[0].data = p;
values[0].len = ngx_http_time(p, last_modified) - p;
return 1;
}
return 0;
}
break;
default:
break;
}
@ -1211,4 +1246,16 @@ ngx_http_lua_ngx_raw_header_cleanup(void *data)
#endif
#if (NGX_DARWIN)
int
ngx_http_lua_ffi_set_resp_header_macos(ngx_http_lua_set_resp_header_params_t *p)
{
return ngx_http_lua_ffi_set_resp_header(p->r, p->key_data, p->key_len,
p->is_nil, p->sval, p->sval_len,
p->mvals, p->mvals_len,
p->override, p->errmsg);
}
#endif
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -152,9 +152,15 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = {
ngx_http_set_builtin_header },
#endif
#if defined(nginx_version) && nginx_version >= 1023000
{ ngx_string("Cookie"),
offsetof(ngx_http_headers_in_t, cookie),
ngx_http_set_builtin_multi_header },
#else
{ ngx_string("Cookie"),
offsetof(ngx_http_headers_in_t, cookies),
ngx_http_set_builtin_multi_header },
#endif
{ ngx_null_string, 0, ngx_http_set_header }
};
@ -580,6 +586,45 @@ static ngx_int_t
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_lua_header_val_t *hv, ngx_str_t *value)
{
#if defined(nginx_version) && nginx_version >= 1023000
ngx_table_elt_t **headers, **ph, *h;
int nelts;
headers = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
if (!hv->no_override && *headers != NULL) {
nelts = 0;
for (h = *headers; h; h = h->next) {
nelts++;
}
*headers = NULL;
dd("clear multi-value headers: %d", nelts);
}
if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
return NGX_ERROR;
}
if (value->len == 0) {
return NGX_OK;
}
dd("new multi-value header: %p", h);
if (*headers) {
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
*ph = h;
} else {
*headers = h;
}
h->next = NULL;
return NGX_OK;
#else
ngx_array_t *headers;
ngx_table_elt_t **v, *h;
@ -626,6 +671,7 @@ ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
*v = h;
return NGX_OK;
#endif
}
@ -669,7 +715,13 @@ ngx_http_lua_set_input_header(ngx_http_request_t *r, ngx_str_t key,
return NGX_ERROR;
}
hv.hash = ngx_hash_key_lc(key.data, key.len);
if (value.len > 0) {
hv.hash = ngx_hash_key_lc(key.data, key.len);
} else {
hv.hash = 0;
}
hv.key = key;
hv.offset = 0;

View File

@ -311,6 +311,69 @@ static ngx_int_t
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
ngx_http_lua_header_val_t *hv, ngx_str_t *value)
{
#if defined(nginx_version) && nginx_version >= 1023000
ngx_table_elt_t **headers, *h, *ho, **ph;
headers = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
if (hv->no_override) {
for (h = *headers; h; h = h->next) {
if (!h->hash) {
h->value = *value;
h->hash = hv->hash;
return NGX_OK;
}
}
goto create;
}
/* override old values (if any) */
if (*headers) {
for (h = (*headers)->next; h; h = h->next) {
h->hash = 0;
h->value.len = 0;
}
h = *headers;
h->value = *value;
if (value->len == 0) {
h->hash = 0;
} else {
h->hash = hv->hash;
}
return NGX_OK;
}
create:
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
ho = ngx_list_push(&r->headers_out.headers);
if (ho == NULL) {
return NGX_ERROR;
}
ho->value = *value;
if (value->len == 0) {
ho->hash = 0;
} else {
ho->hash = hv->hash;
}
ho->key = hv->key;
ho->next = NULL;
*ph = ho;
return NGX_OK;
#else
ngx_array_t *pa;
ngx_table_elt_t *ho, **ph;
ngx_uint_t i;
@ -384,6 +447,7 @@ create:
*ph = ho;
return NGX_OK;
#endif
}
@ -486,8 +550,9 @@ ngx_http_lua_set_output_header(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx,
ngx_str_t key, ngx_str_t value, unsigned override)
{
ngx_http_lua_header_val_t hv;
ngx_http_lua_set_header_t *handlers = ngx_http_lua_set_handlers;
ngx_uint_t i;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_set_header_t *lsh;
ngx_hash_t *hash;
dd("set header value: %.*s", (int) value.len, value.data);
@ -504,42 +569,20 @@ ngx_http_lua_set_output_header(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx,
hv.offset = 0;
hv.no_override = !override;
hv.handler = NULL;
for (i = 0; handlers[i].name.len; i++) {
if (hv.key.len != handlers[i].name.len
|| ngx_strncasecmp(hv.key.data, handlers[i].name.data,
handlers[i].name.len) != 0)
{
dd("hv key comparison: %s <> %s", handlers[i].name.data,
hv.key.data);
continue;
}
dd("Matched handler: %s %s", handlers[i].name.data, hv.key.data);
hv.offset = handlers[i].offset;
hv.handler = handlers[i].handler;
hv.handler = ngx_http_set_header;
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
hash = &lmcf->builtin_headers_out;
lsh = ngx_http_lua_hash_find_lc(hash, hv.hash, hv.key.data, hv.key.len);
if (lsh) {
dd("Matched handler: %s %s", lsh->name.data, hv.key.data);
hv.offset = lsh->offset;
hv.handler = lsh->handler;
if (hv.handler == ngx_http_set_content_type_header) {
ctx->mime_set = 1;
}
break;
}
if (handlers[i].name.len == 0 && handlers[i].handler) {
hv.offset = handlers[i].offset;
hv.handler = handlers[i].handler;
}
#if 1
if (hv.handler == NULL) {
return NGX_ERROR;
}
#endif
return hv.handler(r, &hv, &value);
}
@ -652,4 +695,48 @@ ngx_http_lua_get_output_header(lua_State *L, ngx_http_request_t *r,
return 1;
}
ngx_int_t
ngx_http_lua_init_builtin_headers_out(ngx_conf_t *cf,
ngx_http_lua_main_conf_t *lmcf)
{
ngx_array_t headers;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
ngx_http_lua_set_header_t *handlers = ngx_http_lua_set_handlers;
ngx_uint_t count;
count = sizeof(ngx_http_lua_set_handlers)
/ sizeof(ngx_http_lua_set_header_t);
if (ngx_array_init(&headers, cf->temp_pool, count, sizeof(ngx_hash_key_t))
!= NGX_OK)
{
return NGX_ERROR;
}
while (handlers->name.data) {
hk = ngx_array_push(&headers);
if (hk == NULL) {
return NGX_ERROR;
}
hk->key = handlers->name;
hk->key_hash = ngx_hash_key_lc(handlers->name.data, handlers->name.len);
hk->value = (void *) handlers;
handlers++;
}
hash.hash = &lmcf->builtin_headers_out;
hash.key = ngx_hash_key_lc;
hash.max_size = 512;
hash.bucket_size = ngx_align(64, ngx_cacheline_size);
hash.name = "builtin_headers_out_hash";
hash.pool = cf->pool;
hash.temp_pool = NULL;
return ngx_hash_init(&hash, headers.elts, headers.nelts);
}
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -12,10 +12,28 @@
#include "ngx_http_lua_common.h"
#if (NGX_DARWIN)
typedef struct {
ngx_http_request_t *r;
const char *key_data;
size_t key_len;
int is_nil;
const char *sval;
size_t sval_len;
void *mvals;
size_t mvals_len;
int override;
char **errmsg;
} ngx_http_lua_set_resp_header_params_t;
#endif
ngx_int_t ngx_http_lua_set_output_header(ngx_http_request_t *r,
ngx_http_lua_ctx_t *ctx, ngx_str_t key, ngx_str_t value, unsigned override);
int ngx_http_lua_get_output_header(lua_State *L, ngx_http_request_t *r,
ngx_http_lua_ctx_t *ctx, ngx_str_t *key);
ngx_int_t ngx_http_lua_init_builtin_headers_out(ngx_conf_t *cf,
ngx_http_lua_main_conf_t *lmcf);
#endif /* _NGX_HTTP_LUA_HEADERS_OUT_H_INCLUDED_ */

View File

@ -18,9 +18,18 @@ ngx_http_lua_init_by_inline(ngx_log_t *log, ngx_http_lua_main_conf_t *lmcf,
lua_State *L)
{
int status;
const char *chunkname;
if (lmcf->init_chunkname == NULL) {
chunkname = "=init_by_lua";
} else {
chunkname = (const char *) lmcf->init_chunkname;
}
status = luaL_loadbuffer(L, (char *) lmcf->init_src.data,
lmcf->init_src.len, "=init_by_lua")
lmcf->init_src.len, chunkname)
|| ngx_http_lua_do_call(log, L);
return ngx_http_lua_report(log, L, status, "init_by_lua");

View File

@ -118,14 +118,15 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle)
ngx_queue_init(&fake_cycle->reusable_connections_queue);
if (ngx_array_init(&fake_cycle->listening, cycle->pool,
cycle->listening.nelts || 1,
cycle->listening.nelts ? cycle->listening.nelts : 1,
sizeof(ngx_listening_t))
!= NGX_OK)
{
goto failed;
}
if (ngx_array_init(&fake_cycle->paths, cycle->pool, cycle->paths.nelts || 1,
if (ngx_array_init(&fake_cycle->paths, cycle->pool,
cycle->paths.nelts ? cycle->paths.nelts : 1,
sizeof(ngx_path_t *))
!= NGX_OK)
{
@ -135,7 +136,8 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle)
part = &cycle->open_files.part;
ofile = part->elts;
if (ngx_list_init(&fake_cycle->open_files, cycle->pool, part->nelts || 1,
if (ngx_list_init(&fake_cycle->open_files, cycle->pool,
part->nelts ? part->nelts : 1,
sizeof(ngx_open_file_t))
!= NGX_OK)
{
@ -317,9 +319,17 @@ ngx_http_lua_init_worker_by_inline(ngx_log_t *log,
ngx_http_lua_main_conf_t *lmcf, lua_State *L)
{
int status;
const char *chunkname;
if (lmcf->init_worker_chunkname == NULL) {
chunkname = "=init_worker_by_lua";
} else {
chunkname = (const char *) lmcf->init_worker_chunkname;
}
status = luaL_loadbuffer(L, (char *) lmcf->init_worker_src.data,
lmcf->init_worker_src.len, "=init_worker_by_lua")
lmcf->init_worker_src.len, chunkname)
|| ngx_http_lua_do_call(log, L);
return ngx_http_lua_report(log, L, status, "init_worker_by_lua");

View File

@ -99,6 +99,17 @@ ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int status)
}
int
ngx_http_lua_ffi_req_is_internal(ngx_http_request_t *r)
{
if (r->connection->fd == (ngx_socket_t) -1) {
return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
}
return r->internal;
}
int
ngx_http_lua_ffi_is_subrequest(ngx_http_request_t *r)
{

View File

@ -14,6 +14,7 @@
#include "ngx_http_lua_directive.h"
#include "ngx_http_lua_capturefilter.h"
#include "ngx_http_lua_contentby.h"
#include "ngx_http_lua_server_rewriteby.h"
#include "ngx_http_lua_rewriteby.h"
#include "ngx_http_lua_accessby.h"
#include "ngx_http_lua_logby.h"
@ -31,6 +32,7 @@
#include "ngx_http_lua_ssl_session_storeby.h"
#include "ngx_http_lua_ssl_session_fetchby.h"
#include "ngx_http_lua_headers.h"
#include "ngx_http_lua_headers_out.h"
#include "ngx_http_lua_pipe.h"
@ -290,6 +292,22 @@ static ngx_command_t ngx_http_lua_cmds[] = {
(void *) ngx_http_lua_filter_set_by_lua_file },
#endif
/* server_rewrite_by_lua_block { <inline script> } */
{ ngx_string("server_rewrite_by_lua_block"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_lua_server_rewrite_by_lua_block,
NGX_HTTP_SRV_CONF_OFFSET,
0,
(void *) ngx_http_lua_server_rewrite_handler_inline },
/* server_rewrite_by_lua_file filename; */
{ ngx_string("server_rewrite_by_lua_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_lua_server_rewrite_by_lua,
NGX_HTTP_SRV_CONF_OFFSET,
0,
(void *) ngx_http_lua_server_rewrite_handler_file },
/* 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
@ -752,6 +770,16 @@ ngx_http_lua_init(ngx_conf_t *cf)
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
if (lmcf->requires_server_rewrite) {
h = ngx_array_push(
&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_lua_server_rewrite_handler;
}
if (lmcf->requires_rewrite) {
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
if (h == NULL) {
@ -1086,6 +1114,15 @@ ngx_http_lua_init_main_conf(ngx_conf_t *cf, void *conf)
lmcf->worker_thread_vm_pool_size = 100;
}
if (ngx_http_lua_init_builtin_headers_out(cf, lmcf) != NGX_OK) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "init header out error");
return NGX_CONF_ERROR;
}
dd("init built in headers out hash size: %ld",
lmcf->builtin_headers_out.size);
return NGX_CONF_OK;
}
@ -1103,22 +1140,27 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf)
/* set by ngx_pcalloc:
* lscf->srv.ssl_client_hello_handler = NULL;
* lscf->srv.ssl_client_hello_src = { 0, NULL };
* lscf->srv.ssl_client_hello_chunkname = NULL;
* lscf->srv.ssl_client_hello_src_key = NULL;
*
* lscf->srv.ssl_cert_handler = NULL;
* lscf->srv.ssl_cert_src = { 0, NULL };
* lscf->srv.ssl_cert_chunkname = NULL;
* lscf->srv.ssl_cert_src_key = NULL;
*
* lscf->srv.ssl_session_store_handler = NULL;
* lscf->srv.ssl_session_store_src = { 0, NULL };
* lscf->srv.ssl_session_store_chunkname = NULL;
* lscf->srv.ssl_session_store_src_key = NULL;
*
* lscf->srv.ssl_session_fetch_handler = NULL;
* lscf->srv.ssl_session_fetch_src = { 0, NULL };
* lscf->srv.ssl_session_fetch_chunkname = NULL;
* lscf->srv.ssl_session_fetch_src_key = NULL;
*
* lscf->balancer.handler = NULL;
* lscf->balancer.src = { 0, NULL };
* lscf->balancer.chunkname = NULL;
* lscf->balancer.src_key = NULL;
*/
@ -1138,10 +1180,11 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf)
static char *
ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_lua_srv_conf_t *conf = child;
ngx_http_lua_srv_conf_t *prev = parent;
#if (NGX_HTTP_SSL)
ngx_http_lua_srv_conf_t *prev = parent;
ngx_http_lua_srv_conf_t *conf = child;
ngx_http_ssl_srv_conf_t *sscf;
dd("merge srv conf");
@ -1151,6 +1194,8 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
conf->srv.ssl_client_hello_src_ref = prev->srv.ssl_client_hello_src_ref;
conf->srv.ssl_client_hello_src_key = prev->srv.ssl_client_hello_src_key;
conf->srv.ssl_client_hello_handler = prev->srv.ssl_client_hello_handler;
conf->srv.ssl_client_hello_chunkname
= prev->srv.ssl_client_hello_chunkname;
}
if (conf->srv.ssl_client_hello_src.len) {
@ -1190,6 +1235,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
conf->srv.ssl_cert_src_ref = prev->srv.ssl_cert_src_ref;
conf->srv.ssl_cert_src_key = prev->srv.ssl_cert_src_key;
conf->srv.ssl_cert_handler = prev->srv.ssl_cert_handler;
conf->srv.ssl_cert_chunkname = prev->srv.ssl_cert_chunkname;
}
if (conf->srv.ssl_cert_src.len) {
@ -1229,6 +1275,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
conf->srv.ssl_sess_store_src_ref = prev->srv.ssl_sess_store_src_ref;
conf->srv.ssl_sess_store_src_key = prev->srv.ssl_sess_store_src_key;
conf->srv.ssl_sess_store_handler = prev->srv.ssl_sess_store_handler;
conf->srv.ssl_sess_store_chunkname = prev->srv.ssl_sess_store_chunkname;
}
if (conf->srv.ssl_sess_store_src.len) {
@ -1252,6 +1299,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
conf->srv.ssl_sess_fetch_src_ref = prev->srv.ssl_sess_fetch_src_ref;
conf->srv.ssl_sess_fetch_src_key = prev->srv.ssl_sess_fetch_src_key;
conf->srv.ssl_sess_fetch_handler = prev->srv.ssl_sess_fetch_handler;
conf->srv.ssl_sess_fetch_chunkname = prev->srv.ssl_sess_fetch_chunkname;
}
if (conf->srv.ssl_sess_fetch_src.len) {
@ -1271,6 +1319,16 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
}
#endif /* NGX_HTTP_SSL */
if (conf->srv.server_rewrite_src.value.len == 0) {
conf->srv.server_rewrite_src = prev->srv.server_rewrite_src;
conf->srv.server_rewrite_src_ref = prev->srv.server_rewrite_src_ref;
conf->srv.server_rewrite_src_key = prev->srv.server_rewrite_src_key;
conf->srv.server_rewrite_handler = prev->srv.server_rewrite_handler;
conf->srv.server_rewrite_chunkname
= prev->srv.server_rewrite_chunkname;
}
return NGX_CONF_OK;
}
@ -1393,6 +1451,7 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->header_filter_handler = prev->header_filter_handler;
conf->header_filter_src_ref = prev->header_filter_src_ref;
conf->header_filter_src_key = prev->header_filter_src_key;
conf->header_filter_chunkname = prev->header_filter_chunkname;
}
if (conf->body_filter_src.value.len == 0) {
@ -1400,6 +1459,7 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->body_filter_handler = prev->body_filter_handler;
conf->body_filter_src_ref = prev->body_filter_src_ref;
conf->body_filter_src_key = prev->body_filter_src_key;
conf->body_filter_chunkname = prev->body_filter_chunkname;
}
#if (NGX_HTTP_SSL)

View File

@ -63,6 +63,7 @@ ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
}
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_CONTENT);
@ -499,6 +500,7 @@ ngx_http_lua_ngx_flush(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_CONTENT);
@ -653,6 +655,7 @@ ngx_http_lua_ngx_eof(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_CONTENT);
@ -715,6 +718,7 @@ ngx_http_lua_ngx_send_headers(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_CONTENT);

View File

@ -78,10 +78,15 @@ static void ngx_http_lua_pipe_proc_read_stdout_cleanup(void *data);
static void ngx_http_lua_pipe_proc_read_stderr_cleanup(void *data);
static void ngx_http_lua_pipe_proc_write_cleanup(void *data);
static void ngx_http_lua_pipe_proc_wait_cleanup(void *data);
static void ngx_http_lua_pipe_reap_pids(ngx_event_t *ev);
static void ngx_http_lua_pipe_reap_timer_handler(ngx_event_t *ev);
void ngx_http_lua_ffi_pipe_proc_destroy(
ngx_http_lua_ffi_pipe_proc_t *proc);
static ngx_rbtree_t ngx_http_lua_pipe_rbtree;
static ngx_rbtree_node_t ngx_http_lua_pipe_proc_sentinel;
static ngx_event_t ngx_reap_pid_event;
#if (NGX_HTTP_LUA_HAVE_SIGNALFD)
@ -160,6 +165,15 @@ ngx_http_lua_pipe_add_signal_handler(ngx_cycle_t *cycle)
struct sigaction sa;
#endif
ngx_reap_pid_event.handler = ngx_http_lua_pipe_reap_timer_handler;
ngx_reap_pid_event.log = cycle->log;
ngx_reap_pid_event.data = cycle;
ngx_reap_pid_event.cancelable = 1;
if (!ngx_reap_pid_event.timer_set) {
ngx_add_timer(&ngx_reap_pid_event, 1000);
}
#if (NGX_HTTP_LUA_HAVE_SIGNALFD)
if (sigemptyset(&set) != 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
@ -351,11 +365,7 @@ static void
ngx_http_lua_pipe_sigchld_event_handler(ngx_event_t *ev)
{
int n;
int status;
ngx_pid_t pid;
ngx_connection_t *c = ev->data;
ngx_rbtree_node_t *node;
ngx_http_lua_pipe_node_t *pipe_node;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
"lua pipe reaping children");
@ -377,72 +387,99 @@ ngx_http_lua_pipe_sigchld_event_handler(ngx_event_t *ev)
break;
}
for ( ;; ) {
pid = waitpid(-1, &status, WNOHANG);
ngx_http_lua_pipe_reap_pids(ev);
}
}
if (pid == 0) {
break;
static void
ngx_http_lua_pipe_reap_pids(ngx_event_t *ev)
{
int status;
ngx_pid_t pid;
ngx_rbtree_node_t *node;
ngx_http_lua_pipe_node_t *pipe_node;
for ( ;; ) {
pid = waitpid(-1, &status, WNOHANG);
if (pid == 0) {
break;
}
if (pid < 0) {
if (ngx_errno != NGX_ECHILD) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
"lua pipe waitpid failed");
}
if (pid < 0) {
if (ngx_errno != NGX_ECHILD) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
"lua pipe waitpid failed");
}
break;
}
break;
/* This log is ported from Nginx's signal handler since we override
* or block it in this implementation. */
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
"signal %d (SIGCHLD) received from %P",
SIGCHLD, pid);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua pipe SIGCHLD fd read pid:%P status:%d", pid,
status);
node = ngx_http_lua_pipe_lookup_pid(pid);
if (node != NULL) {
pipe_node = (ngx_http_lua_pipe_node_t *) &node->color;
if (pipe_node->wait_co_ctx != NULL) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua pipe resume process:%p waiting for %P",
pipe_node->proc, pid);
/*
* We need the extra parentheses around the first argument
* of ngx_post_event() just to work around macro issues in
* nginx cores older than 1.7.12 (exclusive).
*/
ngx_post_event((&pipe_node->wait_co_ctx->sleep),
&ngx_posted_events);
}
/* This log is ported from Nginx's signal handler since we override
* or block it in this implementation. */
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
"signal %d (SIGCHLD) received from %P",
SIGCHLD, pid);
/* TODO: we should proactively close and free up the pipe after
* the user consume all the data in the pipe.
*/
pipe_node->proc->pipe->dead = 1;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua pipe SIGCHLD fd read pid:%P status:%d", pid,
status);
if (WIFSIGNALED(status)) {
pipe_node->status = WTERMSIG(status);
pipe_node->reason_code = REASON_SIGNAL_CODE;
node = ngx_http_lua_pipe_lookup_pid(pid);
if (node != NULL) {
pipe_node = (ngx_http_lua_pipe_node_t *) &node->color;
if (pipe_node->wait_co_ctx != NULL) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua pipe resume process:%p waiting for %P",
pipe_node->proc, pid);
} else if (WIFEXITED(status)) {
pipe_node->status = WEXITSTATUS(status);
pipe_node->reason_code = REASON_EXIT_CODE;
/*
* We need the extra parentheses around the first argument
* of ngx_post_event() just to work around macro issues in
* nginx cores older than 1.7.12 (exclusive).
*/
ngx_post_event((&pipe_node->wait_co_ctx->sleep),
&ngx_posted_events);
}
pipe_node->proc->pipe->dead = 1;
if (WIFSIGNALED(status)) {
pipe_node->status = WTERMSIG(status);
pipe_node->reason_code = REASON_SIGNAL_CODE;
} else if (WIFEXITED(status)) {
pipe_node->status = WEXITSTATUS(status);
pipe_node->reason_code = REASON_EXIT_CODE;
} else {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"lua pipe unknown exit status %d from "
"process %P", status, pid);
pipe_node->status = status;
pipe_node->reason_code = REASON_UNKNOWN_CODE;
}
} else {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"lua pipe unknown exit status %d from "
"process %P", status, pid);
pipe_node->status = status;
pipe_node->reason_code = REASON_UNKNOWN_CODE;
}
}
}
}
static void
ngx_http_lua_pipe_reap_timer_handler(ngx_event_t *ev)
{
ngx_http_lua_pipe_reap_pids(ev);
if (!ngx_exiting) {
ngx_add_timer(&ngx_reap_pid_event, 1000);
ngx_reap_pid_event.timedout = 0;
}
}
static ssize_t
ngx_http_lua_pipe_fd_read(ngx_connection_t *c, u_char *buf, size_t size)
{
@ -562,7 +599,8 @@ ngx_http_lua_execvpe(const char *program, char * const argv[],
int
ngx_http_lua_ffi_pipe_spawn(ngx_http_lua_ffi_pipe_proc_t *proc,
ngx_http_lua_ffi_pipe_spawn(ngx_http_request_t *r,
ngx_http_lua_ffi_pipe_proc_t *proc,
const char *file, const char **argv, int merge_stderr, size_t buffer_size,
const char **environ, u_char *errbuf, size_t *errbuf_size)
{
@ -582,6 +620,7 @@ ngx_http_lua_ffi_pipe_spawn(ngx_http_lua_ffi_pipe_proc_t *proc,
ngx_http_lua_pipe_node_t *pipe_node;
struct sigaction sa;
ngx_http_lua_pipe_signal_t *sig;
ngx_pool_cleanup_t *cln;
sigset_t set;
pool_size = ngx_align(NGX_MIN_POOL_SIZE + buffer_size * 2,
@ -773,10 +812,21 @@ ngx_http_lua_ffi_pipe_spawn(ngx_http_lua_ffi_pipe_proc_t *proc,
}
}
close(in[0]);
close(out[1]);
if (close(in[0]) == -1) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
"lua pipe failed to close the in[0]");
}
if (close(out[1]) == -1) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
"lua pipe failed to close the out[1]");
}
if (!merge_stderr) {
close(err[1]);
if (close(err[1]) == -1) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
"lua pipe failed to close the err[1]");
}
}
if (environ != NULL) {
@ -858,6 +908,21 @@ ngx_http_lua_ffi_pipe_spawn(ngx_http_lua_ffi_pipe_proc_t *proc,
pp->stderr_fd = stderr_fd;
}
if (pp->cleanup == NULL) {
cln = ngx_pool_cleanup_add(r->pool, 0);
if (cln == NULL) {
*errbuf_size = ngx_snprintf(errbuf, *errbuf_size, "no memory")
- errbuf;
goto close_in_out_err_fd;
}
cln->handler = (ngx_pool_cleanup_pt) ngx_http_lua_ffi_pipe_proc_destroy;
cln->data = proc;
pp->cleanup = &cln->handler;
pp->r = r;
}
node = (ngx_rbtree_node_t *) (pp + 1);
node->key = pid;
pipe_node = (ngx_http_lua_pipe_node_t *) &node->color;
@ -1128,6 +1193,12 @@ ngx_http_lua_ffi_pipe_proc_destroy(ngx_http_lua_ffi_pipe_proc_t *proc)
}
}
if (pipe->cleanup != NULL) {
*pipe->cleanup = NULL;
ngx_http_lua_cleanup_free(pipe->r, pipe->cleanup);
pipe->cleanup = NULL;
}
ngx_http_lua_pipe_proc_finalize(proc);
ngx_destroy_pool(pipe->pool);
proc->pipe = NULL;
@ -1141,7 +1212,7 @@ ngx_http_lua_pipe_get_lua_ctx(ngx_http_request_t *r,
int rc;
*ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
if (*ctx == NULL) {
return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
}

View File

@ -57,6 +57,8 @@ struct ngx_http_lua_pipe_s {
ngx_http_lua_pipe_ctx_t *stdout_ctx;
ngx_http_lua_pipe_ctx_t *stderr_ctx;
ngx_http_lua_pipe_retval_handler retval_handler;
ngx_http_cleanup_pt *cleanup;
ngx_http_request_t *r;
size_t buffer_size;
unsigned closed:1;
unsigned dead:1;

View File

@ -173,6 +173,8 @@ ngx_http_lua_ffi_set_jit_stack_size(int size, u_char *errstr,
lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle,
ngx_http_lua_module);
ngx_http_lua_assert(lmcf != NULL);
if (size < NGX_LUA_RE_MIN_JIT_STACK_SIZE) {
size = NGX_LUA_RE_MIN_JIT_STACK_SIZE;
}
@ -270,6 +272,8 @@ ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len,
lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle,
ngx_http_lua_module);
ngx_http_lua_assert(lmcf != NULL);
#if (LUA_HAVE_PCRE_JIT)
if (flags & NGX_LUA_RE_MODE_JIT) {

View File

@ -101,6 +101,7 @@ ngx_http_lua_ngx_req_read_body(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_CONTENT);

View File

@ -0,0 +1,339 @@
/*
* Copyright (C) Xiaozhe Wang (chaoslawful)
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include <nginx.h>
#include "ngx_http_lua_server_rewriteby.h"
#include "ngx_http_lua_util.h"
#include "ngx_http_lua_exception.h"
#include "ngx_http_lua_cache.h"
static ngx_int_t ngx_http_lua_server_rewrite_by_chunk(lua_State *L,
ngx_http_request_t *r);
ngx_int_t
ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
lua_State *L;
ngx_http_lua_srv_conf_t *lscf;
ngx_http_lua_loc_conf_t *llcf;
ngx_http_lua_ctx_t *ctx;
/* XXX we need to take into account ngx_rewrite's location dump */
if (r->uri_changed) {
return NGX_DECLINED;
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua server rewrite handler, uri:\"%V\" c:%ud", &r->uri,
r->main->count);
lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module);
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
L = ngx_http_lua_get_lua_vm(r, NULL);
if (lscf->srv.server_rewrite_handler == NULL) {
dd("no rewrite 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_http_lua_create_ctx(r);
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
dd("entered? %d", (int) ctx->entered_server_rewrite_phase);
if (ctx->entered_server_rewrite_phase) {
dd("rewriteby: calling wev handler");
rc = ctx->resume_handler(r);
dd("rewriteby: wev handler returns %d", (int) rc);
if (rc == NGX_OK) {
rc = NGX_DECLINED;
}
if (rc == NGX_DECLINED) {
if (r->header_sent) {
dd("header already sent");
/* response header was already generated in rewrite_by_lua*,
* so it is no longer safe to proceed to later phases
* which may generate responses again */
if (!ctx->eof) {
dd("eof not yet sent");
rc = ngx_http_lua_send_chain_link(r, ctx, NULL
/* indicate last_buf */);
if (rc == NGX_ERROR || rc > NGX_OK) {
return rc;
}
}
return NGX_HTTP_OK;
}
r->write_event_handler = ngx_http_core_run_phases;
ctx->entered_server_rewrite_phase = 0;
return NGX_DECLINED;
}
return rc;
}
if (ctx->waiting_more_body) {
return NGX_DONE;
}
/* TODO: lscf do not have force_read_body */
if (llcf->force_read_body && !ctx->read_body_done) {
r->request_body_in_single_buf = 1;
r->request_body_in_persistent_file = 1;
r->request_body_in_clean_file = 1;
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 server rewrite handler");
return lscf->srv.server_rewrite_handler(r, lscf, L);
}
ngx_int_t
ngx_http_lua_server_rewrite_handler_inline(ngx_http_request_t *r,
ngx_http_lua_srv_conf_t *lscf, lua_State *L)
{
ngx_int_t rc;
dd("server_rewrite by lua inline");
/* load Lua inline script (w/ cache) sp = 1 */
rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L,
lscf->srv.server_rewrite_src.value.data,
lscf->srv.server_rewrite_src.value.len,
&lscf->srv.server_rewrite_src_ref,
lscf->srv.server_rewrite_src_key,
(const char *)
lscf->srv.server_rewrite_chunkname);
if (rc != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return ngx_http_lua_server_rewrite_by_chunk(L, r);
}
ngx_int_t
ngx_http_lua_server_rewrite_handler_file(ngx_http_request_t *r,
ngx_http_lua_srv_conf_t *lscf, lua_State *L)
{
ngx_int_t rc;
u_char *script_path;
ngx_str_t eval_src;
if (ngx_http_complex_value(r, &lscf->srv.server_rewrite_src,
&eval_src) != NGX_OK)
{
return NGX_ERROR;
}
script_path = ngx_http_lua_rebase_path(r->pool, eval_src.data,
eval_src.len);
if (script_path == NULL) {
return NGX_ERROR;
}
/* load Lua script file (w/ cache) sp = 1 */
rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path,
&lscf->srv.server_rewrite_src_ref,
lscf->srv.server_rewrite_src_key);
if (rc != NGX_OK) {
if (rc < NGX_HTTP_SPECIAL_RESPONSE) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return rc;
}
return ngx_http_lua_server_rewrite_by_chunk(L, r);
}
static ngx_int_t
ngx_http_lua_server_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r)
{
int co_ref;
lua_State *co;
ngx_int_t rc;
ngx_uint_t nreqs;
ngx_event_t *rev;
ngx_connection_t *c;
ngx_http_lua_ctx_t *ctx;
ngx_http_cleanup_t *cln;
ngx_http_lua_loc_conf_t *llcf;
/* {{{ new coroutine to handle request */
co = ngx_http_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_HTTP_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_http_lua_get_globals_table(co);
lua_setfenv(co, -2);
#endif
/* save nginx request in coroutine globals table */
ngx_http_lua_set_req(co, r);
/* {{{ 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_server_rewrite_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_http_lua_attach_co_ctx_to_L(co, ctx->cur_co_ctx);
/* }}} */
/* {{{ 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_handler;
cln->data = ctx;
ctx->cleanup = &cln->handler;
}
/* }}} */
ctx->context = NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE;
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
if (llcf->check_client_abort) {
r->read_event_handler = ngx_http_lua_rd_check_broken_connection;
#if (NGX_HTTP_V2)
if (!r->stream) {
#endif
rev = r->connection->read;
if (!rev->active) {
if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
return NGX_ERROR;
}
}
#if (NGX_HTTP_V2)
}
#endif
} else {
r->read_event_handler = ngx_http_block_reading;
}
c = r->connection;
nreqs = c->requests;
rc = ngx_http_lua_run_thread(L, r, ctx, 0);
if (rc == NGX_ERROR || rc > NGX_OK) {
return rc;
}
if (rc == NGX_AGAIN) {
rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs);
} else if (rc == NGX_DONE) {
ngx_http_lua_finalize_request(r, NGX_DONE);
rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs);
}
if (rc == NGX_OK || rc == NGX_DECLINED) {
if (r->header_sent) {
dd("header already sent");
/* response header was already generated in rewrite_by_lua*,
* so it is no longer safe to proceed to later phases
* which may generate responses again */
if (!ctx->eof) {
dd("eof not yet sent");
rc = ngx_http_lua_send_chain_link(r, ctx, NULL
/* indicate last_buf */);
if (rc == NGX_ERROR || rc > NGX_OK) {
return rc;
}
}
return NGX_HTTP_OK;
}
r->write_event_handler = ngx_http_core_run_phases;
ctx->entered_server_rewrite_phase = 0;
return NGX_DECLINED;
}
return rc;
}
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -0,0 +1,20 @@
/*
* Copyright (C) Xiaozhe Wang (chaoslawful)
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef _NGX_HTTP_LUA_SERVER_REWRITEBY_H_INCLUDED_
#define _NGX_HTTP_LUA_SERVER_REWRITEBY_H_INCLUDED_
#include "ngx_http_lua_common.h"
ngx_int_t ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r);
ngx_int_t ngx_http_lua_server_rewrite_handler_inline(ngx_http_request_t *r,
ngx_http_lua_srv_conf_t *lscf, lua_State *L);
ngx_int_t ngx_http_lua_server_rewrite_handler_file(ngx_http_request_t *r,
ngx_http_lua_srv_conf_t *lscf, lua_State *L);
#endif /* _NGX_HTTP_LUA_SERVER_REWRITEBY_H_INCLUDED_ */
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -123,16 +123,15 @@ ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val,
}
int
ngx_http_lua_setby_param_get(lua_State *L, ngx_http_request_t *r)
void
ngx_http_lua_ffi_get_setby_param(ngx_http_request_t *r, int idx,
u_char **data_p, size_t *len_p)
{
int idx;
int n;
ngx_http_variable_value_t *v;
ngx_http_lua_main_conf_t *lmcf;
idx = luaL_checkint(L, 2);
idx--;
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
@ -144,13 +143,12 @@ ngx_http_lua_setby_param_get(lua_State *L, ngx_http_request_t *r)
v = lmcf->setby_args;
if (idx < 0 || idx > n - 1) {
lua_pushnil(L);
*len_p = 0;
} else {
lua_pushlstring(L, (const char *) (v[idx].data), v[idx].len);
*data_p = v[idx].data;
*len_p = v[idx].len;
}
return 1;
}

View File

@ -7,7 +7,6 @@
ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r,
ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs,
ngx_str_t *script);
int ngx_http_lua_setby_param_get(lua_State *L, ngx_http_request_t *r);
#endif /* _NGX_HTTP_LUA_SET_BY_H_INCLUDED_ */

View File

@ -943,7 +943,7 @@ push_node:
ngx_shmtx_unlock(&ctx->shpool->mutex);
lua_pushboolean(L, 0);
lua_pushnil(L);
lua_pushliteral(L, "no memory");
return 2;
}
@ -2092,4 +2092,38 @@ ngx_http_lua_ffi_shdict_free_space(ngx_shm_zone_t *zone)
#endif
#if (NGX_DARWIN)
int
ngx_http_lua_ffi_shdict_get_macos(ngx_http_lua_shdict_get_params_t *p)
{
return ngx_http_lua_ffi_shdict_get(p->zone, p->key, p->key_len,
p->value_type, p->str_value_buf,
p->str_value_len, p->num_value,
p->user_flags, p->get_stale,
p->is_stale, p->errmsg);
}
int
ngx_http_lua_ffi_shdict_store_macos(ngx_http_lua_shdict_store_params_t *p)
{
return ngx_http_lua_ffi_shdict_store(p->zone, p->op, p->key, p->key_len,
p->value_type, p->str_value_buf,
p->str_value_len, p->num_value,
p->exptime, p->user_flags,
p->errmsg, p->forcible);
}
int
ngx_http_lua_ffi_shdict_incr_macos(ngx_http_lua_shdict_incr_params_t *p)
{
return ngx_http_lua_ffi_shdict_incr(p->zone, p->key, p->key_len,
p->num_value, p->errmsg,
p->has_init, p->init, p->init_ttl,
p->forcible);
}
#endif
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -55,6 +55,52 @@ typedef struct {
} ngx_http_lua_shm_zone_ctx_t;
#if (NGX_DARWIN)
typedef struct {
void *zone;
const unsigned char *key;
size_t key_len;
int *value_type;
unsigned char **str_value_buf;
size_t *str_value_len;
double *num_value;
int *user_flags;
int get_stale;
int *is_stale;
char **errmsg;
} ngx_http_lua_shdict_get_params_t;
typedef struct {
void *zone;
int op;
const unsigned char *key;
size_t key_len;
int value_type;
const unsigned char *str_value_buf;
size_t str_value_len;
double num_value;
long exptime;
int user_flags;
char **errmsg;
int *forcible;
} ngx_http_lua_shdict_store_params_t;
typedef struct {
void *zone;
const unsigned char *key;
size_t key_len;
double *num_value;
char **errmsg;
int has_init;
double init;
long init_ttl;
int *forcible;
} ngx_http_lua_shdict_incr_params_t;
#endif
ngx_int_t ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data);
void ngx_http_lua_shdict_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);

View File

@ -20,9 +20,12 @@
static int ngx_http_lua_socket_tcp(lua_State *L);
static int ngx_http_lua_socket_tcp_bind(lua_State *L);
static int ngx_http_lua_socket_tcp_connect(lua_State *L);
#if (NGX_HTTP_SSL)
static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L);
static void ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c);
static int ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L);
#endif
static int ngx_http_lua_socket_tcp_receive(lua_State *L);
static int ngx_http_lua_socket_tcp_receiveany(lua_State *L);
@ -149,12 +152,6 @@ static void ngx_http_lua_socket_shutdown_pool_helper(
ngx_http_lua_socket_pool_t *spool);
static int ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L, ngx_uint_t ft_type);
#if (NGX_HTTP_SSL)
static int ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L);
static void ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c);
static int ngx_http_lua_ssl_free_session(lua_State *L);
#endif
static void ngx_http_lua_socket_tcp_close_connection(ngx_connection_t *c);
@ -164,14 +161,17 @@ enum {
SOCKET_CONNECT_TIMEOUT_INDEX = 2,
SOCKET_SEND_TIMEOUT_INDEX = 4,
SOCKET_READ_TIMEOUT_INDEX = 5,
SOCKET_CLIENT_CERT_INDEX = 6 ,
SOCKET_CLIENT_PKEY_INDEX = 7 ,
SOCKET_BIND_INDEX = 8 /* only in upstream cosocket */
};
enum {
SOCKET_OP_CONNECT,
SOCKET_OP_READ,
SOCKET_OP_WRITE,
SOCKET_OP_RESUME_CONN,
SOCKET_OP_CONNECT = 0x01,
SOCKET_OP_READ = 0x02,
SOCKET_OP_WRITE = 0x04,
SOCKET_OP_RESUME_CONN = 0x08,
};
@ -222,9 +222,6 @@ static char ngx_http_lua_upstream_udata_metatable_key;
static char ngx_http_lua_downstream_udata_metatable_key;
static char ngx_http_lua_pool_udata_metatable_key;
static char ngx_http_lua_pattern_udata_metatable_key;
#if (NGX_HTTP_SSL)
static char ngx_http_lua_ssl_session_metatable_key;
#endif
#define ngx_http_lua_tcp_socket_metatable_literal_key "__tcp_cosocket_mt"
@ -319,18 +316,14 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
/* {{{tcp object metatable */
lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask(
tcp_socket_metatable_key));
lua_createtable(L, 0 /* narr */, 14 /* nrec */);
lua_createtable(L, 0 /* narr */, 16 /* nrec */);
lua_pushcfunction(L, ngx_http_lua_socket_tcp_bind);
lua_setfield(L, -2, "bind");
lua_pushcfunction(L, ngx_http_lua_socket_tcp_connect);
lua_setfield(L, -2, "connect");
#if (NGX_HTTP_SSL)
lua_pushcfunction(L, ngx_http_lua_socket_tcp_sslhandshake);
lua_setfield(L, -2, "sslhandshake");
#endif
lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive);
lua_setfield(L, -2, "receive");
@ -404,19 +397,6 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
lua_setfield(L, -2, "__gc");
lua_rawset(L, LUA_REGISTRYINDEX);
/* }}} */
#if (NGX_HTTP_SSL)
/* {{{ssl session userdata metatable */
lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask(
ssl_session_metatable_key));
lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */
lua_pushcfunction(L, ngx_http_lua_ssl_free_session);
lua_setfield(L, -2, "__gc");
lua_rawset(L, LUA_REGISTRYINDEX);
/* }}} */
#endif
}
@ -451,7 +431,7 @@ ngx_http_lua_socket_tcp(lua_State *L)
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE);
lua_createtable(L, 5 /* narr */, 1 /* nrec */);
lua_createtable(L, 7 /* narr */, 1 /* nrec */);
lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask(
tcp_socket_metatable_key));
lua_rawget(L, LUA_REGISTRYINDEX);
@ -852,6 +832,61 @@ no_memory_and_not_resuming:
}
static int
ngx_http_lua_socket_tcp_bind(lua_State *L)
{
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
int n;
u_char *text;
size_t len;
ngx_addr_t *local;
n = lua_gettop(L);
if (n != 2) {
return luaL_error(L, "expecting 2 arguments, but got %d",
lua_gettop(L));
}
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no ctx found");
}
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER
| NGX_HTTP_LUA_CONTEXT_SSL_CERT);
luaL_checktype(L, 1, LUA_TTABLE);
text = (u_char *) luaL_checklstring(L, 2, &len);
local = ngx_http_lua_parse_addr(L, text, len);
if (local == NULL) {
lua_pushnil(L);
lua_pushfstring(L, "bad address");
return 2;
}
/* TODO: we may reuse the userdata here */
lua_rawseti(L, 1, SOCKET_BIND_INDEX);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua tcp socket bind ip: %V", &local->name);
lua_pushboolean(L, 1);
return 1;
}
static int
ngx_http_lua_socket_tcp_connect(lua_State *L)
{
@ -863,6 +898,7 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
size_t len;
ngx_http_lua_loc_conf_t *llcf;
ngx_peer_connection_t *pc;
ngx_addr_t *local;
int connect_timeout, send_timeout, read_timeout;
unsigned custom_pool;
int key_index;
@ -1093,6 +1129,14 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
dd("lua peer connection log: %p", pc->log);
lua_rawgeti(L, 1, SOCKET_BIND_INDEX);
local = lua_touserdata(L, -1);
lua_pop(L, 1);
if (local) {
u->peer.local = local;
}
lua_rawgeti(L, 1, SOCKET_CONNECT_TIMEOUT_INDEX);
lua_rawgeti(L, 1, SOCKET_SEND_TIMEOUT_INDEX);
lua_rawgeti(L, 1, SOCKET_READ_TIMEOUT_INDEX);
@ -1559,64 +1603,73 @@ ngx_http_lua_socket_conn_error_retval_handler(ngx_http_request_t *r,
#if (NGX_HTTP_SSL)
static int
ngx_http_lua_socket_tcp_sslhandshake(lua_State *L)
static const char *
ngx_http_lua_socket_tcp_check_busy(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, unsigned int ops)
{
int n, top;
ngx_int_t rc;
ngx_str_t name = ngx_null_string;
if ((ops & SOCKET_OP_CONNECT) && u->conn_waiting) {
return "socket busy connecting";
}
if ((ops & SOCKET_OP_READ) && u->read_waiting) {
return "socket busy reading";
}
if ((ops & SOCKET_OP_WRITE)
&& (u->write_waiting
|| (u->raw_downstream
&& (r->connection->buffered & NGX_HTTP_LOWLEVEL_BUFFERED))))
{
return "socket busy writing";
}
return NULL;
}
int
ngx_http_lua_ffi_socket_tcp_sslhandshake(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t *sess,
int enable_session_reuse, ngx_str_t *server_name, int verify,
int ocsp_status_req, STACK_OF(X509) *chain, EVP_PKEY *pkey,
const char **errmsg)
{
ngx_int_t rc, i;
ngx_connection_t *c;
ngx_ssl_session_t **psession;
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
ngx_http_lua_co_ctx_t *coctx;
ngx_http_lua_socket_tcp_upstream_t *u;
/* Lua function arguments: self [,session] [,host] [,verify]
[,send_status_req] */
n = lua_gettop(L);
if (n < 1 || n > 5) {
return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 5 "
"arguments (including the object), but seen %d", n);
}
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
const char *busy_msg;
ngx_ssl_conn_t *ssl_conn;
X509 *x509;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua tcp socket ssl handshake");
luaL_checktype(L, 1, LUA_TTABLE);
lua_rawgeti(L, 1, SOCKET_CTX_INDEX);
u = lua_touserdata(L, -1);
if (u == NULL
|| u->peer.connection == NULL
|| u->read_closed
|| u->write_closed)
{
lua_pushnil(L);
lua_pushliteral(L, "closed");
return 2;
*errmsg = "closed";
return NGX_ERROR;
}
if (u->request != r) {
return luaL_error(L, "bad request");
*errmsg = "bad request";
return NGX_ERROR;
}
ngx_http_lua_socket_check_busy_connecting(r, u, L);
ngx_http_lua_socket_check_busy_reading(r, u, L);
ngx_http_lua_socket_check_busy_writing(r, u, L);
busy_msg = ngx_http_lua_socket_tcp_check_busy(r, u, SOCKET_OP_CONNECT
| SOCKET_OP_READ
| SOCKET_OP_WRITE);
if (busy_msg != NULL) {
*errmsg = busy_msg;
return NGX_ERROR;
}
if (u->raw_downstream || u->body_downstream) {
lua_pushnil(L);
lua_pushliteral(L, "not supported for downstream");
return 2;
*errmsg = "not supported for downstream sockets";
return NGX_ERROR;
}
c = u->peer.connection;
@ -1624,122 +1677,140 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L)
u->ssl_session_reuse = 1;
if (c->ssl && c->ssl->handshaked) {
switch (lua_type(L, 2)) {
case LUA_TUSERDATA:
lua_pushvalue(L, 2);
break;
case LUA_TBOOLEAN:
if (!lua_toboolean(L, 2)) {
/* avoid generating the ssl session */
lua_pushboolean(L, 1);
break;
}
/* fall through */
default:
ngx_http_lua_ssl_handshake_retval_handler(r, u, L);
break;
if (sess != NULL) {
return NGX_DONE;
}
return 1;
u->ssl_session_reuse = enable_session_reuse;
(void) ngx_http_lua_ssl_handshake_retval_handler(r, u, NULL);
return NGX_OK;
}
if (ngx_ssl_create_connection(u->conf->ssl, c,
NGX_SSL_BUFFER|NGX_SSL_CLIENT)
!= NGX_OK)
{
lua_pushnil(L);
lua_pushliteral(L, "failed to create ssl connection");
return 2;
*errmsg = "failed to create ssl connection";
return NGX_ERROR;
}
ssl_conn = c->ssl->connection;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no ctx found");
return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
}
coctx = ctx->cur_co_ctx;
c->sendfile = 0;
if (n >= 2) {
if (lua_type(L, 2) == LUA_TBOOLEAN) {
u->ssl_session_reuse = lua_toboolean(L, 2);
if (sess != NULL) {
if (ngx_ssl_set_session(c, sess) != NGX_OK) {
*errmsg = "ssl set session failed";
return NGX_ERROR;
}
} else {
psession = lua_touserdata(L, 2);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua ssl set session: %p", sess);
if (psession != NULL && *psession != NULL) {
if (ngx_ssl_set_session(c, *psession) != NGX_OK) {
lua_pushnil(L);
lua_pushliteral(L, "lua ssl set session failed");
return 2;
}
} else {
u->ssl_session_reuse = enable_session_reuse;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua ssl set session: %p", *psession);
if (chain != NULL) {
ngx_http_lua_assert(pkey != NULL); /* ensured by resty.core */
if (sk_X509_num(chain) < 1) {
ERR_clear_error();
*errmsg = "invalid client certificate chain";
return NGX_ERROR;
}
x509 = sk_X509_value(chain, 0);
if (x509 == NULL) {
ERR_clear_error();
*errmsg = "ssl fetch client certificate from chain failed";
return NGX_ERROR;
}
if (SSL_use_certificate(ssl_conn, x509) == 0) {
ERR_clear_error();
*errmsg = "ssl set client certificate failed";
return NGX_ERROR;
}
/* read rest of the chain */
for (i = 1; i < sk_X509_num(chain); i++) {
x509 = sk_X509_value(chain, i);
if (x509 == NULL) {
ERR_clear_error();
*errmsg = "ssl fetch client intermediate certificate from "
"chain failed";
return NGX_ERROR;
}
if (SSL_add1_chain_cert(ssl_conn, x509) == 0) {
ERR_clear_error();
*errmsg = "ssl set client intermediate certificate failed";
return NGX_ERROR;
}
}
if (n >= 3) {
name.data = (u_char *) lua_tolstring(L, 3, &name.len);
if (name.data) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua ssl server name: \"%*s\"", name.len,
name.data);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (SSL_set_tlsext_host_name(c->ssl->connection,
(char *) name.data)
== 0)
{
lua_pushnil(L);
lua_pushliteral(L, "SSL_set_tlsext_host_name failed");
return 2;
}
#else
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua socket SNI disabled because the current "
"version of OpenSSL lacks the support");
#endif
}
if (n >= 4) {
u->ssl_verify = lua_toboolean(L, 4);
if (n >= 5) {
if (lua_toboolean(L, 5)) {
#ifdef NGX_HTTP_LUA_USE_OCSP
SSL_set_tlsext_status_type(c->ssl->connection,
TLSEXT_STATUSTYPE_ocsp);
#else
return luaL_error(L, "no OCSP support");
#endif
}
}
}
if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) {
ERR_clear_error();
*errmsg = "ssl set client private key failed";
return NGX_ERROR;
}
}
dd("found sni name: %.*s %p", (int) name.len, name.data, name.data);
if (server_name != NULL && server_name->data != NULL) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua ssl server name: \"%V\"", server_name);
if (name.len == 0) {
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (SSL_set_tlsext_host_name(c->ssl->connection,
(char *) server_name->data)
== 0)
{
*errmsg = "SSL_set_tlsext_host_name failed";
return NGX_ERROR;
}
#else
*errmsg = "no TLS extension support";
return NGX_ERROR;
#endif
}
u->ssl_verify = verify;
if (ocsp_status_req) {
#ifdef NGX_HTTP_LUA_USE_OCSP
SSL_set_tlsext_status_type(c->ssl->connection,
TLSEXT_STATUSTYPE_ocsp);
#else
*errmsg = "no OCSP support";
return NGX_ERROR;
#endif
}
if (server_name == NULL || server_name->len == 0) {
u->ssl_name.len = 0;
} else {
if (u->ssl_name.data) {
/* buffer already allocated */
if (u->ssl_name.len >= name.len) {
if (u->ssl_name.len >= server_name->len) {
/* reuse it */
ngx_memcpy(u->ssl_name.data, name.data, name.len);
u->ssl_name.len = name.len;
ngx_memcpy(u->ssl_name.data, server_name->data,
server_name->len);
u->ssl_name.len = server_name->len;
} else {
ngx_free(u->ssl_name.data);
@ -1750,17 +1821,15 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L)
new_ssl_name:
u->ssl_name.data = ngx_alloc(name.len, ngx_cycle->log);
u->ssl_name.data = ngx_alloc(server_name->len, ngx_cycle->log);
if (u->ssl_name.data == NULL) {
u->ssl_name.len = 0;
lua_pushnil(L);
lua_pushliteral(L, "no memory");
return 2;
*errmsg = "no memory";
return NGX_ERROR;
}
ngx_memcpy(u->ssl_name.data, name.data, name.len);
u->ssl_name.len = name.len;
ngx_memcpy(u->ssl_name.data, server_name->data, server_name->len);
u->ssl_name.len = server_name->len;
}
}
@ -1774,7 +1843,8 @@ new_ssl_name:
rc = ngx_ssl_handshake(c);
dd("ngx_ssl_handshake returned %d", (int) rc);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"ngx_ssl_handshake returned: %d", rc);
if (rc == NGX_AGAIN) {
if (c->write->timer_set) {
@ -1799,21 +1869,24 @@ new_ssl_name:
r->write_event_handler = ngx_http_core_run_phases;
}
return lua_yield(L, 0);
return NGX_AGAIN;
}
top = lua_gettop(L);
ngx_http_lua_ssl_handshake_handler(c);
return lua_gettop(L) - top;
if (rc == NGX_ERROR) {
*errmsg = u->error_ret;
return NGX_ERROR;
}
return NGX_OK;
}
static void
ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
{
const char *err;
int waiting;
lua_State *L;
ngx_int_t rc;
ngx_connection_t *dc; /* downstream connection */
ngx_http_request_t *r;
@ -1836,11 +1909,9 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
waiting = u->conn_waiting;
dc = r->connection;
L = u->write_co_ctx->co;
if (c->read->timedout) {
lua_pushnil(L);
lua_pushliteral(L, "timeout");
u->error_ret = "timeout";
goto failed;
}
@ -1849,19 +1920,18 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
}
if (c->ssl->handshaked) {
if (u->ssl_verify) {
rc = SSL_get_verify_result(c->ssl->connection);
if (rc != X509_V_OK) {
lua_pushnil(L);
err = lua_pushfstring(L, "%d: %s", (int) rc,
X509_verify_cert_error_string(rc));
u->error_ret = X509_verify_cert_error_string(rc);
u->openssl_error_code_ret = rc;
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
if (llcf->log_socket_errors) {
ngx_log_error(NGX_LOG_ERR, dc->log, 0, "lua ssl "
"certificate verify error: (%s)", err);
"certificate verify error: (%d: %s)",
rc, u->error_ret);
}
goto failed;
@ -1872,8 +1942,7 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
if (u->ssl_name.len
&& ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK)
{
lua_pushnil(L);
lua_pushliteral(L, "certificate host mismatch");
u->error_ret = "certificate host mismatch";
llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
if (llcf->log_socket_errors) {
@ -1892,7 +1961,7 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
ngx_http_lua_socket_handle_conn_success(r, u);
} else {
(void) ngx_http_lua_ssl_handshake_retval_handler(r, u, L);
(void) ngx_http_lua_ssl_handshake_retval_handler(r, u, NULL);
}
if (waiting) {
@ -1902,60 +1971,83 @@ ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c)
return;
}
lua_pushnil(L);
lua_pushliteral(L, "handshake failed");
u->error_ret = "handshake failed";
failed:
if (waiting) {
u->write_prepare_retvals =
ngx_http_lua_socket_conn_error_retval_handler;
ngx_http_lua_socket_handle_conn_error(r, u,
NGX_HTTP_LUA_SOCKET_FT_SSL);
ngx_http_lua_socket_conn_error_retval_handler;
ngx_http_lua_socket_handle_conn_error(r, u, NGX_HTTP_LUA_SOCKET_FT_SSL);
ngx_http_run_posted_requests(dc);
} else {
(void) ngx_http_lua_socket_conn_error_retval_handler(r, u, L);
u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_SSL;
(void) ngx_http_lua_socket_conn_error_retval_handler(r, u, NULL);
}
}
int
ngx_http_lua_ffi_socket_tcp_get_sslhandshake_result(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, ngx_ssl_session_t **sess,
const char **errmsg, int *openssl_error_code)
{
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua cosocket get SSL handshake result for upstream: %p", u);
if (u->error_ret != NULL) {
*errmsg = u->error_ret;
*openssl_error_code = u->openssl_error_code_ret;
return NGX_ERROR;
}
*sess = u->ssl_session_ret;
return NGX_OK;
}
static int
ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r,
ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L)
{
ngx_connection_t *c;
ngx_ssl_session_t *ssl_session, **ud;
ngx_ssl_session_t *ssl_session;
if (!u->ssl_session_reuse) {
lua_pushboolean(L, 1);
return 1;
return 0;
}
ud = lua_newuserdata(L, sizeof(ngx_ssl_session_t *));
c = u->peer.connection;
ssl_session = ngx_ssl_get_session(c);
if (ssl_session == NULL) {
*ud = NULL;
u->ssl_session_ret = NULL;
} else {
*ud = ssl_session;
u->ssl_session_ret = ssl_session;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua ssl save session: %p", ssl_session);
/* set up the __gc metamethod */
lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask(
ssl_session_metatable_key));
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
}
return 1;
return 0;
}
void
ngx_http_lua_ffi_ssl_free_session(ngx_ssl_session_t *sess)
{
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua ssl free session: %p", sess);
ngx_ssl_free_session(sess);
}
#endif /* NGX_HTTP_SSL */
@ -2008,12 +2100,14 @@ ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r,
u_char errstr[NGX_MAX_ERROR_STR];
u_char *p;
if (ft_type & (NGX_HTTP_LUA_SOCKET_FT_RESOLVER
| NGX_HTTP_LUA_SOCKET_FT_SSL))
{
if (ft_type & NGX_HTTP_LUA_SOCKET_FT_RESOLVER) {
return 2;
}
if (ft_type & NGX_HTTP_LUA_SOCKET_FT_SSL) {
return 0;
}
lua_pushnil(L);
if (ft_type & NGX_HTTP_LUA_SOCKET_FT_TIMEOUT) {
@ -2441,6 +2535,14 @@ ngx_http_lua_socket_tcp_read(ngx_http_request_t *r,
"lua tcp socket read data: wait:%d",
(int) u->read_waiting);
/* ngx_shutdown_timer_handler will set c->close and c->error on timeout
* when worker_shutdown_timeout is configured.
* The rev->ready is false at that time, so we need to set u->eof.
*/
if (c->close && c->error) {
u->eof = 1;
}
b = &u->buffer;
read = 0;
@ -3363,7 +3465,7 @@ ngx_http_lua_socket_send(ngx_http_request_t *r,
ngx_chain_update_chains(r->pool,
&ctx->free_bufs, &ctx->busy_bufs,
&ctx->free_bufs, &u->busy_bufs,
&u->request_bufs,
(ngx_buf_tag_t) &ngx_http_lua_module);
@ -4642,6 +4744,7 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
u_char c;
u_char *pat;
size_t pat_len;
size_t pending_len;
int i;
int state;
int old_state = 0; /* just to make old
@ -4770,11 +4873,12 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
/* matched */
dd("adding pending data: %.*s", (int) (old_state + 1 - state),
(char *) pat);
pending_len = old_state + 1 - state;
dd("adding pending data: %.*s", (int) pending_len, (char *) pat);
rc = ngx_http_lua_socket_add_pending_data(r, u, b->pos, i, pat,
old_state + 1 - state,
pending_len,
old_state);
if (rc != NGX_OK) {
@ -4785,14 +4889,14 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
i++;
if (u->length) {
if (u->rest <= (size_t) state) {
if (u->rest <= pending_len) {
u->rest = 0;
cp->state = state;
b->pos += i;
return NGX_OK;
} else {
u->rest -= state;
u->rest -= pending_len;
}
}
@ -4906,6 +5010,7 @@ ngx_http_lua_req_socket(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_CONTENT);
@ -5188,7 +5293,12 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L)
pc = &u->peer;
c = pc->connection;
if (c == NULL || u->read_closed || u->write_closed) {
/* When the server closes the connection,
* epoll will return EPOLLRDHUP event and nginx will set pending_eof.
*/
if (c == NULL || u->read_closed || u->write_closed
|| c->read->eof || c->read->pending_eof)
{
lua_pushnil(L);
lua_pushliteral(L, "closed");
return 2;
@ -5218,8 +5328,7 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L)
return 2;
}
if (c->read->eof
|| c->read->error
if (c->read->error
|| c->read->timedout
|| c->write->error
|| c->write->timedout)
@ -6101,27 +6210,6 @@ ngx_http_lua_coctx_cleanup(void *data)
}
#if (NGX_HTTP_SSL)
static int
ngx_http_lua_ssl_free_session(lua_State *L)
{
ngx_ssl_session_t **psession;
psession = lua_touserdata(L, 1);
if (psession && *psession != NULL) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua ssl free session: %p", *psession);
ngx_ssl_free_session(*psession);
}
return 0;
}
#endif /* NGX_HTTP_SSL */
void
ngx_http_lua_cleanup_conn_pools(lua_State *L)
{

View File

@ -120,8 +120,13 @@ struct ngx_http_lua_socket_tcp_upstream_s {
#if (NGX_HTTP_SSL)
ngx_str_t ssl_name;
ngx_ssl_session_t *ssl_session_ret;
const char *error_ret;
int openssl_error_code_ret;
#endif
ngx_chain_t *busy_bufs;
unsigned ft_type:16;
unsigned no_close:1;
unsigned conn_waiting:1;

View File

@ -24,7 +24,7 @@
#endif
#define UDP_MAX_DATAGRAM_SIZE 8192
#define UDP_MAX_DATAGRAM_SIZE 65536
static int ngx_http_lua_socket_udp(lua_State *L);

View File

@ -70,7 +70,8 @@ ngx_http_lua_ssl_cert_handler_inline(ngx_http_request_t *r,
lscf->srv.ssl_cert_src.len,
&lscf->srv.ssl_cert_src_ref,
lscf->srv.ssl_cert_src_key,
"=ssl_certificate_by_lua");
(const char *)
lscf->srv.ssl_cert_chunkname);
if (rc != NGX_OK) {
return rc;
}
@ -115,6 +116,8 @@ ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
#else
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key = NULL;
u_char *name;
ngx_str_t *value;
@ -163,8 +166,15 @@ ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "ssl_certificate_by_lua",
sizeof("ssl_certificate_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->srv.ssl_cert_src = value[1];
lscf->srv.ssl_cert_chunkname = chunkname;
}
lscf->srv.ssl_cert_src_key = cache_key;
@ -1042,7 +1052,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der,
int
ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len,
u_char *der, char **err)
const u_char *passphrase, u_char *der, char **err)
{
int len;
BIO *in;
@ -1055,7 +1065,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len,
return NGX_ERROR;
}
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, (void *) passphrase);
if (pkey == NULL) {
BIO_free(in);
*err = "PEM_read_bio_PrivateKey() failed";
@ -1479,4 +1489,15 @@ failed:
}
ngx_ssl_conn_t *
ngx_http_lua_ffi_get_req_ssl_pointer(ngx_http_request_t *r)
{
if (r->connection == NULL || r->connection->ssl == NULL) {
return NULL;
}
return r->connection->ssl->connection;
}
#endif /* NGX_HTTP_SSL */

View File

@ -61,7 +61,7 @@ ngx_http_lua_ssl_client_hello_handler_inline(ngx_http_request_t *r,
lscf->srv.ssl_client_hello_src.len,
&lscf->srv.ssl_client_hello_src_ref,
lscf->srv.ssl_client_hello_src_key,
"=ssl_client_hello_by_lua");
(const char *) lscf->srv.ssl_client_hello_chunkname);
if (rc != NGX_OK) {
return rc;
}
@ -106,6 +106,8 @@ ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
#else
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key = NULL;
u_char *name;
ngx_str_t *value;
@ -154,9 +156,16 @@ ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "ssl_client_hello_by_lua",
sizeof("ssl_client_helloo_by_lua")- 1,
&chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->srv.ssl_client_hello_src = value[1];
lscf->srv.ssl_client_hello_chunkname = chunkname;
}
lscf->srv.ssl_client_hello_src_key = cache_key;

View File

@ -66,7 +66,7 @@ ngx_http_lua_ssl_sess_fetch_handler_inline(ngx_http_request_t *r,
lscf->srv.ssl_sess_fetch_src.len,
&lscf->srv.ssl_sess_fetch_src_ref,
lscf->srv.ssl_sess_fetch_src_key,
"=ssl_session_fetch_by_lua_block");
(const char *) lscf->srv.ssl_sess_fetch_chunkname);
if (rc != NGX_OK) {
return rc;
}
@ -102,6 +102,8 @@ char *
ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key = NULL;
u_char *name;
ngx_str_t *value;
@ -153,8 +155,15 @@ ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "ssl_session_fetch_by_lua",
sizeof("ssl_session_fetch_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->srv.ssl_sess_fetch_src = value[1];
lscf->srv.ssl_sess_fetch_chunkname = chunkname;
}
lscf->srv.ssl_sess_fetch_src_key = cache_key;

View File

@ -64,7 +64,7 @@ ngx_http_lua_ssl_sess_store_handler_inline(ngx_http_request_t *r,
lscf->srv.ssl_sess_store_src.len,
&lscf->srv.ssl_sess_store_src_ref,
lscf->srv.ssl_sess_store_src_key,
"=ssl_session_store_by_lua_block");
(const char *) lscf->srv.ssl_sess_store_chunkname);
if (rc != NGX_OK) {
return rc;
}
@ -100,6 +100,8 @@ char *
ngx_http_lua_ssl_sess_store_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
size_t chunkname_len;
u_char *chunkname;
u_char *cache_key = NULL;
u_char *name;
ngx_str_t *value;
@ -151,8 +153,15 @@ ngx_http_lua_ssl_sess_store_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_ERROR;
}
chunkname = ngx_http_lua_gen_chunk_name(cf, "ssl_session_store_by_lua",
sizeof("ssl_session_store_by_lua") - 1, &chunkname_len);
if (chunkname == NULL) {
return NGX_CONF_ERROR;
}
/* Don't eval nginx variables for inline lua code */
lscf->srv.ssl_sess_store_src = value[1];
lscf->srv.ssl_sess_store_chunkname = chunkname;
}
lscf->srv.ssl_sess_store_src_key = cache_key;

View File

@ -39,6 +39,13 @@ ngx_http_lua_ffi_time(void)
}
long
ngx_http_lua_ffi_monotonic_msec(void)
{
return (long) ngx_current_msec;
}
void
ngx_http_lua_ffi_update_time(void)
{

View File

@ -565,6 +565,8 @@ ngx_http_lua_timer_handler(ngx_event_t *ev)
c = ngx_http_lua_create_fake_connection(tctx.pool);
if (c == NULL) {
errmsg = "could not create fake connection";
/* tctx.pool is freed in ngx_http_lua_create_fake_connection */
tctx.pool = NULL;
goto failed;
}
@ -821,7 +823,7 @@ ngx_http_lua_abort_pending_timers(ngx_event_t *ev)
prev = NULL;
events = ngx_pcalloc(ngx_cycle->pool,
lmcf->pending_timers * sizeof(ngx_event_t));
lmcf->pending_timers * sizeof(ngx_event_t *));
if (events == NULL) {
return;
}

View File

@ -92,12 +92,14 @@ ngx_http_lua_ngx_req_set_uri(lua_State *L)
return luaL_error(L, "no ctx found");
}
dd("rewrite: %d, access: %d, content: %d",
dd("server_rewrite: %d, rewrite: %d, access: %d, content: %d",
(int) ctx->entered_server_rewrite_phase,
(int) ctx->entered_rewrite_phase,
(int) ctx->entered_access_phase,
(int) ctx->entered_content_phase);
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE);
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua set uri jump to \"%*s\"", len, p);

View File

@ -125,6 +125,9 @@ ngx_http_lua_uthread_wait(lua_State *L)
coctx = ctx->cur_co_ctx;
nargs = lua_gettop(L);
if (nargs == 0) {
return luaL_error(L, "at least one coroutine should be specified");
}
for (i = 1; i <= nargs; i++) {
sub_co = lua_tothread(L, i);

View File

@ -119,7 +119,6 @@ static int ngx_http_lua_thread_traceback(lua_State *L, lua_State *co,
static void ngx_http_lua_inject_ngx_api(lua_State *L,
ngx_http_lua_main_conf_t *lmcf, ngx_log_t *log);
static void ngx_http_lua_inject_arg_api(lua_State *L);
static int ngx_http_lua_param_get(lua_State *L);
static int ngx_http_lua_param_set(lua_State *L);
static ngx_int_t ngx_http_lua_output_filter(ngx_http_request_t *r,
ngx_chain_t *in);
@ -281,7 +280,6 @@ ngx_http_lua_new_state(lua_State *parent_vm, ngx_cycle_t *cycle,
lua_pushliteral(L, LUA_DEFAULT_CPATH ";"); /* package default */
lua_getfield(L, -2, "cpath"); /* package default old */
old_cpath = lua_tolstring(L, -1, &old_cpath_len);
lua_concat(L, 2); /* package new */
lua_setfield(L, -2, "cpath"); /* package */
#endif
@ -827,7 +825,7 @@ static void
ngx_http_lua_inject_ngx_api(lua_State *L, ngx_http_lua_main_conf_t *lmcf,
ngx_log_t *log)
{
lua_createtable(L, 0 /* narr */, 113 /* nrec */); /* ngx.* */
lua_createtable(L, 0 /* narr */, 115 /* nrec */); /* ngx.* */
lua_pushcfunction(L, ngx_http_lua_get_raw_phase_context);
lua_setfield(L, -2, "_phase_ctx");
@ -1005,6 +1003,7 @@ ngx_http_lua_reset_ctx(ngx_http_request_t *r, lua_State *L,
ctx->entry_co_ctx.co_ref = LUA_NOREF;
ctx->entered_server_rewrite_phase = 0;
ctx->entered_rewrite_phase = 0;
ctx->entered_access_phase = 0;
ctx->entered_content_phase = 0;
@ -3100,9 +3099,6 @@ ngx_http_lua_inject_arg_api(lua_State *L)
lua_createtable(L, 0 /* narr */, 2 /* nrec */); /* the metatable */
lua_pushcfunction(L, ngx_http_lua_param_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, ngx_http_lua_param_set);
lua_setfield(L, -2, "__newindex");
@ -3114,35 +3110,6 @@ ngx_http_lua_inject_arg_api(lua_State *L)
}
static int
ngx_http_lua_param_get(lua_State *L)
{
ngx_http_lua_ctx_t *ctx;
ngx_http_request_t *r;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return 0;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "ctx not found");
}
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_SET
| NGX_HTTP_LUA_CONTEXT_BODY_FILTER);
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SET)) {
return ngx_http_lua_setby_param_get(L, r);
}
/* ctx->context & (NGX_HTTP_LUA_CONTEXT_BODY_FILTER) */
return ngx_http_lua_body_filter_param_get(L, r);
}
static int
ngx_http_lua_param_set(lua_State *L)
{
@ -4429,4 +4396,77 @@ ngx_http_lua_copy_escaped_header(ngx_http_request_t *r,
return NGX_OK;
}
ngx_addr_t *
ngx_http_lua_parse_addr(lua_State *L, u_char *text, size_t len)
{
ngx_addr_t *addr;
size_t socklen;
in_addr_t inaddr;
ngx_uint_t family;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct in6_addr inaddr6;
struct sockaddr_in6 *sin6;
/*
* prevent MSVC8 warning:
* potentially uninitialized local variable 'inaddr6' used
*/
ngx_memzero(&inaddr6, sizeof(struct in6_addr));
#endif
inaddr = ngx_inet_addr(text, len);
if (inaddr != INADDR_NONE) {
family = AF_INET;
socklen = sizeof(struct sockaddr_in);
#if (NGX_HAVE_INET6)
} else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
family = AF_INET6;
socklen = sizeof(struct sockaddr_in6);
#endif
} else {
return NULL;
}
addr = lua_newuserdata(L, sizeof(ngx_addr_t) + socklen + len);
if (addr == NULL) {
luaL_error(L, "no memory");
return NULL;
}
addr->sockaddr = (struct sockaddr *) ((u_char *) addr + sizeof(ngx_addr_t));
ngx_memzero(addr->sockaddr, socklen);
addr->sockaddr->sa_family = (u_char) family;
addr->socklen = socklen;
switch (family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) addr->sockaddr;
ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) addr->sockaddr;
sin->sin_addr.s_addr = inaddr;
break;
}
addr->name.data = (u_char *) addr->sockaddr + socklen;
addr->name.len = len;
ngx_memcpy(addr->name.data, text, len);
return addr;
}
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

View File

@ -33,6 +33,7 @@
#define NGX_HTTP_LUA_ESCAPE_HEADER_VALUE 8
#define NGX_HTTP_LUA_CONTEXT_YIELDABLE (NGX_HTTP_LUA_CONTEXT_REWRITE \
| NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE \
| NGX_HTTP_LUA_CONTEXT_ACCESS \
| NGX_HTTP_LUA_CONTEXT_CONTENT \
| NGX_HTTP_LUA_CONTEXT_TIMER \
@ -48,6 +49,7 @@
#define ngx_http_lua_context_name(c) \
((c) == NGX_HTTP_LUA_CONTEXT_SET ? "set_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_REWRITE ? "rewrite_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE ? "server_rewrite_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_ACCESS ? "access_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_CONTENT ? "content_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_LOG ? "log_by_lua*" \
@ -260,6 +262,8 @@ void ngx_http_lua_cleanup_free(ngx_http_request_t *r,
void ngx_http_lua_set_sa_restart(ngx_log_t *log);
#endif
ngx_addr_t *ngx_http_lua_parse_addr(lua_State *L, u_char *text, size_t len);
size_t ngx_http_lua_escape_log(u_char *dst, u_char *src, size_t size);
@ -564,7 +568,7 @@ ngx_http_lua_free_thread(ngx_http_request_t *r, lua_State *L, int co_ref,
{
#ifdef HAVE_LUA_RESETTHREAD
ngx_queue_t *q;
ngx_http_lua_thread_ref_t *tref ;
ngx_http_lua_thread_ref_t *tref;
ngx_http_lua_ctx_t *ctx;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
@ -685,6 +689,43 @@ ngx_http_lua_new_cached_thread(lua_State *L, lua_State **out_co,
}
static ngx_inline void *
ngx_http_lua_hash_find_lc(ngx_hash_t *hash, ngx_uint_t key, u_char *name,
size_t len)
{
ngx_uint_t i;
ngx_hash_elt_t *elt;
elt = hash->buckets[key % hash->size];
if (elt == NULL) {
return NULL;
}
while (elt->value) {
if (len != (size_t) elt->len) {
goto next;
}
for (i = 0; i < len; i++) {
if (ngx_tolower(name[i]) != elt->name[i]) {
goto next;
}
}
return elt->value;
next:
elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,
sizeof(void *));
continue;
}
return NULL;
}
extern ngx_uint_t ngx_http_lua_location_hash;
extern ngx_uint_t ngx_http_lua_content_length_hash;

View File

@ -8,6 +8,7 @@
#define DDEBUG 0
#endif
#include "ddebug.h"
#include <ngx_channel.h>
#define NGX_PROCESS_PRIVILEGED_AGENT 99
@ -20,6 +21,36 @@ ngx_http_lua_ffi_worker_pid(void)
}
int
ngx_http_lua_ffi_worker_pids(int *pids, size_t *pids_len)
{
ngx_int_t i, n;
n = 0;
for (i = 0; i < NGX_MAX_PROCESSES; i++) {
if (i != ngx_process_slot && ngx_processes[i].pid == 0) {
break;
}
if (i == ngx_process_slot && ngx_processes[i].pid == 0) {
pids[n++] = ngx_pid;
}
if (ngx_processes[i].pid > 0) {
pids[n++] = ngx_processes[i].pid;
}
}
if (n == 0) {
return NGX_ERROR;
}
*pids_len = n;
return NGX_OK;
}
int
ngx_http_lua_ffi_worker_id(void)
{

View File

@ -16,7 +16,12 @@
#include "ngx_http_lua_util.h"
#include "ngx_http_lua_string.h"
#include "ngx_http_lua_config.h"
#include "ngx_http_lua_shdict.h"
#ifndef STRINGIFY
#define TOSTRING(x) #x
#define STRINGIFY(x) TOSTRING(x)
#endif
#if (NGX_THREADS)
@ -24,6 +29,7 @@
#include <ngx_thread.h>
#include <ngx_thread_pool.h>
#define LUA_COPY_MAX_DEPTH 100
typedef struct ngx_http_lua_task_ctx_s {
lua_State *vm;
@ -139,14 +145,16 @@ ngx_http_lua_get_task_ctx(lua_State *L, ngx_http_request_t *r)
lua_setfield(vm, -2, "path");
lua_pushlstring(vm, cpath, cpath_len);
lua_setfield(vm, -2, "cpath");
lua_pop(vm, 1);
/* pop path, cpath and "package" table from L */
lua_pop(L, 3);
/* inject API from C */
lua_newtable(L); /* ngx.* */
lua_newtable(vm); /* ngx.* */
ngx_http_lua_inject_string_api(vm);
ngx_http_lua_inject_config_api(vm);
ngx_http_lua_inject_shdict_api(lmcf, vm);
lua_setglobal(vm, "ngx");
/* inject API via ffi */
@ -174,6 +182,14 @@ ngx_http_lua_get_task_ctx(lua_State *L, ngx_http_request_t *r)
return NULL;
}
lua_getglobal(vm, "require");
lua_pushstring(vm, "resty.core.shdict");
if (lua_pcall(vm, 1, 0, 0) != 0) {
lua_close(vm);
ngx_free(ctx);
return NULL;
}
} else {
ctx = ctxpool->next;
ctxpool->next = ctx->next;
@ -197,7 +213,7 @@ ngx_http_lua_free_task_ctx(ngx_http_lua_task_ctx_t *ctx)
static int
ngx_http_lua_xcopy(lua_State *from, lua_State *to, int idx,
const int allow_nil)
const int allow_nil, const int depth, const char **err)
{
size_t len = 0;
const char *str;
@ -224,6 +240,13 @@ ngx_http_lua_xcopy(lua_State *from, lua_State *to, int idx,
return LUA_TSTRING;
case LUA_TTABLE:
if (depth >= LUA_COPY_MAX_DEPTH) {
*err = "suspicious circular references, "
"table depth exceed max depth: "
STRINGIFY(LUA_COPY_MAX_DEPTH);
return LUA_TNONE;
}
top_from = lua_gettop(from);
top_to = lua_gettop(to);
@ -237,8 +260,9 @@ ngx_http_lua_xcopy(lua_State *from, lua_State *to, int idx,
lua_pushnil(from);
while (lua_next(from, idx) != 0) {
if (ngx_http_lua_xcopy(from, to, -2, 0) != LUA_TNONE
&& ngx_http_lua_xcopy(from, to, -1, 0) != LUA_TNONE)
if (ngx_http_lua_xcopy(from, to, -2, 0, depth + 1, err) != LUA_TNONE
&& ngx_http_lua_xcopy(from, to, -1, 0,
depth + 1, err) != LUA_TNONE)
{
lua_rawset(to, -3);
@ -258,16 +282,24 @@ ngx_http_lua_xcopy(lua_State *from, lua_State *to, int idx,
lua_pushnil(to);
return LUA_TNIL;
}
/* fall through */
/*
* ignore unsupported values:
* LUA_TNONE
* LUA_TFUNCTION
* LUA_TUSERDATA
* LUA_TTHREAD
*/
*err = "unsupported Lua type: LUA_TNIL";
return LUA_TNONE;
case LUA_TFUNCTION:
*err = "unsupported Lua type: LUA_TFUNCTION";
return LUA_TNONE;
case LUA_TUSERDATA:
*err = "unsupported Lua type: LUA_TUSERDATA";
return LUA_TNONE;
case LUA_TTHREAD:
*err = "unsupported Lua type: LUA_TTHREAD";
return LUA_TNONE;
default:
*err = "unsupported Lua type";
return LUA_TNONE;
}
}
@ -346,6 +378,7 @@ ngx_http_lua_worker_thread_event_handler(ngx_event_t *ev)
ngx_http_lua_ctx_t *ctx;
lua_State *vm;
int saved_top;
const char *err;
worker_thread_ctx = ev->data;
@ -381,10 +414,12 @@ ngx_http_lua_worker_thread_event_handler(ngx_event_t *ev)
lua_pushboolean(L, 1);
nresults = lua_gettop(vm) + 1;
for (i = 1; i < nresults; i++) {
if (ngx_http_lua_xcopy(vm, L, i, 1) == LUA_TNONE) {
err = NULL;
if (ngx_http_lua_xcopy(vm, L, i, 1, 1, &err) == LUA_TNONE) {
lua_settop(L, saved_top);
lua_pushboolean(L, 0);
lua_pushstring(L, "unsupported return value");
lua_pushfstring(L, "%s in the return value",
err != NULL ? err : "unsupoorted Lua type");
nresults = 2;
break;
}
@ -546,9 +581,11 @@ ngx_http_lua_run_worker_thread(lua_State *L)
/* copying passed arguments */
for (i = 4; i <= n_args; i++) {
if (ngx_http_lua_xcopy(L, vm, i, 1) == LUA_TNONE) {
err = NULL;
if (ngx_http_lua_xcopy(L, vm, i, 1, 1, &err) == LUA_TNONE) {
lua_pushboolean(L, 0);
lua_pushstring(L, "unsupported argument type");
lua_pushfstring(L, "%s in the argument",
err != NULL ? err : "unsupoorted Lua type");
ngx_http_lua_free_task_ctx(tctx);
return 2;
}

View File

@ -573,7 +573,7 @@ GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to run set_by_lua*: set_by_lua:1: Bad
failed to run set_by_lua*: set_by_lua(nginx.conf:40):1: Bad

View File

@ -10,7 +10,7 @@ use Test::Nginx::Socket::Lua;
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2 + 24);
plan tests => repeat_each() * (blocks() * 2 + 32);
#no_diff();
#no_long_string();
@ -849,4 +849,252 @@ GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/failed to load inlined Lua code: /
qr/failed to load inlined Lua code: content_by_lua\(nginx.conf:40\)/
=== TEST 43: syntax error in content_by_lua_block
--- config
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/failed to load inlined Lua code: content_by_lua\(nginx.conf:41\)/
=== TEST 44: syntax error in second content_by_lua_block
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/failed to load inlined Lua code: content_by_lua\(nginx.conf:46\)/
=== TEST 45: syntax error in thrid content_by_lua_block
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/failed to load inlined Lua code: content_by_lua\(nginx.conf:52\)/
=== TEST 46: syntax error in included file
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
include ../html/lua.conf;
--- user_files
>>> lua.conf
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to load inlined Lua code: content_by_lua(../html/lua.conf:2):2: unexpected symbol near ''for end''
=== TEST 47: syntax error with very long filename
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
include ../html/1234567890123456789012345678901234.conf;
--- user_files
>>> 1234567890123456789012345678901234.conf
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to load inlined Lua code: content_by_lua(...234567890123456789012345678901234.conf:2)
=== TEST 48: syntax error in /tmp/lua.conf
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
include /tmp/lua.conf;
--- user_files
>>> /tmp/lua.conf
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to load inlined Lua code: content_by_lua(/tmp/lua.conf:2)
=== TEST 49: syntax error in /tmp/12345678901234567890123456789012345.conf
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
include /tmp/12345678901234567890123456789012345.conf;
--- user_files
>>> /tmp/12345678901234567890123456789012345.conf
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to load inlined Lua code: content_by_lua(...345678901234567890123456789012345.conf:2)
=== TEST 50: the error line number greater than 9
--- config
location /foo {
content_by_lua_block {
'for end';
}
}
location /bar {
content_by_lua_block {
'for end';
}
}
include /tmp/12345678901234567890123456789012345.conf;
--- user_files
>>> /tmp/12345678901234567890123456789012345.conf
location /lua {
content_by_lua_block {
'for end';
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to load inlined Lua code: content_by_lua(...45678901234567890123456789012345.conf:14)
=== TEST 51: Lua file permission denied
--- config
location /lua {
content_by_lua_file /etc/shadow;
}
--- request
GET /lua
--- response_body_like: 503 Service Temporarily Unavailable
--- error_code: 503

View File

@ -724,3 +724,98 @@ GET /t
--- response_body
--- no_error_log
[error]
=== TEST 25: 501 Method Not Implemented
--- config
location /lua {
content_by_lua '
ngx.exit(ngx.HTTP_NOT_IMPLEMENTED)
';
}
--- request
GET /lua
--- error_code: 501
--- response_body_like: 501 (?:Method )?Not Implemented
--- no_error_log
[error]
=== TEST 26: accepts NGX_OK
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.OK)
}
}
--- request
GET /t
--- response_body
--- no_error_log
[error]
=== TEST 27: accepts NGX_ERROR
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.ERROR)
}
}
--- request
GET /t
--- error_code:
--- response_body
--- no_error_log
[error]
=== TEST 28: accepts NGX_DECLINED
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.DECLINED)
}
}
--- request
GET /t
--- error_code:
--- response_body
--- no_error_log
[error]
=== TEST 29: refuses NGX_AGAIN
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.AGAIN)
}
}
--- request
GET /t
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log eval
qr/\[error\] .*? bad argument to 'ngx.exit': does not accept NGX_AGAIN or NGX_DONE/
=== TEST 30: refuses NGX_DONE
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.DONE)
}
}
--- request
GET /t
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log eval
qr/\[error\] .*? bad argument to 'ngx.exit': does not accept NGX_AGAIN or NGX_DONE/

View File

@ -243,7 +243,7 @@ GET /log
--- response_body
32
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] set_by_lua:2: HELLO,/
qr/\[error\] \S+: \S+ \[lua\] set_by_lua\(nginx.conf:43\):2: HELLO,/
@ -261,7 +261,7 @@ GET /log
--- response_body
32
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] set_by_lua:2: truefalsenil,/
qr/\[error\] \S+: \S+ \[lua\] set_by_lua\(nginx.conf:43\):2: truefalsenil,/
@ -368,7 +368,7 @@ GET /log
--- response_headers
foo: 32
--- error_log eval
qr/\[notice\] .*? \[lua\] header_filter_by_lua:2: hello world/
qr/\[notice\] .*? \[lua\] header_filter_by_lua\(nginx.conf:43\):2: hello world/
--- response_body
hi
@ -390,7 +390,7 @@ foo: 32
--- response_body
hi
--- error_log eval
qr/\[error\] .*? \[lua\] header_filter_by_lua:2: howdy, lua!/
qr/\[error\] .*? \[lua\] header_filter_by_lua\(nginx.conf:43\):2: howdy, lua!/

View File

@ -8,7 +8,8 @@ log_level('debug');
repeat_each(3);
plan tests => repeat_each() * (blocks() * 2 + 33);
# NB: the shutdown_error_log block is independent from repeat times
plan tests => repeat_each() * (blocks() * 2 + 33) + 1;
our $HtmlDir = html_dir;
#warn $html_dir;
@ -1239,3 +1240,46 @@ res: true
--- must_die
--- error_log eval
qr/\[emerg\] \d+#\d+: unexpected "A" in/
=== TEST 47: cosocket does not exit on worker_shutdown_timeout
--- main_config
worker_shutdown_timeout 1;
--- config
location /t {
content_by_lua_block {
local function thread_func()
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", 65110)
local bytes, err = sock:send("hello")
if bytes ~= 5 then
sock:close()
return ngx.exit(500)
end
local data, err = sock:receive(20)
local line, err, partial = sock:receive()
if not line then
ngx.log(ngx.ERR, "failed to read a line: ", err)
return
end
ngx.log(ngx.ERR, "successfully read a line: ", line)
end
local function timer_func()
ngx.thread.spawn(thread_func)
end
ngx.timer.at(1, timer_func)
ngx.say("Hello world")
}
}
--- request
GET /t
--- response_body
Hello world
--- shutdown_error_log eval
qr|failed to read a line: closed|
--- timeout: 1.2

View File

@ -2141,3 +2141,88 @@ hi
--- error_log
my Content-Length: 8589934591
upstream prematurely closed connection while sending to client
=== TEST 95: Expose the 'Last-Modified' response header as ngx.header["Last-Modified"]
--- config
location /a.txt {
header_filter_by_lua_block {
local last_modified = ngx.header["Last-Modified"]
if last_modified == nil then
ngx.log(ngx.ERR, "can not get lasted modified")
ngx.exit(500)
return
end
local last_mod = ngx.parse_http_time(last_modified)
local age = ngx.time() - last_mod
ngx.header["Age"] = age
}
}
--- user_files
>>> a.txt
Foo
--- request
GET /a.txt
--- raw_response_headers_like chomp
Age: \d\r\n
--- no_error_log
[error]
=== TEST 96: 'Last-Modified' from upstream
--- config
location /test/ {
proxy_pass http://127.0.0.1:$server_port/;
header_filter_by_lua_block {
local last_modified = ngx.header["Last-Modified"]
if last_modified == nil then
ngx.log(ngx.ERR, "can not get lasted modified")
ngx.exit(500)
return
end
local last_mod = ngx.parse_http_time(last_modified)
local age = ngx.time() - last_mod
ngx.header["Age"] = age
}
}
--- user_files
>>> a.txt
Foo
--- request
GET /test/a.txt
--- raw_response_headers_like chomp
Age: \d\r\n
--- no_error_log
[error]
=== TEST 97: 'Last-Modified' does not exist
--- config
location /test {
header_filter_by_lua_block {
local last_modified = ngx.header["Last-Modified"]
if last_modified == nil then
ngx.log(ngx.INFO, "Last-Modified is nil as expected")
return
end
ngx.log(ngx.ERR, "Last-Modified expected to be nil, but got ", last_modified)
}
content_by_lua_block {
ngx.say("Hello World")
}
}
--- request
GET /test
--- response_body
Hello World
--- no_error_log
[error]

View File

@ -1862,17 +1862,17 @@ code cache hit (key='log_by_lua_nhli_8a9441d0a30531ba8bb34ab11c55cfc3', ref=12)
"]
--- error_log eval
[
qr/balancer_by_lua:\d+: hello/,
qr/ssl_session_fetch_by_lua_block:\d+: hello/,
qr/ssl_certificate_by_lua:\d+: hello/,
qr/ssl_session_store_by_lua_block:\d+: hello/,
qr/set_by_lua:\d+: hello/,
qr/balancer_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/ssl_session_fetch_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/ssl_certificate_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/ssl_session_store_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/set_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/rewrite_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/access_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/content_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/header_filter_by_lua:\d+: hello/,
qr/body_filter_by_lua:\d+: hello/,
qr/log_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/header_filter_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/body_filter_by_lua\(nginx\.conf:\d+\):\d+: hello/,
qr/log_by_lua\(nginx.conf:\d+\):\d+: hello/,
]
--- log_level: debug
--- no_error_log

View File

@ -462,7 +462,7 @@ GET /lua
GET /lua
--- ignore_response
--- error_log
failed to run header_filter_by_lua*: header_filter_by_lua:2: Something bad
failed to run header_filter_by_lua*: header_filter_by_lua(nginx.conf:47):2: Something bad
--- no_error_log
[alert]
@ -799,3 +799,77 @@ GET /t
--- error_code: 302
--- no_error_log
[error]
=== TEST 42: syntax error in header_filter_by_lua_block
--- config
location /lua {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(nginx.conf:41):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error
=== TEST 43: syntax error in second content_by_lua_block
--- config
location /foo {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
location /lua {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(nginx.conf:49):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error
=== TEST 44: syntax error in /tmp/12345678901234567890123456789012345.conf
--- config
location /lua {
content_by_lua_block {
ngx.say("Hello world")
}
include /tmp/12345678901234567890123456789012345.conf;
}
--- user_files
>>> /tmp/12345678901234567890123456789012345.conf
header_filter_by_lua_block {
'for end';
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(...901234567890123456789012345.conf:1):2: unexpected symbol near ''for end''
--- no_error_log
[alert]

View File

@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * 231;
plan tests => repeat_each() * (blocks() * 3 + 21);
our $HtmlDir = html_dir;
@ -4367,3 +4367,69 @@ connect failed: missing the port number
finish
--- no_error_log
[error]
=== TEST 73: reset the buffer pos when keepalive
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
for i = 1, 10
do
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local req = "GET /hi HTTP/1.1\r\nHost: localhost\r\n\r\n"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
local line, err, part = sock:receive()
if not line then
ngx.say("receive err: ", err)
return
end
data, err = sock:receiveany(4096)
if not data then
ngx.say("receiveany er: ", err)
return
end
ok, err = sock:setkeepalive(10000, 32)
if not ok then
ngx.say("reused times: ", i, ", setkeepalive err: ", err)
return
end
end
ngx.say("END")
}
}
location /hi {
keepalive_requests 3;
content_by_lua_block {
ngx.say("Hello")
}
more_clear_headers Date;
}
--- request
GET /t
--- response_body
reused times: 3, setkeepalive err: closed
--- no_error_log
[error]
--- skip_eval: 3: $ENV{TEST_NGINX_EVENT_TYPE} && $ENV{TEST_NGINX_EVENT_TYPE} ne 'epoll'

View File

@ -34,7 +34,7 @@ __DATA__
--- request
GET /test
--- response_body
ngx: 114
ngx: 116
--- no_error_log
[error]
@ -55,7 +55,7 @@ ngx: 114
--- request
GET /test
--- response_body
114
116
--- no_error_log
[error]
@ -83,7 +83,7 @@ GET /test
--- request
GET /test
--- response_body
n = 114
n = 116
--- no_error_log
[error]
@ -305,7 +305,7 @@ GET /t
--- response_body_like: 404 Not Found
--- error_code: 404
--- error_log
ngx. entry count: 114
ngx. entry count: 116
@ -438,7 +438,7 @@ thread: 3
--- request
GET /test
--- response_body
worker: 4
worker: 5
--- no_error_log
[error]
@ -459,7 +459,7 @@ worker: 4
--- request
GET /test
--- response_body
n = 14
n = 16
--- no_error_log
[error]

View File

@ -1027,7 +1027,7 @@ close: 1 nil
local reader = sock:receiveuntil("--abc")
for i = 1, 7 do
for i = 1, 6 do
local line, err, part = reader(4)
if line then
ngx.say("read: ", line)
@ -1055,7 +1055,6 @@ read: hell
read: o, w
read: orld
read: --
read:
failed to read a line: nil [nil]
failed to read a line: closed [
]
@ -1104,7 +1103,7 @@ close: 1 nil
local reader = sock:receiveuntil("--abc")
for i = 1, 7 do
for i = 1, 6 do
local line, err, part = reader(4)
if line then
ngx.say("read: ", line)
@ -1132,7 +1131,6 @@ read: hell
read: o, w
read: orld
read: --
read:
failed to read a line: nil [nil]
failed to read a line: closed [
]
@ -1329,3 +1327,78 @@ this exposed a memory leak in receiveuntil
ok
--- no_error_log
[error]
=== TEST 20: add pending bytes
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
lua_socket_buffer_size 1;
content_by_lua '
-- collectgarbage("collect")
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", 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"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
local read_headers = sock:receiveuntil("\\r\\n\\r\\n")
local headers, err, part = read_headers()
if not headers then
ngx.say("failed to read headers: ", err, " [", part, "]")
end
local reader = sock:receiveuntil("--abc")
for i = 1, 4 do
local line, err, part = reader(2)
if line then
ngx.say("read: ", line)
else
ngx.say("failed to read a line: ", err, " [", part, "]")
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
}
location /foo {
echo -- -----abc;
more_clear_headers Date;
}
--- request
GET /t
--- response_body eval
qq{connected: 1
request sent: 57
read: --
read: -
failed to read a line: nil [nil]
failed to read a line: closed [
]
close: 1 nil
}
--- no_error_log
[error]

View File

@ -367,7 +367,7 @@ Transfer-Encoding: chunked\r
Connection: close\r
\r
6\r
failed to set keepalive: (?:unread data in buffer|connection in dubious state)
failed to set keepalive: (?:unread data in buffer|closed|connection in dubious state)
}
--- no_error_log
[error]

View File

@ -317,7 +317,7 @@ hiya globe
GET /t
--- ignore_response
--- error_log
failed to run body_filter_by_lua*: body_filter_by_lua:4: something bad happened!
failed to run body_filter_by_lua*: body_filter_by_lua(nginx.conf:49):4: something bad happened!
@ -838,3 +838,55 @@ GET /lua
--- ignore_response
--- error_log
API disabled in the context of body_filter_by_lua*
=== TEST 27: syntax error in body_filter_by_lua_block
--- config
location /lua {
body_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: body_filter_by_lua(nginx.conf:41):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error1
no_such_error2
=== TEST 28: syntax error in second body_by_lua_block
--- config
location /foo {
body_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
location /lua {
body_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: body_filter_by_lua(nginx.conf:49):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error1
no_such_error2

View File

@ -619,7 +619,7 @@ bad "inclusive" option value type: string
local reader = sock:receiveuntil("--abc", { inclusive = true })
for i = 1, 7 do
for i = 1, 6 do
local line, err, part = reader(4)
if line then
ngx.say("read: ", line)
@ -646,8 +646,7 @@ request sent: 57
read: hell
read: o, w
read: orld
read: --
read: --abc
read: ----abc
failed to read a line: nil [nil]
failed to read a line: closed [
]

View File

@ -321,3 +321,47 @@ INIT 2: foo = 3
failed to init
--- error_log
[error]
=== TEST 13: syntax error in init_by_lua_block
--- http_config
init_by_lua_block {
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
}
--- config
location /lua {
content_by_lua_block {
ngx.say("hello world")
}
}
--- must_die
--- error_log
init_by_lua error: init_by_lua(nginx.conf:25):4: ')' expected (to close '(' at line 3) near 'ngx'
--- no_error_log
no_such_error_log
=== TEST 14: syntax error in init_by_lua_file
--- http_config
init_by_lua_file html/init.lua;
--- config
location /lua {
content_by_lua_block {
ngx.say("hello world")
}
}
--- user_files
>>> init.lua
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
--- must_die
--- error_log eval
qr|init_by_lua_file error: .*?/t/servroot\w*?/html/init.lua:3: '\)' expected \(to close '\(' at line 2\) near 'ngx'|
--- no_error_log
no_such_error_log

View File

@ -69,7 +69,7 @@ GET /t
[error]
--- log_level: debug
--- error_log
lua udp socket receive buffer size: 8192
lua udp socket receive buffer size: 65536
@ -595,7 +595,7 @@ received a good response.
[error]
--- log_level: debug
--- error_log
lua udp socket receive buffer size: 8192
lua udp socket receive buffer size: 65536
--- no_check_leak
@ -662,7 +662,7 @@ received a good response.
[error]
--- log_level: debug
--- error_log
lua udp socket receive buffer size: 8192
lua udp socket receive buffer size: 65536
--- no_check_leak

View File

@ -8,7 +8,7 @@ log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 1) + 2;
plan tests => repeat_each() * (blocks() * 2 + 2) + 2;
#no_diff();
#no_long_string();
@ -198,6 +198,26 @@ GET /lua
ok
--- shutdown_error_log eval
[
qr/exit_worker_by_lua:\d+: exit_worker/,
qr/exit_worker_by_lua\(nginx\.conf:\d+\):\d+: exit_worker/,
qr/exiting now$/,
]
=== TEST 12: server_rewrite_by_lua_block in http
--- http_config
server_rewrite_by_lua_block {
ngx.ctx.phase = ngx.get_phase()
}
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.ctx.phase)
}
}
--- request
GET /lua
--- response_body
server_rewrite
--- no_error_log
[error]

View File

@ -1691,7 +1691,7 @@ GET /t
--- error_log eval
[
qr/\[notice\] .*? in wrapped coroutine/,
qr/\[error\] .*? failed to run header_filter_by_lua\*: header_filter_by_lua:\d+: header_filter_by_lua:\d+: something went wrong/,
qr/\[error\] .*? failed to run header_filter_by_lua\*: header_filter_by_lua\(nginx.conf:\d+\):\d+: header_filter_by_lua\(nginx.conf:\d+\):\d+: something went wrong/,
"stack traceback:",
"in function 'co'"
]
@ -1713,9 +1713,9 @@ GET /t
--- config
--- must_die
--- grep_error_log eval: qr/init_by_lua error: .*? something went wrong/
--- grep_error_log eval: qr/init_by_lua\(nginx.conf:25\).*? something went wrong/
--- grep_error_log_out
init_by_lua error: init_by_lua:7: init_by_lua:4: something went wrong
init_by_lua(nginx.conf:25):7: init_by_lua(nginx.conf:25):4: something went wrong

View File

@ -1321,3 +1321,22 @@ $s;
--- no_error_log
[error]
[alert]
=== TEST 23: no parameters for ngx.thread.wait
--- config
location /lua {
content_by_lua_block {
ngx.thread.wait()
ngx.say("ok")
}
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
at least one coroutine should be specified
--- no_error_log
[crit]

View File

@ -1017,3 +1017,36 @@ client sent invalid header line: "\x20..." while reading client request headers
[error]
--- skip_nginx
3: < 1.21.1
=== TEST 35: bugfix: invalid http request
--- log_level: error
--- http_config
lua_package_path "../lua-resty-core/lib/?.lua;;";
--- config
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_SERVER_PORT)
if not ok then
ngx.log(ngx.ERR, "failed to connect to memc: ", err)
return
end
sock:send("\n")
sock:close()
ngx.say("OK")
}
}
log_by_lua_block {
local h = ngx.req.raw_header()
}
--- request
GET /t
--- response_body
OK
--- no_error_log
[error]

View File

@ -336,7 +336,7 @@ lua found 100 pending timers
lua_shared_dict test_dict 1m;
server {
listen 12355;
listen $TEST_NGINX_RAND_PORT_1;
location = /foo {
echo 'foo';
}
@ -350,7 +350,7 @@ lua found 100 pending timers
-- Connect the socket
local sock = ngx.socket.tcp()
local ok,err = sock:connect("127.0.0.1", 12355)
local ok,err = sock:connect("127.0.0.1", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.log(ngx.ERR, err)
end

View File

@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 3);
plan tests => repeat_each() * (blocks() * 4 - 4);
#no_diff();
no_long_string();
@ -79,3 +79,33 @@ worker pid: \d+
worker pid is correct\.
--- no_error_log
[error]
=== TEST 4: content_by_lua + ngx.worker.pids
--- config
location /lua {
content_by_lua '
local pids = ngx.worker.pids()
local pid = ngx.worker.pid()
ngx.say("worker pid: ", pid)
local count = ngx.worker.count()
if count ~= #pids then
ngx.say("worker pids is wrong.")
end
for i = 1, count do
if pids[i] == pid then
ngx.say("worker pid is correct.")
return
end
end
ngx.say("worker pid is wrong.")
';
}
--- request
GET /lua
--- response_body_like
worker pid: \d+
worker pid is correct\.
--- no_error_log
[error]

View File

@ -842,6 +842,11 @@ lua close the global Lua VM \3 in the cache helper process \d+
lua close the global Lua VM \3
lua close the global Lua VM \3 in the cache helper process \d+
)(?:lua close the global Lua VM [0-9A-F]+
|lua close the global Lua VM ([0-9A-F]+)
lua close the global Lua VM \4 in the cache helper process \d+
lua close the global Lua VM \4 in the cache helper process \d+
lua close the global Lua VM \4
lua close the global Lua VM \4
)*\z/
--- no_error_log
[error]
@ -975,3 +980,53 @@ qr/lua close the global Lua VM ([0-9A-F]+)$/,
--- no_error_log
[error]
start privileged agent process
=== TEST 25: syntax error in init_worker_by_lua_block
--- http_config
init_worker_by_lua_block {
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
}
--- config
location /t {
content_by_lua_block {
ngx.say("hello world")
}
}
--- request
GET /t
--- response_body
hello world
--- error_log
init_worker_by_lua error: init_worker_by_lua(nginx.conf:25):4: ')' expected (to close '(' at line 3) near 'ngx'
--- no_error_log
no_such_error_log
=== TEST 26: syntax error in init_worker_by_lua_file
--- http_config
init_worker_by_lua_file html/init.lua;
--- config
location /t {
content_by_lua_block {
ngx.say("hello world")
}
}
--- user_files
>>> init.lua
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
--- request
GET /t
--- response_body
hello world
--- error_log eval
qr|init_worker_by_lua_file error: .*?t/servroot\w*/html/init.lua:3: '\)' expected \(to close '\(' at line 2\) near 'ngx'|
--- no_error_log
no_such_error_log

View File

@ -39,7 +39,7 @@ run_tests();
__DATA__
=== TEST 1: www.google.com
=== TEST 1: www.bing.com
--- config
server_tokens off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
@ -48,7 +48,7 @@ __DATA__
set $port $TEST_NGINX_MEMCACHED_PORT;
content_by_lua '
-- avoid flushing google in "check leak" testing mode:
-- avoid flushing bing in "check leak" testing mode:
local counter = package.loaded.counter
if not counter then
counter = 1
@ -62,7 +62,7 @@ __DATA__
do
local sock = ngx.socket.tcp()
sock:settimeout(2000)
local ok, err = sock:connect("www.google.com", 443)
local ok, err = sock:connect("www.bing.com", 443)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -78,7 +78,7 @@ __DATA__
ngx.say("ssl handshake: ", type(sess))
local req = "GET / HTTP/1.1\\r\\nHost: www.google.com\\r\\nConnection: close\\r\\n\\r\\n"
local req = "GET / HTTP/1.1\\r\\nHost: www.bing.com\\r\\nConnection: close\\r\\n\\r\\n"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send http request: ", err)
@ -106,8 +106,8 @@ __DATA__
GET /t
--- response_body_like chop
\Aconnected: 1
ssl handshake: userdata
sent http request: 59 bytes.
ssl handshake: cdata
sent http request: 57 bytes.
received: HTTP/1.1 (?:200 OK|302 Found)
close: 1 nil
\z
@ -190,7 +190,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 53 bytes.
received: HTTP/1.1 201 Created
close: 1 nil
@ -271,7 +271,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 58 bytes.
received: HTTP/1.1 302 Moved Temporarily
close: 1 nil
@ -355,12 +355,12 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 200 OK
close: 1 nil
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 200 OK
close: 1 nil
@ -603,7 +603,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 80 bytes.
received: HTTP/1.1 404 Not Found
close: 1 nil
@ -688,7 +688,7 @@ $::DSTRootCertificate"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 58 bytes.
received: HTTP/1.1 302 Moved Temporarily
close: 1 nil
@ -1008,7 +1008,7 @@ $::DSTRootCertificate"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 58 bytes.
received: HTTP/1.1 302 Moved Temporarily
close: 1 nil
@ -1087,7 +1087,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 58 bytes.
received: HTTP/1.1 302 Moved Temporarily
close: 1 nil
@ -1179,7 +1179,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 53 bytes.
received: HTTP/1.1 200 OK
close: 1 nil
@ -1269,7 +1269,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 53 bytes.
received: HTTP/1.1 200 OK
close: 1 nil
@ -1418,13 +1418,13 @@ $::DSTRootCertificate"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
--- log_level: debug
@ -1494,13 +1494,13 @@ $::DSTRootCertificate"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
connected: 1
ssl handshake: userdata
ssl handshake: cdata
set keepalive: 1 nil
--- log_level: debug
@ -1637,7 +1637,7 @@ attempt to call method 'sslhandshake' (a nil value)
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1742,7 +1742,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2031,8 +2031,8 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: userdata
ssl handshake: cdata
ssl handshake: cdata
sent http request: 58 bytes.
received: HTTP/1.1 302 Moved Temporarily
close: 1 nil
@ -2232,7 +2232,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- user_files eval
">>> test.key
@ -2405,7 +2405,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2529,7 +2529,7 @@ SSL reused session
=== TEST 31: handshake, too many arguments
=== TEST 31: handshake, too few arguments
--- config
server_tokens off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
@ -2633,7 +2633,7 @@ qr/\[error\] .* ngx.socket sslhandshake: expecting 1 ~ 5 arguments \(including t
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 53 bytes.
received: HTTP/1.1 200 OK
close: 1 nil
@ -2726,7 +2726,7 @@ SSL reused session
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 53 bytes.
received: HTTP/1.1 200 OK
close: 1 nil

View File

@ -38,7 +38,7 @@ __DATA__
--- error_code: 502
--- error_log eval
[
'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,',
'[lua] balancer_by_lua(nginx.conf:27):2: hello from balancer by lua! while connecting to upstream,',
qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"},
]
--- no_error_log
@ -64,7 +64,7 @@ qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\
--- response_body_like: 403 Forbidden
--- error_code: 403
--- error_log
[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,
[lua] balancer_by_lua(nginx.conf:27):2: hello from balancer by lua! while connecting to upstream,
--- no_error_log eval
[
'[warn]',
@ -92,7 +92,7 @@ qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\
--- error_code: 502
--- error_log eval
[
'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,',
'[lua] balancer_by_lua(nginx.conf:27):2: hello from balancer by lua! while connecting to upstream,',
qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"},
]
--- no_error_log
@ -257,7 +257,7 @@ qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua:2: API disabled in the context of balancer_by_lua\*/
qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua\(nginx\.conf:27\):2: API disabled in the context of balancer_by_lua\*/
@ -278,7 +278,7 @@ qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua:2: API disable
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua:2: API disabled in the context of balancer_by_lua\*/
qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua\(nginx\.conf:27\):2: API disabled in the context of balancer_by_lua\*/
@ -427,7 +427,7 @@ ctx counter: nil
--- error_code: 502
--- error_log eval
[
'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,',
'[lua] balancer_by_lua(nginx.conf:27):2: hello from balancer by lua! while connecting to upstream,',
qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"},
]
--- no_error_log
@ -535,7 +535,7 @@ failed to set more tries: reduced tries due to limit
lua_package_path "../lua-resty-core/lib/?.lua;;";
server {
listen 127.0.0.1:8888;
listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1;
location / {
return 200 "it works";
@ -543,8 +543,8 @@ failed to set more tries: reduced tries due to limit
}
upstream foo {
server 127.0.0.1:8888 max_fails=0;
server 127.0.0.1:8889 max_fails=0 weight=9999;
server 127.0.0.1:$TEST_NGINX_RAND_PORT_1 max_fails=0;
server 127.0.0.1:$TEST_NGINX_RAND_PORT_2 max_fails=0 weight=9999;
balancer_by_lua_block {
local bal = require "ngx.balancer"
@ -567,3 +567,26 @@ connect() failed (111: Connection refused) while connecting to upstream
--- no_error_log
upstream sent more data than specified in "Content-Length" header while reading upstream
[alert]
=== TEST 18: error in balancer_by_llua_block
--- http_config
upstream backend {
server 0.0.0.1;
balancer_by_lua_block {
ngx.say("hello"
}
}
--- config
location = /t {
proxy_pass http://backend;
}
--- request
GET /t
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
"failed to load inlined Lua code: balancer_by_lua(nginx.conf:27):3: ')' expected (to close '(' at line 2) near '<eof>'",
--- no_error_log
[warn]

View File

@ -100,7 +100,7 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -117,18 +117,18 @@ lua ssl server name: "test.com"
--- no_error_log
[error]
[alert]
--- grep_error_log eval: qr/ssl_certificate_by_lua:.*?,|\bssl cert: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log eval: qr/ssl_certificate_by_lua\(nginx.conf:\d+\):.*?,|\bssl cert: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log_out eval
# Since nginx version 1.17.9, nginx call ngx_reusable_connection(c, 0)
# before call ssl callback function
$Test::Nginx::Util::NginxVersion >= 1.017009 ?
qr/reusable connection: 0
ssl cert: connection reusable: 0
ssl_certificate_by_lua:1: ssl cert by lua is running!,/
ssl_certificate_by_lua\(nginx.conf:28\):1: ssl cert by lua is running!,/
: qr /reusable connection: 1
ssl cert: connection reusable: 1
reusable connection: 0
ssl_certificate_by_lua:1: ssl cert by lua is running!,/
ssl_certificate_by_lua\(nginx.conf:28\):1: ssl cert by lua is running!,/
@ -209,7 +209,7 @@ ssl_certificate_by_lua:1: ssl cert by lua is running!,/
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -314,7 +314,7 @@ qr/elapsed in ssl cert by lua: 0.(?:09|1\d)\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -432,7 +432,7 @@ my timer run!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -456,7 +456,7 @@ received memc reply: OK
=== TEST 5: ngx.exit(0) - no yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
ngx.exit(0)
@ -484,7 +484,7 @@ received memc reply: OK
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -523,7 +523,7 @@ should never reached here
=== TEST 6: ngx.exit(ngx.ERROR) - no yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
ngx.exit(ngx.ERROR)
@ -551,7 +551,7 @@ should never reached here
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -593,7 +593,7 @@ should never reached here
=== TEST 7: ngx.exit(0) - yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
ngx.sleep(0.001)
@ -623,7 +623,7 @@ should never reached here
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -662,7 +662,7 @@ should never reached here
=== TEST 8: ngx.exit(ngx.ERROR) - yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
ngx.sleep(0.001)
@ -692,7 +692,7 @@ should never reached here
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -734,7 +734,7 @@ should never reached here
=== TEST 9: lua exception - no yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
error("bad bad bad")
@ -762,7 +762,7 @@ should never reached here
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -789,7 +789,7 @@ failed to do SSL handshake: handshake failed
--- error_log eval
[
'runtime error: ssl_certificate_by_lua:2: bad bad bad',
'runtime error: ssl_certificate_by_lua(nginx.conf:28):2: bad bad bad',
'lua_certificate_by_lua: handler return value: 500, cert cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?cert cb error/,
qr/context: ssl_certificate_by_lua\*, client: \d+\.\d+\.\d+\.\d+, server: \d+\.\d+\.\d+\.\d+:\d+/,
@ -805,7 +805,7 @@ should never reached here
=== TEST 10: lua exception - yield
--- http_config
server {
listen 127.0.0.2:8080 ssl;
listen 127.0.0.2:$TEST_NGINX_RAND_PORT_1 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
ngx.sleep(0.001)
@ -834,7 +834,7 @@ should never reached here
sock:settimeout(2000)
local ok, err = sock:connect("127.0.0.2", 8080)
local ok, err = sock:connect("127.0.0.2", $TEST_NGINX_RAND_PORT_1)
if not ok then
ngx.say("failed to connect: ", err)
return
@ -861,7 +861,7 @@ failed to do SSL handshake: handshake failed
--- error_log eval
[
'runtime error: ssl_certificate_by_lua:3: bad bad bad',
'runtime error: ssl_certificate_by_lua(nginx.conf:28):3: bad bad bad',
'lua_certificate_by_lua: cert cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?cert cb error/,
]
@ -924,7 +924,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- error_log
lua ssl server name: "test.com"
@ -1050,7 +1050,7 @@ failed to do SSL handshake: handshake failed
--- error_log eval
[
'lua ssl server name: "test.com"',
'ssl_certificate_by_lua:1: API disabled in the context of ssl_certificate_by_lua*',
'ssl_certificate_by_lua(nginx.conf:28):1: API disabled in the context of ssl_certificate_by_lua*',
qr/\[info\] .*?cert cb error/,
]
@ -1137,7 +1137,7 @@ print("ssl cert by lua is running!")
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1248,7 +1248,7 @@ a.lua:1: ssl cert by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1372,7 +1372,7 @@ lua ssl server name: "test.com"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1468,7 +1468,7 @@ GitHub openresty/lua-resty-core#42
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1481,7 +1481,7 @@ close: 1 nil
--- error_log
lua ssl server name: "test.com"
ssl_certificate_by_lua:1: ssl cert by lua is running!
ssl_certificate_by_lua(nginx.conf:25):1: ssl cert by lua is running!
--- no_error_log
[error]
@ -1566,7 +1566,7 @@ github issue #723
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1668,7 +1668,7 @@ ssl_certificate_by_lua:1: ssl cert by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 59 bytes.
received: HTTP/1.1 200 OK
received: Server: nginx
@ -1681,7 +1681,7 @@ close: 1 nil
--- error_log eval
[
'ssl_certificate_by_lua:1: ssl cert by lua is running!',
'ssl_certificate_by_lua(nginx.conf:29):1: ssl cert by lua is running!',
'lua ssl server name: "test.com"',
]
--- no_error_log
@ -1963,7 +1963,7 @@ qr/\[info\] .*? SSL_do_handshake\(\) failed\b/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2063,7 +2063,7 @@ client ip: 127.0.0.1
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2221,7 +2221,7 @@ qr/elapsed in ssl_certificate_by_lua\*: 0\.(?:09|1\d)\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- no_error_log
[error]
[alert]
@ -2311,7 +2311,7 @@ ssl handshake: userdata
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- no_error_log
[error]
[alert]

View File

@ -36,7 +36,8 @@ ffi.cdef[[
size_t pem_len, unsigned char *der, char **err);
int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem,
size_t pem_len, unsigned char *der, char **err);
size_t pem_len, const unsigned char *passphrase,
unsigned char *der, char **err);
int ngx_http_lua_ffi_ssl_set_der_certificate(void *r,
const char *data, size_t len, char **err);
@ -58,12 +59,12 @@ ffi.cdef[[
int ngx_http_lua_ffi_set_priv_key(void *r,
void *cdata, char **err);
void *ngx_http_lua_ffi_get_req_ssl_pointer(void *r);
void ngx_http_lua_ffi_free_cert(void *cdata);
void ngx_http_lua_ffi_free_priv_key(void *cdata);
int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err);
int ngx_http_lua_ffi_ssl_verify_client(void *r, void *cdata,
int depth, char **err);
@ -132,7 +133,7 @@ __DATA__
out = ffi.new("char [?]", #pkey)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
if rc < 1 then
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
ffi.string(errmsg[0]))
@ -216,7 +217,7 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -286,7 +287,7 @@ lua ssl server name: "test.com"
out = ffi.new("char [?]", #pkey)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
if rc < 1 then
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
ffi.string(errmsg[0]))
@ -370,7 +371,7 @@ lua ssl server name: "test.com"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -424,7 +425,7 @@ lua ssl server name: "test.com"
out = ffi.new("char [?]", #pkey)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
if rc < 1 then
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
ffi.string(errmsg[0]))
@ -498,7 +499,7 @@ lua ssl server name: "test.com"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -649,7 +650,7 @@ failed to parse PEM priv key: PEM_read_bio_PrivateKey() failed
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -799,7 +800,7 @@ lua ssl server name: "test.com"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1026,3 +1027,299 @@ client certificate subject: nil
--- no_error_log
[error]
[alert]
=== TEST 9: simple cert + private key with passphrase
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
server_name test.com;
ssl_certificate_by_lua_block {
collectgarbage()
local ffi = require "ffi"
ffi.cdef[[
int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem,
size_t pem_len, unsigned char *der, char **err);
int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem,
size_t pem_len, const unsigned char *passphrase,
unsigned char *der, char **err);
int ngx_http_lua_ffi_ssl_set_der_certificate(void *r,
const char *data, size_t len, char **err);
int ngx_http_lua_ffi_ssl_set_der_private_key(void *r,
const char *data, size_t len, char **err);
int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err);
]]
local errmsg = ffi.new("char *[1]")
local r = require "resty.core.base" .get_request()
if not r then
ngx.log(ngx.ERR, "no request found")
return
end
ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg)
local f = assert(io.open("t/cert/test_passphrase.crt", "rb"))
local cert = f:read("*all")
f:close()
local out = ffi.new("char [?]", #cert)
local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg)
if rc < 1 then
ngx.log(ngx.ERR, "failed to parse PEM cert: ",
ffi.string(errmsg[0]))
return
end
local cert_der = ffi.string(out, rc)
local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg)
if rc ~= 0 then
ngx.log(ngx.ERR, "failed to set DER cert: ",
ffi.string(errmsg[0]))
return
end
f = assert(io.open("t/cert/test_passphrase.key", "rb"))
local pkey = f:read("*all")
f:close()
local passphrase = "123456"
out = ffi.new("char [?]", #pkey)
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, passphrase, out, errmsg)
if rc < 1 then
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
ffi.string(errmsg[0]))
return
end
local pkey_der = ffi.string(out, rc)
local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg)
if rc ~= 0 then
ngx.log(ngx.ERR, "failed to set DER priv key: ",
ffi.string(errmsg[0]))
return
end
}
ssl_certificate ../../cert/test2.crt;
ssl_certificate_key ../../cert/test2.key;
server_tokens off;
location /foo {
default_type 'text/plain';
content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
more_clear_headers Date;
}
}
--- config
server_tokens off;
lua_ssl_trusted_certificate ../../cert/test_passphrase.crt;
location /t {
content_by_lua_block {
do
local sock = ngx.socket.tcp()
sock:settimeout(2000)
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local sess, err = sock:sslhandshake(nil, "test.com", false)
if not sess then
ngx.say("failed to do SSL handshake: ", err)
return
end
ngx.say("ssl handshake: ", type(sess))
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send http request: ", err)
return
end
ngx.say("sent http request: ", bytes, " bytes.")
while true do
local line, err = sock:receive()
if not line then
-- ngx.say("failed to recieve response status line: ", err)
break
end
ngx.say("received: ", line)
end
local ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
end -- do
-- collectgarbage()
}
}
--- request
GET /t
--- response_body
connected: 1
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
close: 1 nil
--- error_log
lua ssl server name: "test.com"
--- no_error_log
[error]
[alert]
=== TEST 10: Raw SSL pointer
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
server_name test.com;
ssl_certificate_by_lua_block {
collectgarbage()
local ffi = require "ffi"
require "defines"
local r = require "resty.core.base" .get_request()
if not r then
ngx.log(ngx.ERR, "no request found")
return
end
local ssl = ffi.C.ngx_http_lua_ffi_get_req_ssl_pointer(r);
if ssl == nil then
ngx.log(ngx.ERR, "failed to retrieve SSL*")
return
end
ffi.cdef[[
const char *SSL_get_servername(const void *, const int);
]]
local TLSEXT_NAMETYPE_host_name = 0
local sni = ffi.C.SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)
if sni == nil then
ngx.log(ngx.ERR, "failed to get sni")
return
end
ngx.log(ngx.INFO, "SNI is ", ffi.string(sni))
}
ssl_certificate ../../cert/test.crt;
ssl_certificate_key ../../cert/test.key;
server_tokens off;
location /foo {
default_type 'text/plain';
content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
more_clear_headers Date;
}
}
--- config
server_tokens off;
lua_ssl_trusted_certificate ../../cert/test.crt;
location /t {
content_by_lua_block {
do
local sock = ngx.socket.tcp()
sock:settimeout(2000)
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local sess, err = sock:sslhandshake(nil, "test.com", true)
if not sess then
ngx.say("failed to do SSL handshake: ", err)
return
end
ngx.say("ssl handshake: ", type(sess))
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send http request: ", err)
return
end
ngx.say("sent http request: ", bytes, " bytes.")
while true do
local line, err = sock:receive()
if not line then
-- ngx.say("failed to receive response status line: ", err)
break
end
ngx.say("received: ", line)
end
local ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
end -- do
-- collectgarbage()
}
}
--- request
GET /t
--- response_body
connected: 1
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
close: 1 nil
--- error_log
SNI is test.com
--- no_error_log
[error]
[alert]

View File

@ -77,7 +77,7 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -86,11 +86,11 @@ lua ssl server name: "test.com"
--- no_error_log
[error]
[alert]
--- grep_error_log eval: qr/ssl_session_store_by_lua_block:.*?,|\bssl session store: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log eval: qr/ssl_session_store_by_lua\(nginx.conf:\d+\):.*?,|\bssl session store: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log_out eval
qr/^reusable connection: 0
ssl session store: connection reusable: 0
ssl_session_store_by_lua_block:1: ssl session store by lua is running!,
ssl_session_store_by_lua\(nginx\.conf:25\):1: ssl session store by lua is running!,
/m,
@ -152,7 +152,7 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running!,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -227,7 +227,7 @@ API disabled in the context of ssl_session_store_by_lua*
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -319,7 +319,7 @@ my timer run!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -390,7 +390,7 @@ API disabled in the context of ssl_session_store_by_lua*
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -462,7 +462,7 @@ ngx.exit does not yield and the error code is eaten.
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -532,11 +532,11 @@ ssl_session_store_by_lua*: handler return value: 0, sess new cb exit code: 0
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
failed to run session_store_by_lua*: ssl_session_store_by_lua_block:2: bad bad bad
failed to run session_store_by_lua*: ssl_session_store_by_lua(nginx.conf:25):2: bad bad bad
--- no_error_log
should never reached here
@ -600,7 +600,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -671,14 +671,14 @@ get_phase: ssl_session_store
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log eval
[
'lua ssl server name: "test.com"',
qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/,
'ssl_session_store_by_lua_block:1: ssl store session by lua is running!',
'ssl_session_store_by_lua(nginx.conf:25):1: ssl store session by lua is running!',
]
--- no_error_log
@ -744,7 +744,7 @@ print("ssl store session by lua is running!")
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
@ -820,7 +820,7 @@ a.lua:1: ssl store session by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- no_error_log
@ -891,12 +891,12 @@ qr/\[emerg\] .*? "ssl_session_store_by_lua_block" directive is not allowed here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log
lua ssl server name: "test.com"
ssl_session_store_by_lua_block:1: ssl session store by lua is running!
ssl_session_store_by_lua(nginx.conf:25):1: ssl session store by lua is running!
--- no_error_log
[error]
@ -955,7 +955,7 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- error_log eval
qr/ssl_session_store_by_lua\*: skipped since TLS version >= 1\.3 \(\d+\)/

View File

@ -80,10 +80,10 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval: qr/ssl_session_fetch_by_lua_block:.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log eval: qr/ssl_session_fetch_by_lua\(nginx\.conf:\d+\):.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log_out eval
# Since nginx version 1.17.9, nginx call ngx_reusable_connection(c, 0)
@ -93,11 +93,11 @@ $Test::Nginx::Util::NginxVersion >= 1.017009 ?
qr/\A(?:reusable connection: [01]\n)+\z/s,
qr/^reusable connection: 0
ssl session fetch: connection reusable: 0
ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!,
ssl_session_fetch_by_lua\(nginx\.conf:25\):1: ssl fetch sess by lua is running!,
/m,
qr/^reusable connection: 0
ssl session fetch: connection reusable: 0
ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!,
ssl_session_fetch_by_lua\(nginx\.conf:25\):1: ssl fetch sess by lua is running!,
/m,
]
:
@ -106,12 +106,12 @@ qr/\A(?:reusable connection: [01]\n)+\z/s,
qr/^reusable connection: 1
ssl session fetch: connection reusable: 1
reusable connection: 0
ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!,
ssl_session_fetch_by_lua\(nginx\.conf:25\):1: ssl fetch sess by lua is running!,
/m,
qr/^reusable connection: 1
ssl session fetch: connection reusable: 1
reusable connection: 0
ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!,
ssl_session_fetch_by_lua\(nginx\.conf:25\):1: ssl fetch sess by lua is running!,
/m,
]
--- no_error_log
@ -180,7 +180,7 @@ ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -264,7 +264,7 @@ qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -365,7 +365,7 @@ qr/my timer run!/s
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -446,7 +446,7 @@ qr/received memc reply: OK/s
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -527,7 +527,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -609,7 +609,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -690,18 +690,18 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
qr/ssl_session_fetch_by_lua_block:2: bad bad bad/s
qr/ssl_session_fetch_by_lua\(nginx.conf:\d+\):2: bad bad bad/s
--- grep_error_log_out eval
[
'',
'ssl_session_fetch_by_lua_block:2: bad bad bad
'ssl_session_fetch_by_lua(nginx.conf:25):2: bad bad bad
',
'ssl_session_fetch_by_lua_block:2: bad bad bad
'ssl_session_fetch_by_lua(nginx.conf:25):2: bad bad bad
',
]
@ -773,19 +773,19 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
qr/ssl_session_fetch_by_lua_block:3: bad bad bad|ssl_session_fetch_by_lua\*: sess get cb exit code: 0/s
qr/ssl_session_fetch_by_lua\(nginx.conf:\d+\):3: bad bad bad|ssl_session_fetch_by_lua\*: sess get cb exit code: 0/s
--- grep_error_log_out eval
[
'',
'ssl_session_fetch_by_lua_block:3: bad bad bad
'ssl_session_fetch_by_lua(nginx.conf:25):3: bad bad bad
ssl_session_fetch_by_lua*: sess get cb exit code: 0
',
'ssl_session_fetch_by_lua_block:3: bad bad bad
'ssl_session_fetch_by_lua(nginx.conf:25):3: bad bad bad
ssl_session_fetch_by_lua*: sess get cb exit code: 0
',
@ -853,7 +853,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -939,7 +939,7 @@ qr/get_phase: ssl_session_fetch/s
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -1025,7 +1025,7 @@ print("ssl fetch sess by lua is running!")
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
@ -1109,18 +1109,18 @@ qr/\S+:\d+: ssl fetch sess by lua is running!/s
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s
qr/ssl_session_fetch_by_lua\(nginx.conf:\d+\):1: ssl fetch sess by lua is running!/s
--- grep_error_log_out eval
[
'',
'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!
'ssl_session_fetch_by_lua(nginx.conf:25):1: ssl fetch sess by lua is running!
',
'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!
'ssl_session_fetch_by_lua(nginx.conf:25):1: ssl fetch sess by lua is running!
',
]
@ -1285,7 +1285,7 @@ GET /t
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- no_error_log
[warn]
@ -1346,9 +1346,9 @@ close: 1 nil
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval: qr/ssl_session_fetch_by_lua_block:.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log eval: qr/ssl_session_fetch_by_lua\(nginx\.conf:\d+\):.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/
--- grep_error_log_out eval
# Since nginx version 1.17.9, nginx call ngx_reusable_connection(c, 0)
# before call ssl callback function
@ -1357,11 +1357,11 @@ $Test::Nginx::Util::NginxVersion >= 1.017009 ?
qr/\A(?:reusable connection: [01]\n)+\z/s,
qr/^reusable connection: 0
ssl session fetch: connection reusable: 0
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
ssl_session_fetch_by_lua\(nginx\.conf:\d+\):1: ssl_session_fetch_by_lua\* is running!,
/m,
qr/^reusable connection: 0
ssl session fetch: connection reusable: 0
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
ssl_session_fetch_by_lua\(nginx\.conf:\d+\):1: ssl_session_fetch_by_lua\* is running!,
/m,
]
:
@ -1370,12 +1370,12 @@ qr/\A(?:reusable connection: [01]\n)+\z/s,
qr/^reusable connection: 1
ssl session fetch: connection reusable: 1
reusable connection: 0
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
ssl_session_fetch_by_lua\(nginx\.conf:\d+\):1: ssl_session_fetch_by_lua\* is running!,
/m,
qr/^reusable connection: 1
ssl session fetch: connection reusable: 1
reusable connection: 0
ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
ssl_session_fetch_by_lua\(nginx\.conf:\d+\):1: ssl_session_fetch_by_lua\* is running!,
/m,
]
--- no_error_log
@ -1444,7 +1444,7 @@ ssl_session_fetch_by_lua_block:1: ssl_session_fetch_by_lua\* is running!,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval
qr/elapsed in ssl_session_fetch_by_lua\*: 0\.(?:09|1[01])\d+,/,
@ -1537,7 +1537,7 @@ qr/elapsed in ssl_session_fetch_by_lua\*: 0\.(?:09|1[01])\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval: qr/received memc reply of \d+ bytes/
--- grep_error_log_out eval
@ -1632,7 +1632,7 @@ close: 1 nil
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval: qr/uthread: [^.,]+/
--- grep_error_log_out eval
@ -1732,7 +1732,7 @@ uthread: failed to kill: already waited or killed
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
close: 1 nil
--- grep_error_log eval: qr/uthread: [^.,]+/
--- grep_error_log_out eval

View File

@ -827,3 +827,27 @@ GET /test
aa list value: nil
--- no_error_log
[error]
=== TEST 22: lpush return nil
--- http_config
lua_shared_dict dogs 100k;
--- config
location = /test {
content_by_lua_block {
local dogs = ngx.shared.dogs
for i = 1, 2920
do
local len, err = dogs:lpush("foo", "bar")
end
local len, err = dogs:lpush("foo", "bar")
ngx.say(len)
}
}
--- request
GET /test
--- response_body
nil
--- no_error_log
[error]

View File

@ -91,7 +91,7 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- user_files eval
">>> test.key

View File

@ -60,10 +60,10 @@ __DATA__
--- response_body_like chomp
\A[12]\n\z
--- grep_error_log eval
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|set_by_lua:\d+: in main chunk, )/
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|set_by_lua\(nginx.conf:\d+\):\d+: in main chunk, )/
--- grep_error_log_out eval
[qr/\A\[warn\] .*?writing a global Lua variable \('foo'\)
set_by_lua:3: in main chunk, \n\z/, "old foo: 1\n"]
set_by_lua\(nginx.conf:40\):3: in main chunk, \n\z/, "old foo: 1\n"]
@ -154,10 +154,10 @@ content_by_lua\(nginx\.conf:\d+\):\d+: in main chunk, \n\z/, "old foo: 1\n"]
--- response_body_like chomp
\A(?:nil|1)\n\z
--- grep_error_log eval
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua:\d+: in main chunk, )/
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua\(nginx\.conf:\d+\):\d+: in main chunk, )/
--- grep_error_log_out eval
[qr/\A\[warn\] .*?writing a global Lua variable \('foo'\)
header_filter_by_lua:3: in main chunk, \n\z/, "old foo: 1\n"]
header_filter_by_lua\(nginx.conf:43\):3: in main chunk, \n\z/, "old foo: 1\n"]
@ -179,10 +179,10 @@ header_filter_by_lua:3: in main chunk, \n\z/, "old foo: 1\n"]
--- response_body_like chomp
\A(?:nil|2)\n\z
--- grep_error_log eval
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua:\d+: in main chunk,)/
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua\(nginx\.conf:\d+\):\d+: in main chunk,)/
--- grep_error_log_out eval
[qr/\[warn\] .*?writing a global Lua variable \('foo'\)
body_filter_by_lua:3: in main chunk,
body_filter_by_lua\(nginx.conf:43\):3: in main chunk,
old foo: 1\n\z/, "old foo: 2\nold foo: 3\n"]
@ -297,10 +297,10 @@ log_by_lua\(nginx\.conf:\d+\):\d+: in main chunk\n\z/, "old foo: 1\n"]
--- response_body_like chomp
\A[12]done\n\z
--- grep_error_log eval
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua:\d+: in main chunk)/
qr/(old foo: \d+|\[\w+\].*?writing a global Lua variable \('[^'\s]+'\)|\w+_by_lua\(nginx.conf:\d+\):\d+: in main chunk)/
--- grep_error_log_out eval
[qr/\A\[warn\] .*?writing a global Lua variable \('foo'\)
ssl_certificate_by_lua:3: in main chunk\n\z/, "old foo: 1\n"]
ssl_certificate_by_lua\(nginx.conf:28\):3: in main chunk\n\z/, "old foo: 1\n"]

View File

@ -12,6 +12,9 @@ my $http_config = <<_EOC_;
function set_up_ngx_tmp_conf(conf)
if conf == nil then
conf = [[
# to prevent the test process from overwriting the
# original pid file
pid logs/test_nginx.pid;
events {
worker_connections 64;
}
@ -150,6 +153,7 @@ qr/\[error\] .*? init_by_lua:\d+: run init_by_lua/
location = /t {
content_by_lua_block {
local conf = [[
pid logs/test_nginx.pid;
events {
worker_connections 64;
}

View File

@ -6,7 +6,7 @@ master_on();
repeat_each(2);
# NB: the shutdown_error_log block is independent from repeat times
plan tests => repeat_each() * (blocks() * 2 + 1) + 13;
plan tests => repeat_each() * (blocks() * 2 + 1) + 15;
#log_level("warn");
no_long_string();
@ -194,3 +194,49 @@ qr/cache loader process \d+ exited/,
qr/cache manager process \d+ exited/,
qr/hello from exit worker by lua, process type: worker/,
]
=== TEST 8: syntax error in exit_worker_by_lua_block
--- http_config
exit_worker_by_lua_block {
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
}
--- config
location /t {
content_by_lua_block {
ngx.say("hello world")
}
}
--- request
GET /t
--- response_body
hello world
--- shutdown_error_log
exit_worker_by_lua error: exit_worker_by_lua(nginx.conf:25):4: ')' expected (to close '(' at line 3) near 'ngx'
=== TEST 9: syntax error in exit_worker_by_lua_file
--- http_config
exit_worker_by_lua_file html/exit.lua;
--- config
location /t {
content_by_lua_block {
ngx.say("hello world")
}
}
--- user_files
>>> exit.lua
ngx.log(ngx.debug, "pass")
error("failed to init"
ngx.log(ngx.debug, "unreachable")
--- request
GET /t
--- response_body
hello world
--- shutdown_error_log eval
qr|exit_worker_by_lua_file error: .*?t/servroot\w*/html/exit.lua:3: '\)' expected \(to close '\(' at line 2\) near 'ngx'|

View File

@ -0,0 +1,373 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * 43;
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
log_level 'debug';
no_long_string();
#no_diff();
sub read_file {
my $infile = shift;
open my $in, $infile
or die "cannot open $infile for reading: $!";
my $cert = do { local $/; <$in> };
close $in;
$cert;
}
our $MTLSCA = read_file("t/cert/mtls_ca.crt");
our $MTLSClient = read_file("t/cert/mtls_client.crt");
our $MTLSClientKey = read_file("t/cert/mtls_client.key");
our $MTLSServer = read_file("t/cert/mtls_server.crt");
our $MTLSServerKey = read_file("t/cert/mtls_server.key");
our $HtmlDir = html_dir;
our $mtls_http_config = <<"_EOC_";
server {
listen unix:$::HtmlDir/mtls.sock ssl;
ssl_certificate $::HtmlDir/mtls_server.crt;
ssl_certificate_key $::HtmlDir/mtls_server.key;
ssl_client_certificate $::HtmlDir/mtls_ca.crt;
ssl_verify_client on;
server_tokens off;
location / {
return 200 "hello, \$ssl_client_s_dn";
}
}
_EOC_
our $mtls_user_files = <<"_EOC_";
>>> mtls_server.key
$::MTLSServerKey
>>> mtls_server.crt
$::MTLSServer
>>> mtls_ca.crt
$::MTLSCA
>>> mtls_client.key
$::MTLSClientKey
>>> mtls_client.crt
$::MTLSClient
_EOC_
run_tests();
__DATA__
=== TEST 1: sanity: www.bing.com
--- config
server_tokens off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
content_by_lua_block {
-- avoid flushing bing in "check leak" testing mode:
local counter = package.loaded.counter
if not counter then
counter = 1
elseif counter >= 2 then
return ngx.exit(503)
else
counter = counter + 1
end
package.loaded.counter = counter
do
local sock = ngx.socket.tcp()
sock:settimeout(2000)
local ok, err = sock:connect("www.bing.com", 443)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local sess, err = sock:sslhandshake()
if not sess then
ngx.say("failed to do SSL handshake: ", err)
return
end
ngx.say("ssl handshake: ", type(sess))
local req = "GET / HTTP/1.1\r\nHost: www.bing.com\r\nConnection: close\r\n\r\n"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send http request: ", err)
return
end
ngx.say("sent http request: ", bytes, " bytes.")
local line, err = sock:receive()
if not line then
ngx.say("failed to receive response status line: ", err)
return
end
ngx.say("received: ", line)
local ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
end -- do
collectgarbage()
}
}
--- request
GET /t
--- response_body_like chop
\Aconnected: 1
ssl handshake: cdata
sent http request: 57 bytes.
received: HTTP/1.1 (?:200 OK|302 Found)
close: 1 nil
\z
--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/
--- grep_error_log_out eval
qr/^lua ssl save session: ([0-9A-F]+)
lua ssl free session: ([0-9A-F]+)
$/
--- no_error_log
lua ssl server name:
SSL reused session
[error]
[alert]
--- timeout: 5
=== TEST 2: mutual TLS handshake, upstream is not accessible without client certs
--- http_config eval: $::mtls_http_config
--- config eval
"
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect('unix:$::HtmlDir/mtls.sock')
if not ok then
ngx.say('failed to connect: ', err)
end
assert(sock:sslhandshake())
ngx.say('connected: ', ok)
local req = 'GET /\\r\\n'
local bytes, err = sock:send(req)
if not bytes then
ngx.say('failed to send request: ', err)
return
end
ngx.say('request sent: ', bytes)
ngx.say(sock:receive('*a'))
assert(sock:close())
}
}
"
--- user_files eval: $::mtls_user_files
--- request
GET /t
--- response_body_like: 400 No required SSL certificate was sent
--- no_error_log
[alert]
[error]
[crit]
[emerg]
=== TEST 3: mutual TLS handshake, upstream is accessible with client certs
--- http_config eval: $::mtls_http_config
--- config eval
"
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect('unix:$::HtmlDir/mtls.sock')
if not ok then
ngx.say('failed to connect: ', err)
end
local f = assert(io.open('$::HtmlDir/mtls_client.crt'))
local cert_data = f:read('*a')
f:close()
f = assert(io.open('$::HtmlDir/mtls_client.key'))
local key_data = f:read('*a')
f:close()
local ssl = require('ngx.ssl')
local chain = assert(ssl.parse_pem_cert(cert_data))
local priv = assert(ssl.parse_pem_priv_key(key_data))
sock:setclientcert(chain, priv)
assert(sock:sslhandshake())
ngx.say('connected: ', ok)
local req = 'GET /\\r\\n'
local bytes, err = sock:send(req)
if not bytes then
ngx.say('failed to send request: ', err)
return
end
ngx.say('request sent: ', bytes)
ngx.say(sock:receive('*a'))
assert(sock:close())
}
}
"
--- user_files eval: $::mtls_user_files
--- request
GET /t
--- response_body
connected: 1
request sent: 7
hello, CN=foo@example.com,O=OpenResty,ST=California,C=US
--- no_error_log
[alert]
[error]
[crit]
[emerg]
=== TEST 4: incorrect type of client cert
--- config
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:setclientcert("doesnt", "work")
if not ok then
ngx.say('failed to setclientcert: ', err)
return
end
assert(sock:close())
}
}
--- request
GET /t
--- response_body
failed to setclientcert: bad cert arg: cdata expected, got string
--- no_error_log
[alert]
[error]
[crit]
[emerg]
=== TEST 5: incorrect type of client key
--- config eval
"
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local f = assert(io.open('$::HtmlDir/mtls_client.crt'))
local cert_data = f:read('*a')
f:close()
local ssl = require('ngx.ssl')
local chain = assert(ssl.parse_pem_cert(cert_data))
local ok, err = sock:setclientcert(chain, 'work')
if not ok then
ngx.say('failed to setclientcert: ', err)
return
end
assert(sock:close())
}
}
"
--- user_files eval: $::mtls_user_files
--- request
GET /t
--- response_body
failed to setclientcert: bad pkey arg: cdata expected, got string
--- no_error_log
[alert]
[error]
[crit]
[emerg]
=== TEST 6: missing client cert
--- config
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:setclientcert(nil, "work")
if not ok then
ngx.say('failed to setclientcert: ', err)
return
end
assert(sock:close())
}
}
--- request
GET /t
--- response_body
failed to setclientcert: client certificate must be supplied with corresponding private key
--- no_error_log
[alert]
[error]
[crit]
[emerg]
=== TEST 7: missing private key
--- config
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:setclientcert('doesnt', nil)
if not ok then
ngx.say('failed to setclientcert: ', err)
return
end
assert(sock:close())
}
}
--- request
GET /t
--- response_body
failed to setclientcert: client certificate must be supplied with corresponding private key
--- no_error_log
[alert]
[error]
[crit]
[emerg]

View File

@ -100,7 +100,7 @@ __DATA__
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -209,7 +209,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua is running!,/
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -314,7 +314,7 @@ qr/elapsed in ssl client hello by lua: 0.(?:09|1\d)\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -432,7 +432,7 @@ my timer run!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -924,7 +924,7 @@ should never reached here
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- error_log
lua ssl server name: "test.com"
@ -1135,7 +1135,7 @@ print("ssl client hello by lua is running!")
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1246,7 +1246,7 @@ a.lua:1: ssl client hello by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1370,7 +1370,7 @@ lua ssl server name: "test.com"
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1466,7 +1466,7 @@ GitHub openresty/lua-resty-core#42
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1561,7 +1561,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -1817,7 +1817,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2005,7 +2005,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 57 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2103,7 +2103,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua in server2 is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2208,7 +2208,7 @@ ssl_client_hello_by_lua:1: ssl client hello by lua is running!
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2308,7 +2308,7 @@ client ip: 127.0.0.1
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 201 Created
received: Server: nginx
@ -2465,7 +2465,7 @@ qr/elapsed in ssl_client_hello_by_lua\*: 0\.(?:09|1\d)\d+,/,
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- no_error_log
[error]
[alert]
@ -2555,7 +2555,7 @@ ssl handshake: userdata
GET /t
--- response_body
connected: 1
ssl handshake: userdata
ssl handshake: cdata
--- no_error_log
[error]
[alert]

View File

@ -229,7 +229,7 @@ return {hello=hello}
--- request
GET /hello
--- response_body
false : unsupported argument type
false : unsupported Lua type: LUA_TFUNCTION in the argument
@ -491,7 +491,7 @@ return {hello=hello}
--- request
GET /hello
--- response_body
false : unsupported argument type
false : unsupported Lua type: LUA_TFUNCTION in the argument
@ -524,7 +524,7 @@ return {hello=hello}
--- request
GET /hello
--- response_body
false , unsupported return value
false , unsupported Lua type: LUA_TFUNCTION in the return value
@ -1220,7 +1220,7 @@ GET /hello
location /write_log_file {
default_type 'text/plain';
content_by_lua_block {
access_by_lua_block {
local ok, err = ngx.run_worker_thread("testpool", "write_log_file", "log", ngx.var.arg_str)
if not ok then
ngx.say(ok, " : ", err)
@ -1246,3 +1246,513 @@ return {log=log}
GET /write_log_file?str=hello
--- response_body
true
=== TEST 40: shdict get, int value
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 10m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictget {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
local ok, err = ngx.run_worker_thread("testpool", "test_shdict", "dictget")
ngx.say(ok, ",", err)
}
}
--- user_files
>>> test_shdict.lua
local function dictget(str)
local dogs = ngx.shared.dogs
return dogs:get("Jim")
end
return {dictget=dictget}
--- request
GET /dictget
--- response_body
true,8
=== TEST 41: shdict set nil in main thread
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 10m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictget {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
local ok, err = ngx.run_worker_thread("testpool", "test_shdict", "dictget")
ngx.say(ok, ",", err)
dogs:set("Jim", nil)
local ok, err = ngx.run_worker_thread("testpool", "test_shdict", "dictget")
ngx.say(ok, ",", err)
}
}
--- user_files
>>> test_shdict.lua
local function dictget(str)
local dogs = ngx.shared.dogs
return dogs:get("Jim")
end
return {dictget=dictget}
--- request
GET /dictget
--- response_body
true,8
true,nil
=== TEST 42: shdict set nil in worker thread
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 10m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictsetnil {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
local ok, err = ngx.run_worker_thread("testpool", "test_shdict", "dictsetnil")
ngx.say(ok, ",", err)
ngx.say(ok, ",", dogs:get("Jim"))
}
}
--- user_files
>>> test_shdict.lua
local function dictsetnil(str)
local dogs = ngx.shared.dogs
return dogs:set("Jim", nil)
end
return {dictsetnil=dictsetnil}
--- request
GET /dictsetnil
--- response_body
true,true
true,nil
=== TEST 43: shdict get_stale
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 10m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictget {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8, 1)
ngx.sleep(2)
local ok, err = ngx.run_worker_thread("testpool", "test_shdict", "dictget")
ngx.say(ok, ",", err)
}
}
--- user_files
>>> test_shdict.lua
local function dictget(str)
local dogs = ngx.shared.dogs
return dogs:get_stale("Jim")
end
return {dictget=dictget}
--- request
GET /dictget
--- response_body
true,8
=== TEST 44: shdict add failed
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 10m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictadd {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
local ok, err, err2 = ngx.run_worker_thread("testpool", "test_shdict", "dictadd")
ngx.say(ok, ",", err, ",", err2)
}
}
--- user_files
>>> test_shdict.lua
local function dictadd(str)
local dogs = ngx.shared.dogs
local success, err = dogs:add("Jim", "hello")
return success, err
end
return {dictadd=dictadd}
--- request
GET /dictadd
--- response_body
true,false,exists
=== TEST 45: shdict force add
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictadd {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
local bigstr = string.rep("A", 1024*1024*3)
dogs:set("Jim", bigstr)
local ok, ret, err, forcible = ngx.run_worker_thread("testpool", "test_shdict", "dictadd")
ngx.say(ok, ",", ret, ",", forcible, ",", dogs:get("Jim"))
}
}
--- user_files
>>> test_shdict.lua
local function dictadd(str)
local dogs = ngx.shared.dogs
local bigstr = string.rep("A", 1024*1024*5)
local success, err, forcible = dogs:add("King", bigstr)
return success, err, forcible
end
return {dictadd=dictadd}
--- request
GET /dictadd
--- response_body
true,true,true,nil
=== TEST 46: shdict replace
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictreplace {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
local bigstr = string.rep("A", 1024*1024*3)
dogs:set("Jim", bigstr)
local ok, ret, err = ngx.run_worker_thread("testpool", "test_shdict", "dictreplace")
ngx.say(ok, ",", ret, ",", err, ",", dogs:get("Jim"))
}
}
--- user_files
>>> test_shdict.lua
local function dictreplace(str)
local dogs = ngx.shared.dogs
local success, err = dogs:replace("Jim", 8)
return success, err
end
return {dictreplace=dictreplace}
--- request
GET /dictreplace
--- response_body
true,true,nil,8
=== TEST 47: shdict replace not found
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictreplace {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
local ok, ret, err = ngx.run_worker_thread("testpool", "test_shdict", "dictreplace")
ngx.say(ok, ",", ret, ",", err)
}
}
--- user_files
>>> test_shdict.lua
local function dictreplace(str)
local dogs = ngx.shared.dogs
local success, err = dogs:replace("Jim", 8)
return success, err
end
return {dictreplace=dictreplace}
--- request
GET /dictreplace
--- response_body
true,false,not found
=== TEST 48: shdict incr
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictincr {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
local success, err = dogs:set("Jim", 8)
local ok, ret, err = ngx.run_worker_thread("testpool", "test_shdict", "dictincr")
ngx.say(ok, ",", ret, ",", err, ",", dogs:get("Jim"))
}
}
--- user_files
>>> test_shdict.lua
local function dictincr(str)
local dogs = ngx.shared.dogs
local success, err = dogs:incr("Jim", 1)
return success, err
end
return {dictincr=dictincr}
--- request
GET /dictincr
--- response_body
true,9,nil,9
=== TEST 49: shdict lpush lpop
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictlpush {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:lpush("Jim", 8)
dogs:lpush("Jim", 9)
local ok, val, len, err = ngx.run_worker_thread("testpool", "test_shdict", "dictlpush")
ngx.say(ok, ",", val, ",", len, ",", err, ",", dogs:lpop("Jim"))
}
}
--- user_files
>>> test_shdict.lua
local function dictlpush(str)
local dogs = ngx.shared.dogs
local val = dogs:lpop("Jim")
local len, err = dogs:lpush("Jim", 7)
return val, len, err
end
return {dictlpush=dictlpush}
--- request
GET /dictlpush
--- response_body
true,9,2,nil,7
=== TEST 50: shdict expire ttl
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictexpire {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
local ok, success, err = ngx.run_worker_thread("testpool", "test_shdict", "dictexpire")
ngx.say(ok, ",", success, ",", err, ",", dogs:ttl("Jim") <= 1)
}
}
--- user_files
>>> test_shdict.lua
local function dictexpire(str)
local dogs = ngx.shared.dogs
local success, err = dogs:expire("Jim", 1)
return success, err
end
return {dictexpire=dictexpire}
--- request
GET /dictexpire
--- response_body
true,true,nil,true
=== TEST 51: shdict flush_all
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictexpire {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
dogs:set("King", 9)
local ok = ngx.run_worker_thread("testpool", "test_shdict", "dictexpire")
ngx.say(ok, ",", dogs:get("Jim"), ",", dogs:get("King"))
}
}
--- user_files
>>> test_shdict.lua
local function dictexpire(str)
local dogs = ngx.shared.dogs
dogs:flush_all()
end
return {dictexpire=dictexpire}
--- request
GET /dictexpire
--- response_body
true,nil,nil
=== TEST 52: shdict get_keys
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"
lua_shared_dict dogs 6m;
lua_package_path '$::HtmlDir/?.lua;./?.lua;;';
"
--- config
location /dictgetkeys {
default_type 'text/plain';
access_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
dogs:set("King", 9)
local ok, keys = ngx.run_worker_thread("testpool", "test_shdict", "dictgetkeys")
ngx.say(ok, ",", table.concat(keys, ":"))
}
}
--- user_files
>>> test_shdict.lua
local function dictgetkeys(str)
local dogs = ngx.shared.dogs
return dogs:get_keys()
end
return {dictgetkeys=dictgetkeys}
--- request
GET /dictgetkeys
--- response_body
true,Jim:King
=== TEST 53: unsupported argument type in self-reference table
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;./?.lua;;';"
--- config
location /hello {
default_type 'text/plain';
content_by_lua_block {
local t = {}
t.a = t
local ok, ok_or_err = ngx.run_worker_thread("testpool", "hello", "hello", t)
ngx.say(ok, " , ", ok_or_err)
}
}
--- user_files
>>> hello.lua
local function hello(arg1)
return true
end
return {hello=hello}
--- request
GET /hello
--- response_body
false , suspicious circular references, table depth exceed max depth: 100 in the argument
=== TEST 54: unsupported argument type in circular-reference table
--- main_config
thread_pool testpool threads=100;
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;./?.lua;;';"
--- config
location /hello {
default_type 'text/plain';
content_by_lua_block {
local t = {}
local s = {}
t.a = s
s.b = t
local ok, ok_or_err = ngx.run_worker_thread("testpool", "hello", "hello", t)
ngx.say(ok, " , ", ok_or_err)
}
}
--- user_files
>>> hello.lua
local function hello(arg1)
return true
end
return {hello=hello}
--- request
GET /hello
--- response_body
false , suspicious circular references, table depth exceed max depth: 100 in the argument

View File

@ -0,0 +1,488 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = <<_EOC_;
$t::StapThread::GCScript
F(ngx_http_lua_check_broken_connection) {
println("lua check broken conn")
}
F(ngx_http_lua_request_cleanup) {
println("lua req cleanup")
}
_EOC_
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 3 + 10);
#log_level("info");
#no_long_string();
run_tests();
__DATA__
=== TEST 1: server_rewrite_by_lua_block in http
--- http_config
server_rewrite_by_lua_block {
ngx.ctx.a = "server_rewrite_by_lua_block in http"
}
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.ctx.a)
ngx.log(ngx.INFO, ngx.ctx.a)
}
}
--- request
GET /lua
--- response_body
server_rewrite_by_lua_block in http
--- error_log
server_rewrite_by_lua_block in http
--- no_error_log
[error]
=== TEST 2: server_rewrite_by_lua_block in server
--- config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "server_rewrite_by_lua_block in server")
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
server_rewrite_by_lua_block in server
--- no_error_log
[error]
=== TEST 3: redirect
--- config
server_rewrite_by_lua_block {
ngx.redirect("/foo")
}
--- request
GET /lua
--- raw_response_headers_like: Location: /foo\r\n
--- response_body_like: 302 Found
--- error_code: 302
--- no_error_log
[error]
=== TEST 4: flush
--- config
server_rewrite_by_lua_block {
ngx.say("foo")
ngx.flush(true)
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
foo
--- no_error_log
[error]
=== TEST 5: eof
--- config
server_rewrite_by_lua_block {
ngx.say("foo")
ngx.eof()
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
foo
--- no_error_log
[error]
=== TEST 6: send_headers
--- config
server_rewrite_by_lua_block {
ngx.header["Foox"] = {"conx1", "conx2" }
ngx.header["Fooy"] = {"cony1", "cony2" }
ngx.send_headers()
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
--- response_headers
Foox: conx1, conx2
Fooy: cony1, cony2
--- no_error_log
[error]
=== TEST 7: read_body
--- config
server_rewrite_by_lua_block {
ngx.req.read_body()
ngx.say(ngx.var.request_body)
}
--- request
POST /lua
hello, world
--- response_body
hello, world
--- no_error_log
[error]
=== TEST 8: req_sock
--- config
server_rewrite_by_lua_block {
local sock = ngx.req.socket()
sock:receive(2)
sock:receive(2)
sock:receive(1)
ngx.sleep(1)
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
POST /lua
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
=== TEST 9: rewrite args (not break cycle by default)
--- config
location /bar {
echo "bar: $uri?$args";
}
server_rewrite_by_lua_block {
if ngx.var.uri ~= "/bar" then
ngx.req.set_uri_args("hello")
ngx.req.set_uri("/bar", true)
end
}
location /foo {
echo "foo: $uri?$args";
}
--- request
GET /foo?world
--- response_body
bar: /bar?hello
=== TEST 10: server_rewrite_by_lua_block overwrite by server
--- http_config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "server_rewrite_by_lua_block in http")
}
--- config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "server_rewrite_by_lua_block in server")
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
server_rewrite_by_lua_block in server
--- no_error_log
[error]
=== TEST 11: sleep
--- config
server_rewrite_by_lua_block {
ngx.sleep(0.001)
ngx.log(ngx.INFO, "server_rewrite_by_lua_block in server")
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
server_rewrite_by_lua_block in server
--- no_error_log
[error]
=== TEST 12: ngx.exit(ngx.OK)
--- config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "ngx.exit")
ngx.exit(ngx.OK)
}
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
ngx.exit
--- no_error_log
[error]
=== TEST 13: ngx.exit(503)
--- config
server_rewrite_by_lua_block {
ngx.exit(503)
}
location /lua {
content_by_lua_block {
ngx.log(ngx.ERR, "content_by_lua")
ngx.say("OK")
}
}
--- request
GET /lua
--- error_code: 503
--- no_error_log
[error]
=== TEST 14: subrequests
--- config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "is_subrequest:", ngx.is_subrequest)
}
location /lua {
content_by_lua_block {
local res = ngx.location.capture("/sub")
ngx.print(res.body)
}
}
location /sub {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
is_subrequest:false
is_subrequest:true
--- no_error_log
[error]
=== TEST 15: rewrite by ngx_http_rewrite_module
--- config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "uri is ", ngx.var.uri)
}
rewrite ^ /re;
location /re {
content_by_lua_block {
ngx.say("RE")
}
}
location /ok {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
RE
--- error_log
uri is /lua
--- no_error_log
[error]
=== TEST 16: exec
--- config
server_rewrite_by_lua_block {
if ngx.var.uri ~= "/ok" then
ngx.exec("/ok")
end
ngx.log(ngx.INFO, "uri is ", ngx.var.uri)
}
location /ok {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
uri is /ok
--- no_error_log
[error]
=== TEST 17: server_rewrite_by_lua and rewrite_by_lua
--- http_config
server_rewrite_by_lua_block {
ngx.log(ngx.INFO, "server_rewrite_by_lua_block in http")
}
--- config
location /lua {
rewrite_by_lua_block {
ngx.log(ngx.INFO, "rewrite_by_lua_block in location")
}
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- response_body
OK
--- error_log
server_rewrite_by_lua_block in http
rewrite_by_lua_block in location
--- no_error_log
[error]
=== TEST 18: server_rewrite_by_lua_file
--- http_config
server_rewrite_by_lua_file 'html/foo.lua';
--- config
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- user_files
>>> foo.lua
ngx.log(ngx.INFO, "rewrite_by_lua_file in server")
--- response_body
OK
--- error_log
rewrite_by_lua_file in server
--- no_error_log
[error]
=== TEST 19: syntax error server_rewrite_by_lua_block in http
--- http_config
server_rewrite_by_lua_block {
'for end';
}
--- config
location /lua {
content_by_lua_block {
ngx.say("OK")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: server_rewrite_by_lua(nginx.conf:25):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error
=== TEST 20: syntax error server_rewrite_by_lua_block in server
--- config
server_rewrite_by_lua_block {
'for end';
}
location /lua {
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: server_rewrite_by_lua(nginx.conf:39):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error

View File

@ -0,0 +1,367 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
# more times than usual(2) for test case 6
repeat_each(4);
plan tests => repeat_each() * (blocks() * 3 + 7);
our $HtmlDir = html_dir;
# get ip address in the dev which is default route outgoing dev
my $dev = `ip route | awk '/default/ {printf "%s", \$5}'`;
my $local_ip = `ip route | grep $dev | grep -o "src .*" | head -n 1 | awk '{print \$2}'`;
chomp $local_ip;
$ENV{TEST_NGINX_HTML_DIR} = $HtmlDir;
$ENV{TEST_NGINX_NOT_EXIST_IP} ||= '8.8.8.8';
$ENV{TEST_NGINX_INVALID_IP} ||= '127.0.0.1:8899';
$ENV{TEST_NGINX_SERVER_IP} ||= $local_ip;
no_long_string();
#no_diff();
#log_level 'warn';
log_level 'debug';
no_shuffle();
run_tests();
__DATA__
=== TEST 1: upstream sockets bind 127.0.0.1
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local ip = "127.0.0.1"
local port = ngx.var.port
local sock = ngx.socket.tcp()
local ok, err = sock:bind(ip)
if not ok then
ngx.say("failed to bind", err)
return
end
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local bytes, err = sock:send("GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: keepalive\r\n\r\n")
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent")
local reader = sock:receiveuntil("\r\n0\r\n\r\n")
local data, err = reader()
if not data then
ngx.say("failed to receive response body: ", err)
return
end
ngx.say("received response")
local remote_ip = string.match(data, "(bind: %d+%.%d+%.%d+%.%d+)")
ngx.say(remote_ip)
ngx.say("done")
}
}
location /foo {
echo bind: $remote_addr;
}
--- request
GET /t
--- response_body
connected: 1
request sent
received response
bind: 127.0.0.1
done
--- no_error_log
["[error]",
"bind(127.0.0.1) failed"]
--- error_log eval
"lua tcp socket bind ip: 127.0.0.1"
=== TEST 2: upstream sockets bind server ip, not 127.0.0.1
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local ip = "$TEST_NGINX_SERVER_IP"
local port = ngx.var.port
local sock = ngx.socket.tcp()
local ok, err = sock:bind(ip)
if not ok then
ngx.say("failed to bind", err)
return
end
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local bytes, err = sock:send("GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: keepalive\r\n\r\n")
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent")
local reader = sock:receiveuntil("\r\n0\r\n\r\n")
local data, err = reader()
if not data then
ngx.say("failed to receive response body: ", err)
return
end
ngx.say("received response")
local remote_ip = string.match(data, "(bind: %d+%.%d+%.%d+%.%d+)")
if remote_ip == "bind: $TEST_NGINX_SERVER_IP" then
ngx.say("ip matched")
end
ngx.say("done")
}
}
location /foo {
echo bind: $remote_addr;
}
--- request
GET /t
--- response_body
connected: 1
request sent
received response
ip matched
done
--- no_error_log eval
["[error]",
"bind($ENV{TEST_NGINX_SERVER_IP}) failed"]
--- error_log eval
"lua tcp socket bind ip: $ENV{TEST_NGINX_SERVER_IP}"
=== TEST 3: add setkeepalive
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;./?.lua;;';"
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local test = require "test"
local t1 = test.go()
local t2 = test.go()
ngx.say("t2 - t1: ", t2 - t1)
}
}
--- user_files
>>> test.lua
local _M = {}
function _M.go()
local ip = "127.0.0.1"
local port = ngx.var.port
local sock = ngx.socket.tcp()
local ok, err = sock:bind(ip)
if not ok then
ngx.say("failed to bind", err)
return
end
ngx.say("bind: ", ip)
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local reused = sock:getreusedtimes()
local ok, err = sock:setkeepalive()
if not ok then
ngx.say("failed to set reusable: ", err)
end
return reused
end
return _M
--- request
GET /t
--- response_body
bind: 127.0.0.1
connected: 1
bind: 127.0.0.1
connected: 1
t2 - t1: 1
--- no_error_log
["[error]",
"bind(127.0.0.1) failed"]
--- error_log eval
"lua tcp socket bind ip: 127.0.0.1"
=== TEST 4: upstream sockets bind not exist ip
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local ip = "$TEST_NGINX_NOT_EXIST_IP"
local port = ngx.var.port
local sock = ngx.socket.tcp()
local ok, err = sock:bind(ip)
if not ok then
ngx.say("failed to bind", err)
return
end
ngx.say("bind: ", ip)
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
}
}
--- request
GET /t
--- response_body
bind: 8.8.8.8
failed to connect: cannot assign requested address
--- error_log eval
["bind(8.8.8.8) failed",
"lua tcp socket bind ip: 8.8.8.8"]
=== TEST 5: upstream sockets bind invalid ip
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local ip = "$TEST_NGINX_INVALID_IP"
local port = ngx.var.port
local sock = ngx.socket.tcp()
local ok, err = sock:bind(ip)
if not ok then
ngx.say("failed to bind: ", err)
return
end
ngx.say("bind: ", ip)
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
}
}
--- request
GET /t
--- response_body
failed to bind: bad address
--- no_error_log
[error]
=== TEST 6: tcpsock across request after bind
--- http_config
init_worker_by_lua_block {
-- this is not the recommend way, just for test
local function tcp()
local sock = ngx.socket.tcp()
local ok, err = sock:bind("127.0.0.1")
if not ok then
ngx.log(ngx.ERR, "failed to bind")
end
package.loaded.share_sock = sock
end
local ok, err = ngx.timer.at(0, tcp)
if not ok then
ngx.log(ngx.ERR, "failed to create timer")
end
}
--- config
server_tokens off;
location /t {
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua_block {
local port = ngx.var.port
-- make sure share_sock is created
ngx.sleep(0.002)
local sock = package.loaded.share_sock
if sock ~= nil then
package.loaded.share_sock = nil
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:close()
collectgarbage("collect")
else
-- the sock from package.loaded.share_sock is just
-- for the first request after worker init
-- add following code to keep the same result for other request
ngx.say("connected: ", 1)
end
}
}
--- request
GET /t
--- response_body
connected: 1
--- no_error_log
[error]

View File

@ -0,0 +1,25 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket 'no_plan';
repeat_each(2);
run_tests();
__DATA__
=== TEST 1: one buf was linked to multiple ngx_chain_t nodes
--- config
location /t {
content_by_lua_block {
local str = string.rep(".", 1300)
ngx.print(str)
ngx.flush()
ngx.print("small chunk")
ngx.flush()
}
body_filter_by_lua_block {local dummy=1}
}
--- request
GET /t
--- response_body_like: small chunk

View File

@ -0,0 +1,81 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket 'no_plan';
use Test::Nginx::Socket::Lua::Stream;
log_level('warn');
repeat_each(2);
run_tests();
__DATA__
=== TEST 1: ngx.say and cosocket
--- stream_server_config
content_by_lua_block {
local sock = assert(ngx.req.socket(true))
sock:settimeout(1000)
while true do
local data = sock:receive(5)
if not data then
return
end
ngx.print(data)
ngx.flush(true)
end
}
--- config
location /test {
content_by_lua_block {
ngx.say("hello")
--ngx.flush(true)
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", ngx.var.server_port + 1)
assert(ok)
local last_duration = 0
local cnt = 0
local t1, t2
local err_cnt = 0
local ERR_THRESHOLD_MS = 100
for i = 1,100000 do
if cnt == 0 then
ngx.update_time()
t1 = ngx.now()
end
cnt = cnt + 1
local sent = sock:send("hello")
local data = sock:receive(5)
assert(data=="hello")
if cnt == 1000 then
cnt = 0
ngx.update_time()
t2 = ngx.now()
local duration = (t2 - t1) * 1000
if last_duration > 0 and (duration - last_duration) > ERR_THRESHOLD_MS then
if err_cnt >= 3 then
ngx.log(ngx.ERR,
"more than ", err_cnt, " times, duration larger than ",
ERR_THRESHOLD_MS, " ms, ",
"last_duration: ", math.floor(duration), " ms")
return ngx.exit(500)
end
err_cnt = err_cnt + 1
end
last_duration = duration
end
end
sock:close()
ngx.exit(200)
}
}
--- no_error_log
[error]
--- timeout: 30
--- request
GET /test

View File

@ -0,0 +1,78 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
32:ed:21:56:d8:4e:aa:03:89:a9:4a:a4:e2:85:2d:8a:3b:2b:89:22
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = California, O = OpenResty, CN = OpenResty Testing Root CA
Validity
Not Before: Mar 13 15:49:00 2022 GMT
Not After : Mar 8 15:49:00 2042 GMT
Subject: C = US, ST = California, O = OpenResty, CN = OpenResty Testing Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:e6:37:d2:c6:17:36:c7:b2:7f:7d:cf:d0:62:87:
99:d9:21:b8:de:ff:d8:e2:3a:1c:68:90:8f:ce:17:
68:22:b0:60:30:cc:29:e8:34:ee:ff:b2:25:de:6e:
1a:d4:df:10:19:11:4b:40:61:d3:a9:4d:80:ed:97:
81:4e:c5:74:e8:4d:63:e3:5f:21:bc:5a:6e:22:a0:
17:91:c1:cb:25:53:9b:9d:4e:e1:51:5b:f6:52:e7:
0a:27:f6:16:c2:31:cb:6c:47:f4:89:51:15:cc:06:
be:31:3e:1c:ea:ee:81:9b:c4:97:96:fd:e5:1c:95:
9e:c0:65:cd:a9:9a:cb:68:67:f2:62:a0:21:eb:5a:
c5:a1:92:ed:32:41:28:f9:47:34:eb:44:ae:d6:e7:
76:71:11:98:c9:2e:ce:6c:7c:10:1b:c7:4c:c3:14:
89:4e:d9:4c:d9:c7:43:e9:3c:29:ca:62:a9:91:b3:
87:e7:d7:b4:18:ab:65:f9:6b:ed:82:ca:a1:36:35:
18:05:cb:5c:24:26:13:13:f8:99:ac:99:be:9b:a6:
73:df:0d:16:95:b1:dc:be:fe:7a:c2:b6:dc:c8:93:
cf:10:e0:29:03:0e:28:78:18:84:ee:14:92:ab:be:
5a:a0:14:a2:4a:2f:d3:d0:b8:0e:00:d2:5a:cd:e4:
bd:a1
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
F0:D7:4B:14:73:E1:67:00:6B:54:B4:19:20:76:12:9F:9D:8E:C8:09
Signature Algorithm: sha256WithRSAEncryption
6d:52:21:6d:6e:8c:e5:4a:28:07:65:6d:d8:7c:23:2e:c6:c1:
d0:ec:27:b3:b0:c3:d3:e8:fa:72:b9:de:32:4e:ff:97:8d:86:
a9:6d:b3:a9:b4:2d:77:ca:28:97:6a:3d:7b:a2:15:ed:34:dc:
72:9f:6f:e7:01:0c:d3:28:6a:80:1b:50:09:fd:d7:2c:d8:92:
d5:10:c4:73:15:20:7d:99:dc:de:30:7b:3c:6e:e9:66:b2:0e:
4e:1a:c1:51:57:6e:5b:b0:a9:f6:ff:0b:8f:07:67:31:40:5b:
11:a9:06:d3:d3:76:c5:d2:56:95:9a:9e:4a:16:44:4b:32:e5:
af:dd:4b:4d:5d:57:b8:85:69:36:93:2a:c6:0c:8f:e1:42:35:
be:8e:f3:e7:35:d3:2c:3a:03:31:40:75:8e:e8:dd:57:35:20:
5e:18:a9:76:ce:85:be:7e:3a:cf:6e:08:58:5b:47:d5:e9:c4:
ec:0e:e9:8e:3c:2d:5c:7b:59:20:5b:24:92:a0:e0:1e:a3:5a:
67:d8:ff:7f:a5:82:f1:df:db:05:65:79:88:b1:3c:e6:01:d1:
5a:c7:d2:6e:9a:e6:a2:da:4a:c7:19:78:d9:14:71:6e:1f:70:
f3:41:e5:b3:78:31:d5:22:0e:7c:1a:b2:43:d9:86:ff:53:ea:
2b:ba:d2:27
-----BEGIN CERTIFICATE-----
MIIDhDCCAmygAwIBAgIUMu0hVthOqgOJqUqk4oUtijsriSIwDQYJKoZIhvcNAQEL
BQAwWjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAoT
CU9wZW5SZXN0eTEiMCAGA1UEAxMZT3BlblJlc3R5IFRlc3RpbmcgUm9vdCBDQTAe
Fw0yMjAzMTMxNTQ5MDBaFw00MjAzMDgxNTQ5MDBaMFoxCzAJBgNVBAYTAlVTMRMw
EQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQKEwlPcGVuUmVzdHkxIjAgBgNVBAMT
GU9wZW5SZXN0eSBUZXN0aW5nIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDmN9LGFzbHsn99z9Bih5nZIbje/9jiOhxokI/OF2gisGAwzCno
NO7/siXebhrU3xAZEUtAYdOpTYDtl4FOxXToTWPjXyG8Wm4ioBeRwcslU5udTuFR
W/ZS5won9hbCMctsR/SJURXMBr4xPhzq7oGbxJeW/eUclZ7AZc2pmstoZ/JioCHr
WsWhku0yQSj5RzTrRK7W53ZxEZjJLs5sfBAbx0zDFIlO2UzZx0PpPCnKYqmRs4fn
17QYq2X5a+2CyqE2NRgFy1wkJhMT+Jmsmb6bpnPfDRaVsdy+/nrCttzIk88Q4CkD
Dih4GITuFJKrvlqgFKJKL9PQuA4A0lrN5L2hAgMBAAGjQjBAMA4GA1UdDwEB/wQE
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTw10sUc+FnAGtUtBkgdhKf
nY7ICTANBgkqhkiG9w0BAQsFAAOCAQEAbVIhbW6M5UooB2Vt2HwjLsbB0Owns7DD
0+j6crneMk7/l42GqW2zqbQtd8ool2o9e6IV7TTccp9v5wEM0yhqgBtQCf3XLNiS
1RDEcxUgfZnc3jB7PG7pZrIOThrBUVduW7Cp9v8LjwdnMUBbEakG09N2xdJWlZqe
ShZESzLlr91LTV1XuIVpNpMqxgyP4UI1vo7z5zXTLDoDMUB1jujdVzUgXhipds6F
vn46z24IWFtH1enE7A7pjjwtXHtZIFskkqDgHqNaZ9j/f6WC8d/bBWV5iLE85gHR
WsfSbprmotpKxxl42RRxbh9w80Hls3gx1SIOfBqyQ9mG/1PqK7rSJw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA5jfSxhc2x7J/fc/QYoeZ2SG43v/Y4jocaJCPzhdoIrBgMMwp
6DTu/7Il3m4a1N8QGRFLQGHTqU2A7ZeBTsV06E1j418hvFpuIqAXkcHLJVObnU7h
UVv2UucKJ/YWwjHLbEf0iVEVzAa+MT4c6u6Bm8SXlv3lHJWewGXNqZrLaGfyYqAh
61rFoZLtMkEo+Uc060Su1ud2cRGYyS7ObHwQG8dMwxSJTtlM2cdD6TwpymKpkbOH
59e0GKtl+WvtgsqhNjUYBctcJCYTE/iZrJm+m6Zz3w0WlbHcvv56wrbcyJPPEOAp
Aw4oeBiE7hSSq75aoBSiSi/T0LgOANJazeS9oQIDAQABAoIBAQDhH9+uNE8uUv/X
MNvvLfklWpOlBf25o+fZ3NuzRjJgEafOsCee2fyI8FWVwIfeeE8OpFm5GLDZk1+r
dwdM10xuSheO5Z1gyfF/TJwfvamA09SNrPArFkm3YhUNZNl2hykMtwSLL06oWEOu
dbXjit4VS9aNIbTlEe7O5/6Ih0W3zmr1yvUua2swmAZMx3GFA4kbjZZ9vDs27sdu
K+VY3DYRbq1HkiNFT0otfke5bObFBCG7Yp8JLyhYaIkGYFoBXuZ6JNY8EuU2+YyP
6r40tJ7StR1Q6eZJh9/1leaYGZLCh5oFyKpilTuxHbRbr5A28RJKjKvPsdDgTtQn
yHGg70FRAoGBAOhC3TQlFcT2WCCZHHql9JEEHnHVBWnL3Jg7VJuL1i6pEIz7qQkW
AtBEIY/nnTcVNfJ6eXznYtutYvvRSgQTUsBNRoj3s1z9wKOo4uw4LoIUXDEmHCr+
49DiQyIO21SNMHA+dVxvGRDDjLI9Uc+Scb64QOodoX75HLRZG++24mtdAoGBAP2/
gCjga2p8Jx9UnhIcrEIIGANyxEQeBdhF56Nt9CJy/Iwi3a6qQ/GkbeoDm5FhXnXo
xcBaHyv2lwi4uO/hONY8eRnYxAWMwAKMZe6VnU1hWI2Ytkh+OcMPMh7NIGQf6X1o
JZrBtnTms060TuuDjLeIlaubDR/xDrMWTMKjKbsVAoGAVLuYAZ8J6xpIGlRhbGlA
6OrMxJCHcgpahvsWKc0BLXKmRBjHmTX7fslsSRihZWgKj1SZH7U2fpgpxV6cFxKJ
nPhUJEHhoKo+bjZ92tnANdqBq7iQjCsDJ8Bz52fuIlGD+1795+PsDA6bNKdkQkrV
zlNf80kuEqmFDFJ5+6EHx00CgYAf+jkpbZa71aeMgDpnZ+uhaqm0DYuEVhBAgBa/
9sRUbw86jc5IC7cCRcmAOzIosQ+ZZls9cV4KSUohVD4iJMzn2rkcM8AIPwOXjp/t
4DbxoHnrZjpaimW3Gjwju5AAbjEbl7tddFoNA2HHYlurvGlIW9MYzDJsOxGyKfZE
dRF2PQKBgQDUKNHgDYEjLJ99S5Fm5zN/64bKzzDtktGdqOxik5pBKcs/BvOdLM0i
eCjGz/3qrEoenFIBwF/IRz3ug90Zr8bWOu6DudReflAKI/N13dZ2gOTAfaX4ljJF
w0ohSi6xs+mu1GmtipGtNxHi/J3na2BeSnSRFSUg6Zd+oh8BZQKmNg==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,4 @@
*.pem
*.csr
cfssl
cfssljson

View File

@ -0,0 +1,23 @@
#!/bin/bash
rm *.pem *.csr cfssl cfssljson
wget -O cfssl https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64
wget -O cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64
chmod +x cfssl cfssljson
./cfssl gencert -initca -config profile.json mtls_ca.json | ./cfssljson -bare mtls_ca
./cfssl gencert -ca mtls_ca.pem -ca-key mtls_ca-key.pem -config profile.json -profile=client mtls_client.json | ./cfssljson -bare mtls_client
./cfssl gencert -ca mtls_ca.pem -ca-key mtls_ca-key.pem -config profile.json -profile=server mtls_server.json | ./cfssljson -bare mtls_server
openssl x509 -in mtls_ca.pem -text > ../mtls_ca.crt
mv mtls_ca-key.pem ../mtls_ca.key
openssl x509 -in mtls_client.pem -text > ../mtls_client.crt
mv mtls_client-key.pem ../mtls_client.key
openssl x509 -in mtls_server.pem -text > ../mtls_server.crt
mv mtls_server-key.pem ../mtls_server.key
rm *.pem *.csr cfssl cfssljson

View File

@ -0,0 +1,18 @@
{
"CA": {
"expiry": "175200h",
"pathlen": 0
},
"CN": "OpenResty Testing Root CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"O": "OpenResty",
"ST": "California"
}
]
}

Some files were not shown because too many files have changed in this diff Show More