diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..22fd00e70 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,27 @@ +This place is for bug reports and development discussions only. For general questions and +discussions, please join the openresty-en mailing list instead: https://groups.google.com/group/openresty-en. +If you want to use Chinese, please join the openresty (Chinese) mailing list instead: https://groups.google.com/group/openresty. +Do not use Chinese in this place. + +Before you open a new issue, please search the internet and make sure it is not duplicate. + +Ensure you have provided the following details while reporting a problem: + +- [ ] The exact version of the related software, including but not limited to the OpenResty version +(if any), the NGINX core version, the `ngx_lua` module version(via `openresty -V` or `nginx -V`), +and the `lua-resty-core` version(via `resty -e 'print(require("resty.core").version)'`), +and your operating system version(via `uname -a`). +- [ ] **A minimal and standalone test case** that others can easily run on their side and +reproduce the issue you are seeing. +- [ ] Do not simply say "something is broken" or "something does not work". Always provide +as much details as possible. Always describe **the symptoms and your expected results**. + +You can (temporarily) enable the nginx debugging logs to see the internal workings +of NGINX in your nginx''s `error.log` file. See http://nginx.org/en/docs/debugging_log.html +The same instructions apply equally well to OpenResty. + +If you are seeing crashes, please provide the full backtrace for the crash. See +https://www.nginx.com/resources/wiki/start/topics/tutorials/debugging/#core-dump +for more details. + +Thanks for your cooperation. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..9d3889429 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,2 @@ +I hereby granted the copyright of the changes in this pull request +to the authors of this lua-resty-core project. diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 000000000..8981e16a5 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,5 @@ +std = 'ngx_lua' +unused_args = false +read_globals = { + "coroutine._yield" +} diff --git a/.travis.yml b/.travis.yml index bbbfbb897..3f5cf76bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,37 +9,52 @@ compiler: - gcc - clang +addons: + apt: + packages: + - cpanminus + - axel + - luarocks + cache: directories: - download-cache env: global: - - JOBS=3 + - JOBS=2 - NGX_BUILD_JOBS=$JOBS - LUAJIT_PREFIX=/opt/luajit21 - LUAJIT_LIB=$LUAJIT_PREFIX/lib - LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1 - LUA_INCLUDE_DIR=$LUAJIT_INC - LUA_CMODULE_DIR=/lib + - PCRE_VER=8.40 - OPENSSL_PREFIX=/opt/ssl - OPENSSL_LIB=$OPENSSL_PREFIX/lib - OPENSSL_INC=$OPENSSL_PREFIX/include - - OPENSSL_VER=1.0.2h + - OPENSSL_VER=1.0.2j - LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH - - TEST_NGINX_SLEEP=0.006 + - TEST_NGINX_SLEEP=0.005 + - TEST_NGINX_RANDOMIZE=1 matrix: - NGINX_VERSION=1.9.15 -# - NGINX_VERSION=1.10.0 + - NGINX_VERSION=1.11.2 + +before_install: + - sudo luarocks install luacheck + - luacheck -q . + - '! grep -n -P ''(?<=.{80}).+'' --color `find . -name ''*.lua''` || (echo "ERROR: Found Lua source lines exceeding 80 columns." > /dev/stderr; exit 1)' + - '! grep -n -P ''\t+'' --color `find . -name ''*.lua''` || (echo "ERROR: Cannot use tabs." > /dev/stderr; exit 1)' + - sudo cpanm --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1) install: - if [ ! -d download-cache ]; then mkdir download-cache; fi - if [ ! -f download-cache/openssl-$OPENSSL_VER.tar.gz ]; then wget -O download-cache/openssl-$OPENSSL_VER.tar.gz https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz; fi - - sudo apt-get install -qq -y cpanminus axel - - sudo cpanm --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1) + - if [ ! -f download-cache/pcre-$PCRE_VER.tar.gz ]; then wget -P download-cache http://ftp.cs.stanford.edu/pub/exim/pcre/pcre-$PCRE_VER.tar.gz; fi - wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz - git clone https://github.com/openresty/openresty.git ../openresty - - git clone https://github.com/openresty/nginx-devel-utils.git + - git clone https://github.com/openresty/openresty-devel-utils.git - git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module - git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module - git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx @@ -48,27 +63,29 @@ install: - git clone https://github.com/openresty/headers-more-nginx-module.git ../headers-more-nginx-module - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git - git clone https://github.com/openresty/mockeagain.git + - git clone https://github.com/openresty/test-nginx.git script: - cd luajit2/ - - make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS='-DLUA_USE_APICHECK -DLUA_USE_ASSERT' > build.log 2>&1 || (cat build.log && exit 1) + - make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS='-DLUA_USE_APICHECK -DLUA_USE_ASSERT -msse4.2' > build.log 2>&1 || (cat build.log && exit 1) - sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1) - cd .. - cd lua-resty-lrucache && sudo make DESTDIR=$LUAJIT_PREFIX LUA_LIB_DIR=/share/lua/5.1 install && cd .. - tar zxf download-cache/openssl-$OPENSSL_VER.tar.gz - cd openssl-$OPENSSL_VER/ - - wget https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-$OPENSSL_VER-sess_set_get_cb_yield.patch - - patch -p1 < openssl-$OPENSSL_VER-sess_set_get_cb_yield.patch + - if [ ! -f openssl-1.0.2h-sess_set_get_cb_yield.patch ]; then wget -O openssl-1.0.2h-sess_set_get_cb_yield.patch https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.0.2h-sess_set_get_cb_yield.patch; fi + - patch -p1 < openssl-1.0.2h-sess_set_get_cb_yield.patch - ./config shared --prefix=$OPENSSL_PREFIX -DPURIFY > build.log 2>&1 || (cat build.log && exit 1) - make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1) - sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1) - cd ../mockeagain/ && make CC=$CC -j$JOBS && cd .. - - export PATH=$PWD/work/nginx/sbin:$PWD/nginx-devel-utils:$PATH + - tar zxf download-cache/pcre-$PCRE_VER.tar.gz + - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:$PATH - export LD_PRELOAD=$PWD/mockeagain/mockeagain.so - export LD_LIBRARY_PATH=$PWD/mockeagain:$LD_LIBRARY_PATH - export TEST_NGINX_RESOLVER=8.8.4.4 - export NGX_BUILD_CC=$CC - - ngx-build $NGINX_VERSION --with-ipv6 --with-http_realip_module --with-http_ssl_module --with-cc-opt="-I$OPENSSL_INC" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB" --add-module=../ndk-nginx-module --add-module=../echo-nginx-module --add-module=../headers-more-nginx-module --add-module=../lua-nginx-module --with-debug > build.log 2>&1 || (cat build.log && exit 1) + - ngx-build $NGINX_VERSION --with-ipv6 --with-http_realip_module --with-http_ssl_module --with-pcre=../../pcre-$PCRE_VER --with-pcre-jit --with-cc-opt="-I$OPENSSL_INC" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB" --add-module=../ndk-nginx-module --add-module=../echo-nginx-module --add-module=../headers-more-nginx-module --add-module=../lua-nginx-module --with-debug > build.log 2>&1 || (cat build.log && exit 1) - nginx -V - ldd `which nginx`|grep -E 'luajit|ssl|pcre' - - prove -r t + - prove -Itest-nginx/lib -j$JOBS -r t diff --git a/README.markdown b/README.markdown index be7501461..da28057e9 100644 --- a/README.markdown +++ b/README.markdown @@ -29,6 +29,9 @@ Table of Contents * [ngx.balancer](#ngxbalancer) * [ngx.ssl](#ngxssl) * [ngx.ssl.session](#ngxsslsession) + * [ngx.re](#ngxre) + * [ngx.process](#ngxprocess) + * [ngx.errlog](#ngxerrlog) * [Caveat](#caveat) * [TODO](#todo) * [Author](#author) @@ -83,8 +86,12 @@ and requirements. Prerequisites ============= +**WARNING** This library is included with every OpenResty release. You should use the bundled version +of this library in the particular OpenResty release you are using. Otherwise you may run +into serious comaptibility issues. + * LuaJIT 2.1 (for now, it is the v2.1 git branch in the official luajit-2.0 git repository: http://luajit.org/download.html ) -* [ngx_lua](https://github.com/openresty/lua-nginx-module) v0.10.6 or later. +* [ngx_lua](https://github.com/openresty/lua-nginx-module) v0.10.9 or later. * [lua-resty-lrucache](https://github.com/openresty/lua-resty-lrucache) [Back to TOC](#table-of-contents) @@ -235,6 +242,35 @@ See the [documentation](./lib/ngx/ssl/session.md) for this Lua module for more d [Back to TOC](#table-of-contents) +## ngx.re + +This Lua module provides a Lua API which implements convenience utilities for +the `ngx.re` API. + +See the [documentation](./lib/ngx/re.md) for this Lua module for more details. + +[Back to TOC](#table-of-contents) + +## ngx.process + +This Lua module is used to manage the nginx process in Lua. + +See the [documentation](./lib/ngx/process.md) for this Lua module for more details. + +This module was first introduced in lua-resty-core v0.1.12. + +[Back to TOC](#table-of-contents) + +## ngx.errlog + +This Lua module provides Lua API to capture and manage nginx error log messages. + +See the [documentation](./lib/ngx/errlog.md) for this Lua module for more details. + +This module was first introduced in lua-resty-core v0.1.12. + +[Back to TOC](#table-of-contents) + Caveat ====== @@ -256,7 +292,7 @@ TODO Author ====== -Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. +Yichun "agentzh" Zhang (章亦春) , OpenResty Inc. [Back to TOC](#table-of-contents) @@ -265,7 +301,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2013-2016, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2013-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/dist.ini b/dist.ini new file mode 100644 index 000000000..5e8fe79f3 --- /dev/null +++ b/dist.ini @@ -0,0 +1,10 @@ +name=lua-resty-core +abstract=New FFI-based Lua API for the ngx_lua module +author=Yichun "agentzh" Zhang (agentzh) +is_original=yes +license=2bsd +lib_dir=lib +doc_dir=lib +repo_link=https://github.com/openresty/lua-resty-core +main_module=lib/resty/core/base.lua +requires = luajit >= 2.1.0, nginx >= 1.11.2, ngx_http_lua = 0.10.9, openresty/lua-resty-lrucache >= 0.06 diff --git a/lib/ngx/balancer.md b/lib/ngx/balancer.md index 51513bac2..5884ca526 100644 --- a/lib/ngx/balancer.md +++ b/lib/ngx/balancer.md @@ -80,8 +80,8 @@ Description =========== This Lua module provides API functions to allow defining highly dynamic NGINX load balancers for -any existing nginx upstream modules like [http://nginx.org/en/docs/http/ngx_http_proxy_module.html ngx_proxy] and -[http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html ngx_fastcgi]. +any existing nginx upstream modules like [ngx_proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) and +[ngx_fastcgi](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html). It allows you to dynamically select a backend peer to connect to (or retry) on a per-request basis from a list of backend peers which may also be dynamic. @@ -173,7 +173,7 @@ Zero and negative timeout values are not allowed. You can specify millisecond precision in the timeout values by using floating point numbers like 0.001 (which means 1ms). -Returns `true` when the operation is successul; returns `nil` and a string describing the error +Returns `true` when the operation is successful; returns `nil` and a string describing the error otherwise. This only affects the current downstream request. It is not a global change. @@ -216,7 +216,7 @@ Please report bugs or submit patches by Author ====== -Yichun Zhang <agentzh@gmail.com> (agentzh), CloudFlare Inc. +Yichun Zhang <agentzh@gmail.com> (agentzh), OpenResty Inc. [Back to TOC](#table-of-contents) @@ -225,7 +225,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2015, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2015-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/lib/ngx/errlog.lua b/lib/ngx/errlog.lua new file mode 100644 index 000000000..2f8c2882e --- /dev/null +++ b/lib/ngx/errlog.lua @@ -0,0 +1,107 @@ +-- Copyright (C) Yichun Zhang (agentzh) + + +local ffi = require 'ffi' +local base = require "resty.core.base" +local ffi_string = ffi.string +local get_string_buf = base.get_string_buf +local get_size_ptr = base.get_size_ptr +local C = ffi.C +local new_tab = base.new_tab +local ffi_new = ffi.new +local charpp = ffi_new("char *[1]") +local intp = ffi.new("int[1]") +local num_value = ffi_new("double[1]") +local getfenv = getfenv +local tonumber = tonumber + + +local _M = { version = base.version } + + +ffi.cdef[[ +int ngx_http_lua_ffi_errlog_set_filter_level(int level, unsigned char *err, + size_t *errlen); +int ngx_http_lua_ffi_errlog_get_msg(char **log, int *loglevel, + unsigned char *err, size_t *errlen, double *log_time); + +int ngx_http_lua_ffi_errlog_get_sys_filter_level(ngx_http_request_t *r); +]] + + +local ERR_BUF_SIZE = 128 +local FFI_ERROR = base.FFI_ERROR + + +function _M.set_filter_level(level) + if not level then + return nil, [[missing "level" argument]] + end + + local err = get_string_buf(ERR_BUF_SIZE) + local errlen = get_size_ptr() + errlen[0] = ERR_BUF_SIZE + local rc = C.ngx_http_lua_ffi_errlog_set_filter_level(level, err, errlen) + + if rc == FFI_ERROR then + return nil, ffi_string(err, errlen[0]) + end + + return true +end + + +function _M.get_logs(max, logs) + local err = get_string_buf(ERR_BUF_SIZE) + local errlen = get_size_ptr() + errlen[0] = ERR_BUF_SIZE + + local log = charpp + local loglevel = intp + local log_time = num_value + + max = max or 10 + + if not logs then + logs = new_tab(max * 3 + 1, 0) + end + + local count = 0 + + for i = 1, max do + local loglen = C.ngx_http_lua_ffi_errlog_get_msg(log, loglevel, err, + errlen, log_time) + if loglen == FFI_ERROR then + return nil, ffi_string(err, errlen[0]) + end + + if loglen > 0 then + logs[count + 1] = loglevel[0] + logs[count + 2] = log_time[0] + logs[count + 3] = ffi_string(log[0], loglen) + + count = count + 3 + end + + if loglen < 0 then -- no error log + logs[count + 1] = nil + break + end + + if i == max then -- last one + logs[count + 1] = nil + break + end + end + + return logs +end + + +function _M.get_sys_filter_level() + local r = getfenv(0).__ngx_req + return tonumber(C.ngx_http_lua_ffi_errlog_get_sys_filter_level(r)) +end + + +return _M diff --git a/lib/ngx/errlog.md b/lib/ngx/errlog.md new file mode 100644 index 000000000..031ad3125 --- /dev/null +++ b/lib/ngx/errlog.md @@ -0,0 +1,318 @@ +Name +==== + +`ngx.errlog` - manage nginx error log data in Lua for OpenResty/ngx_lua. + +Table of Contents +================= + +* [Name](#name) +* [Status](#status) +* [Synopsis](#synopsis) + * [Capturing nginx error logs with specified log filtering level](#capturing-nginx-error-logs-with-specified-log-filtering-level) +* [Methods](#methods) + * [set_filter_level](#set_filter_level) + * [get_logs](#get_logs) + * [get_sys_filter_level](#get_sys_filter_level) +* [Community](#community) + * [English Mailing List](#english-mailing-list) + * [Chinese Mailing List](#chinese-mailing-list) +* [Bugs and Patches](#bugs-and-patches) +* [Author](#author) +* [Copyright and License](#copyright-and-license) +* [See Also](#see-also) + +Status +====== + +This Lua module is currently considered experimental. + +The API is still in flux and may change in the future without notice. + +Synopsis +======== + +Capturing nginx error logs with specified log filtering level +------------------------------------------------------------- + +```nginx +error logs/error.log info; + +http { + # enable capturing error logs + lua_capture_error_log 32m; + + init_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + ngx.log(ngx.ERR, err) + return + end + ngx.log(ngx.WARN, "set error filter level: WARN") + } + + server { + # ... + location = /t { + content_by_lua_block { + local errlog = require "ngx.errlog" + ngx.log(ngx.INFO, "test1") + ngx.log(ngx.WARN, "test2") + ngx.log(ngx.ERR, "test3") + + local logs, err = errlog.get_logs(10) + if not logs then + ngx.say("FAILED ", err) + return + end + + for i = 1, #logs, 3 do + ngx.say("level: ", logs[i], " time: ", logs[i + 1], + " data: ", logs[i + 2]) + end + } + } + } +} + +``` + +The example location above produces a response like this: + +``` +level: 5 time: 1498546995.304 data: 2017/06/27 15:03:15 [warn] 46877#0: + [lua] init_by_lua:8: set error filter level: WARN +level: 5 time: 1498546999.178 data: 2017/06/27 15:03:19 [warn] 46879#0: *1 + [lua] test.lua:5: test2, client: 127.0.0.1, server: localhost, ...... +level: 4 time: 1498546999.178 data: 2017/06/27 15:03:19 [error] 46879#0: *1 + [lua] test.lua:6: test3, client: 127.0.0.1, server: localhost, ...... +``` + +[Back to TOC](#table-of-contents) + +Methods +======= + +set_filter_level +----------------- +**syntax:** *status, err = log_module.set_filter_level(log_level)* + +**context:** *init_by_lua** + +Specifies the filter log level, only to capture and buffer the error logs with a log level +no lower than the specified level. + +If we don't call this API, all of the error logs will be captured by default. + +In case of error, `nil` will be returned as well as a string describing the +error. + +This API should always work with directive +[lua_capture_error_log](https://github.com/openresty/lua-nginx-module#lua_capture_error_log). + +See [Nginx log level constants](https://github.com/openresty/lua-nginx-module#nginx-log-level-constants) for all nginx log levels. + +For example, + +```lua + init_by_lua_block { + local errlog = require "ngx.errlog" + errlog.set_filter_level(ngx.WARN) + } +``` + +*NOTE:* The debugging logs since when OpenResty or NGINX is not built with `--with-debug`, all the debug level logs are suppressed regardless. + +[Back to TOC](#table-of-contents) + +get_logs +-------- +**syntax:** *res, err = log_module.get_logs(max?, res?)* + +**context:** *any* + +Fetches the captured nginx error log messages if any in the global data buffer +specified by `ngx_lua`'s +[lua_capture_error_log](https://github.com/openresty/lua-nginx-module#lua_capture_error_log) +directive. Upon return, this Lua function also *removes* those messages from +that global capturing buffer to make room for future new error log data. + +In case of error, `nil` will be returned as well as a string describing the +error. + +The optional `max` argument is a number that when specified, will prevent +`errlog.get_logs` from adding more than `max` messages to the `res` array. + +```lua +for i = 1, 20 do + ngx.log(ngx.ERR, "test") +end + +local errlog = require "ngx.errlog" +local res = errlog.get_logs(10) +-- the number of messages in the `res` table is 10 and the `res` table +-- has 30 elements. +``` + +The resulting table has the following structure: + +```lua +{ level1, time1, msg1, level2, time2, msg2, ... } +``` + +The `levelX` values are constants defined below: + +https://github.com/openresty/lua-nginx-module/#nginx-log-level-constants + +The `timeX` values are UNIX timestamps in seconds with millisecond precision. The sub-second part is presented as the decimal part. +The time format is exactly the same as the value returned by [ngx.now](https://github.com/openresty/lua-nginx-module/#ngxnow). It is +also subject to NGINX core's time caching. + +The `msgX` values are the error log message texts. + +So to traverse this array, the user can use a loop like this: + +```lua +for i = 1, #res, 3 do + local level = res[i] + if not level then + break + end + + local time = res[i + 1] + local msg = res[i + 2] + + -- handle the current message with log level in `level`, + -- log time in `time`, and log message body in `msg`. +end +``` + +Specifying `max <= 0` disables this behavior, meaning that the number of +results won't be limited. + +The optional 2th argument `res` can be a user-supplied Lua table +to hold the result instead of creating a brand new table. This can avoid +unnecessary table dynamic allocations on hot Lua code paths. It is used like this: + +```lua +local errlog = require "ngx.errlog" +local new_tab = require "table.new" + +local buffer = new_tab(100 * 3, 0) -- for 100 messages + +local errlog = require "ngx.errlog" +local res, err = errlog.get_logs(0, buffer) +if res then + -- res is the same table as `buffer` + for i = 1, #res, 3 do + local level = res[i] + if not level then + break + end + local time = res[i + 1] + local msg = res[i + 2] + ... + end +end +``` + +When provided with a `res` table, `errlog.get_logs` won't clear the table +for performance reasons, but will rather insert a trailing `nil` value +after the last table element. + +When the trailing `nil` is not enough for your purpose, you should +clear the table yourself before feeding it into the `errlog.get_logs` function. + +[Back to TOC](#table-of-contents) + +get_sys_filter_level +-------------------- +**syntax:** *log_level = log_module.get_sys_filter_level()* + +**context:** *any* + +Return the nginx core's error log filter level (defined via the [error_log](http://nginx.org/r/error_log) +configuration directive in `nginx.conf`) as an integer value matching the nginx error log level +constants documented below: + +https://github.com/openresty/lua-nginx-module/#nginx-log-level-constants + +For example: + +```lua +local errlog = require "ngx.errlog" +local log_level = errlog.get_sys_filter_level() +-- Now the filter level is always one level higher than system default log level on priority +local status, err = errlog.set_filter_level(log_level - 1) +if not status then + ngx.log(ngx.ERR, err) + return +end +``` + +[Back to TOC](#table-of-contents) + +Community +========= + +[Back to TOC](#table-of-contents) + +English Mailing List +-------------------- + +The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers. + +[Back to TOC](#table-of-contents) + +Chinese Mailing List +-------------------- + +The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers. + +[Back to TOC](#table-of-contents) + +Bugs and Patches +================ + +Please report bugs or submit patches by + +1. creating a ticket on the [GitHub Issue Tracker](https://github.com/openresty/lua-resty-core/issues), +1. or posting to the [OpenResty community](#community). + +[Back to TOC](#table-of-contents) + +Author +====== + +Yuansheng Wang <membphis@gmail.com> (membphis), OpenResty Inc. + +[Back to TOC](#table-of-contents) + +Copyright and License +===================== + +This module is licensed under the BSD license. + +Copyright (C) 2017, by Yichun "agentzh" Zhang, OpenResty Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[Back to TOC](#table-of-contents) + +See Also +======== +* library [lua-resty-core](https://github.com/openresty/lua-resty-core) +* the ngx_lua module: https://github.com/openresty/lua-nginx-module +* OpenResty: http://openresty.org + +[Back to TOC](#table-of-contents) + diff --git a/lib/ngx/ocsp.md b/lib/ngx/ocsp.md index 856ee8400..62c230810 100644 --- a/lib/ngx/ocsp.md +++ b/lib/ngx/ocsp.md @@ -72,7 +72,7 @@ server { -- use cosocket-based HTTP client libraries like lua-resty-http-simple -- to send the request (url + ocsp_req as POST params or URL args) to -- CA's OCSP server. assuming the server returns the OCSP response - -- in the Lua varaible, resp. + -- in the Lua variable, resp. local schema, host, port, ocsp_uri, err = parse_url(ocsp_url) @@ -115,7 +115,7 @@ server { end -- set the OCSP stapling - ok, err = ocsp.set_ocsp_status_resp(resp) + ok, err = ocsp.set_ocsp_status_resp(ocsp_resp) if not ok then ngx.log(ngx.ERR, "failed to set ocsp status resp: ", err) return ngx.exit(ngx.ERROR) @@ -264,7 +264,7 @@ Please report bugs or submit patches by Author ====== -Yichun Zhang <agentzh@gmail.com> (agentzh), CloudFlare Inc. +Yichun Zhang <agentzh@gmail.com> (agentzh), OpenResty Inc. [Back to TOC](#table-of-contents) @@ -273,7 +273,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2015, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2015-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/lib/ngx/process.lua b/lib/ngx/process.lua new file mode 100644 index 000000000..b797c0b2e --- /dev/null +++ b/lib/ngx/process.lua @@ -0,0 +1,60 @@ +-- Copyright (C) Yichun Zhang (agentzh) + + +local ffi = require 'ffi' +local base = require "resty.core.base" +local errmsg = base.get_errmsg_ptr() +local FFI_ERROR = base.FFI_ERROR +local ffi_str = ffi.string +local ngx_phase = ngx.get_phase +local tonumber = tonumber + + +local process_type_names = { + [0 ] = "single", + [1 ] = "master", + [2 ] = "signaller", + [3 ] = "worker", + [4 ] = "helper", + [99] = "privileged agent", +} + + +local C = ffi.C +local _M = { version = base.version } + + +ffi.cdef[[ +int ngx_http_lua_ffi_enable_privileged_agent(char **err); +int ngx_http_lua_ffi_get_process_type(void); +void ngx_http_lua_ffi_process_signal_graceful_exit(void); +]] + + +function _M.type() + local typ = C.ngx_http_lua_ffi_get_process_type() + return process_type_names[tonumber(typ)] +end + + +function _M.enable_privileged_agent() + if ngx_phase() ~= "init" then + return nil, "API disabled in the current context" + end + + local rc = C.ngx_http_lua_ffi_enable_privileged_agent(errmsg) + + if rc == FFI_ERROR then + return nil, ffi_str(errmsg[0]) + end + + return true +end + + +function _M.signal_graceful_exit() + C.ngx_http_lua_ffi_process_signal_graceful_exit() +end + + +return _M diff --git a/lib/ngx/process.md b/lib/ngx/process.md new file mode 100644 index 000000000..080b91370 --- /dev/null +++ b/lib/ngx/process.md @@ -0,0 +1,215 @@ +Name +==== + +`ngx.process` - manage the nginx processes for OpenResty/ngx_lua. + +Table of Contents +================= + +* [Name](#name) +* [Status](#status) +* [Synopsis](#synopsis) + * [Enables privileged agent process and get process type](#enables-privileged-agent-process-and-get-process-type) +* [Functions](#functions) + * [type](#type) + * [enable_privileged_agent](#enable_privileged_agent) + * [signal_graceful_exit](#signal_graceful_exit) +* [Community](#community) + * [English Mailing List](#english-mailing-list) + * [Chinese Mailing List](#chinese-mailing-list) +* [Bugs and Patches](#bugs-and-patches) +* [Author](#author) +* [Copyright and License](#copyright-and-license) +* [See Also](#see-also) + +Status +====== + +This Lua module is currently considered experimental. +The API is still in flux and may change in the future without notice. + +Synopsis +======== + +Enables privileged agent process and get process type +----------------------------------------- + +```nginx +# http config +init_by_lua_block { + local process = require "ngx.process" + + -- enables privileged agent process + local ok, err = process.enable_privileged_agent() + if not ok then + ngx.log(ngx.ERR, "enables privileged agent failed error:", err) + end + + -- output process type + ngx.log(ngx.INFO, "process type: ", process.type()) +} + +init_worker_by_lua_block { + local process = require "ngx.process" + ngx.log(ngx.INFO, "process type: ", process.type()) +} + +server { + # ... + location = /t { + content_by_lua_block { + local process = require "ngx.process" + ngx.say("process type: ", process.type()) + } + } +} + +``` + +The example config above produces an output to `error.log` when +server starts: + +``` +[lua] init_by_lua:11: process type: master +[lua] init_worker_by_lua:3: process type: privileged agent +[lua] init_worker_by_lua:3: process type: worker +``` + +The example location above produces the following response body: + +``` +process type: worker +``` + +[Back to TOC](#table-of-contents) + +Functions +========= + +type +---- +**syntax:** *type_name = process_module.type()* + +**context:** *any* + +Returns the current process's type name. Here are all of the names: + +``` +single +master +signaller +worker +helper +privileged agent +``` + +For example, + +```lua + local process = require "ngx.process" + ngx.say("process type:", process.type()) -- RESPONSE: worker +``` + +[Back to TOC](#table-of-contents) + +enable_privileged_agent +----------------------- +**syntax:** *ok, err = process_module.enable_privileged_agent()* + +**context:** *init_by_lua** + +Enables the privileged agent process in Nginx. + +The priviledged agent process does not listen on any virtual server ports like those worker processes. +And it uses the same system account as the nginx master process, which is usually a privileged account +like `root`. + +The `init_worker_by_lua*` directive handler still runs in the privileged agent process. And one can +use the [type](#type) function provided by this module to check if the current process is a privileged +agent. + +In case of failures, returns `nil` and a string describing the error. + +[Back to TOC](#table-of-contents) + +signal_graceful_exit +-------------------- +**syntax:** *process_module.signal_graceful_exit()* + +**context:** *any* + +Signals the *current* nginx (worker) process to quit gracefully, i.e., after all the timers have expired (in time or expired prematurely). + +Note that this API function simply sets the nginx global C variable `ngx_quit` to signal the nginx event +loop directly. No UNIX signals or IPC are involved here. + +WARNING: the official NGINX core does not perform the graceful exiting procedure when the [master_process](http://nginx.org/r/master_process) +directive is turned `off`. The OpenResty's NGINX core has a +[custom patch](https://github.com/openresty/openresty/blob/master/patches/nginx-1.11.2-single_process_graceful_exit.patch) +applied, which fixes this issue. + +[Back to TOC](#table-of-contents) + +Community +========= + +[Back to TOC](#table-of-contents) + +English Mailing List +-------------------- + +The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers. + +[Back to TOC](#table-of-contents) + +Chinese Mailing List +-------------------- + +The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers. + +[Back to TOC](#table-of-contents) + +Bugs and Patches +================ + +Please report bugs or submit patches by + +1. creating a ticket on the [GitHub Issue Tracker](https://github.com/openresty/lua-resty-core/issues), +1. or posting to the [OpenResty community](#community). + +[Back to TOC](#table-of-contents) + +Author +====== + +Yuansheng Wang <membphis@gmail.com> (membphis), OpenResty Inc. + +[Back to TOC](#table-of-contents) + +Copyright and License +===================== + +This module is licensed under the BSD license. + +Copyright (C) 2017, by Yichun "agentzh" Zhang, OpenResty Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[Back to TOC](#table-of-contents) + +See Also +======== +* library [lua-resty-core](https://github.com/openresty/lua-resty-core) +* the ngx_lua module: https://github.com/openresty/lua-nginx-module +* OpenResty: http://openresty.org + +[Back to TOC](#table-of-contents) + diff --git a/lib/ngx/re.lua b/lib/ngx/re.lua new file mode 100644 index 000000000..2ca40164e --- /dev/null +++ b/lib/ngx/re.lua @@ -0,0 +1,273 @@ +-- I hereby assign copyright in this code to the lua-resty-core project, +-- to be licensed under the same terms as the rest of the code. + + +local ffi = require 'ffi' +local bit = require "bit" +local base = require "resty.core.base" +local core_regex = require "resty.core.regex" + + +local C = ffi.C +local ffi_str = ffi.string +local sub = string.sub +local error = error +local type = type +local band = bit.band +local new_tab = base.new_tab +local tostring = tostring +local math_max = math.max +local math_min = math.min +local is_regex_cache_empty = core_regex.is_regex_cache_empty +local re_match_compile = core_regex.re_match_compile +local destroy_compiled_regex = core_regex.destroy_compiled_regex +local get_string_buf = base.get_string_buf +local get_size_ptr = base.get_size_ptr +local FFI_OK = base.FFI_OK + + +local MAX_ERR_MSG_LEN = 128 +local FLAG_DFA = 0x02 +local PCRE_ERROR_NOMATCH = -1 +local DEFAULT_SPLIT_RES_SIZE = 4 + + +local split_ctx = new_tab(0, 1) + + +ffi.cdef[[ +int ngx_http_lua_ffi_set_jit_stack_size(int size, unsigned char *errstr, + size_t *errstr_size); +]] + + +local _M = { version = base.version } + + +local function re_split_helper(subj, compiled, compile_once, flags, ctx) + local rc + do + local pos = math_max(ctx.pos - 1, 0) + + rc = C.ngx_http_lua_ffi_exec_regex(compiled, flags, subj, #subj, pos) + end + + if rc == PCRE_ERROR_NOMATCH then + if not compile_once then + destroy_compiled_regex(compiled) + end + return nil, nil, nil + end + + if rc < 0 then + if not compile_once then + destroy_compiled_regex(compiled) + end + return nil, nil, nil, "pcre_exec() failed: " .. rc + end + + if rc == 0 then + if band(flags, FLAG_DFA) == 0 then + return nil, nil, nil, "capture size too small" + end + + rc = 1 + end + + local caps = compiled.captures + local ncaps = compiled.ncaptures + + local from = caps[0] + local to = caps[1] + + if from < 0 or to < 0 then + return nil, nil, nil + end + + -- convert to Lua string indexes + + from = from + 1 + to = to + 1 + ctx.pos = to + 1 + + -- retrieve the first sub-match capture if any + + if ncaps > 0 and rc > 1 then + return from, to, sub(subj, caps[2] + 1, caps[3]) + end + + return from, to +end + + +function _M.split(subj, regex, opts, ctx, max, res) + -- we need to cast this to strings to avoid exceptions when they are + -- something else. + -- needed because of further calls to string.sub in this function. + subj = tostring(subj) + + if not ctx then + ctx = split_ctx + ctx.pos = 1 -- set or reset upvalue field + + elseif not ctx.pos then + -- ctx provided by user but missing pos field + ctx.pos = 1 + end + + max = max or 0 + + if not res then + -- limit the initial arr_n size of res to a reasonable value + -- 0 < narr <= DEFAULT_SPLIT_RES_SIZE + local narr = DEFAULT_SPLIT_RES_SIZE + if max > 0 then + -- the user specified a valid max limiter if max > 0 + narr = math_min(narr, max) + end + + res = new_tab(narr, 0) + + elseif type(res) ~= "table" then + return error("res is not a table", 2) + end + + local len = #subj + if ctx.pos > len then + res[1] = nil + return res + end + + -- compile regex + + local compiled, compile_once, flags = re_match_compile(regex, opts) + if compiled == nil then + -- compiled_once holds the error string + return nil, compile_once + end + + local sub_idx = ctx.pos + local res_idx = 0 + local last_empty_match + + -- splitting: with and without a max limiter + + if max > 0 then + local count = 1 + + while count < max do + local from, to, capture, err = re_split_helper(subj, compiled, + compile_once, flags, ctx) + if err then + return nil, err + end + + if not from then + break + end + + if last_empty_match then + sub_idx = last_empty_match + end + + if from == to then + last_empty_match = from + end + + if from > sub_idx or not last_empty_match then + count = count + 1 + res_idx = res_idx + 1 + res[res_idx] = sub(subj, sub_idx, from - 1) + + if capture then + res_idx = res_idx + 1 + res[res_idx] = capture + end + + sub_idx = to + + if sub_idx >= len then + break + end + end + end + + if count == max then + if not compile_once then + destroy_compiled_regex(compiled) + end + end + + else + while true do + local from, to, capture, err = re_split_helper(subj, compiled, + compile_once, flags, ctx) + if err then + return nil, err + end + + if not from then + break + end + + if last_empty_match then + sub_idx = last_empty_match + end + + if from == to then + last_empty_match = from + end + + if from > sub_idx or not last_empty_match then + res_idx = res_idx + 1 + res[res_idx] = sub(subj, sub_idx, from - 1) + + if capture then + res_idx = res_idx + 1 + res[res_idx] = capture + end + + sub_idx = to + + if sub_idx >= len then + break + end + end + end + + end + + -- trailing nil for non-cleared res tables + + res[res_idx + 1] = sub(subj, sub_idx) + res[res_idx + 2] = nil + + return res +end + + +function _M.opt(option, value) + if option == "jit_stack_size" then + if not is_regex_cache_empty() then + error("changing jit stack size is not allowed when some " .. + "regexs have already been compiled and cached") + end + + local errbuf = get_string_buf(MAX_ERR_MSG_LEN) + local sizep = get_size_ptr() + sizep[0] = MAX_ERR_MSG_LEN + + local rc = C.ngx_http_lua_ffi_set_jit_stack_size(value, errbuf, sizep) + + if rc == FFI_OK then + return + end + + error(ffi_str(errbuf, sizep[0])) + end + + error("unrecognized option name") +end + + +return _M diff --git a/lib/ngx/re.md b/lib/ngx/re.md new file mode 100644 index 000000000..1c97ff668 --- /dev/null +++ b/lib/ngx/re.md @@ -0,0 +1,249 @@ +Name +==== + +ngx.re - Lua API for convenience utilities for `ngx.re`. + +Table of Contents +================= + +* [Name](#name) +* [Status](#status) +* [Synopsis](#synopsis) +* [Description](#description) +* [Methods](#methods) + * [split](#split) + * [opt](#opt) +* [Community](#community) + * [English Mailing List](#english-mailing-list) + * [Chinese Mailing List](#chinese-mailing-list) +* [Bugs and Patches](#bugs-and-patches) +* [Author](#author) +* [Copyright and License](#copyright-and-license) +* [See Also](#see-also) + +Status +====== + +This Lua module is currently considered experimental. + +Synopsis +======== + +```lua +local ngx_re = require "ngx.re" + +-- split +local res, err = ngx_re.split("a,b,c,d", ",") +--> res is now {"a", "b", "c", "d"} + +-- opt +ngx_re.opt("jit_stack_size", 128 * 1024) +--> the PCRE jit stack can now handle more complex regular expressions +``` + +[Back to TOC](#table-of-contents) + +Description +=========== + +This Lua module provides a Lua API which implements convenience utilities for +the `ngx.re` API. + +[Back to TOC](#table-of-contents) + +Methods +======= + +All the methods of this module are static (or module-level). That is, you do +not need an object (or instance) to call these methods. + +[Back to TOC](#table-of-contents) + +split +----- +**syntax:** *res, err = ngx_re.split(subject, regex, options?, ctx?, max?, res?)* + +Splits the `subject` string using the Perl compatible regular expression +`regex` with the optional `options`. + +This function returns a Lua (array) table (with integer keys) containing the +splitted values. + +In case of error, `nil` will be returned as well as a string describing the +error. + +When `regex` contains a sub-match capturing group, and when such a match is +found, the first submatch capture will be inserted in between each splitted +value, like so: + +```lua +local ngx_re = require "ngx.re" + +local res, err = ngx_re.split("a,b,c,d", "(,)") +-- res is now {"a", ",", "b", ",", "c", ",", "d"} +``` + +When `regex` is empty string `""`, the `subject` will be split into chars, +like so: + +```lua +local ngx_re = require "ngx.re" + +local res, err = ngx_re.split("abcd", "") +-- res is now {"a", "b", "c", "d"} +``` + +The optional `ctx` table argument can be a Lua table holding an optional `pos` +field. When the `pos` field in the `ctx` table argument is specified, +`ngx_re.split` will start splitting the `subject` from that index: + +```lua +local ngx_re = require "ngx.re" + +local res, err = ngx_re.split("a,b,c,d", ",", nil, {pos = 5}) +-- res is now {"c", "d"} +``` + +The optional `max` argument is a number that when specified, will prevent +`ngx_re.split` from adding more than `max` matches to the `res` array: + +```lua +local ngx_re = require "ngx.re" + +local res, err = ngx_re.split("a,b,c,d", ",", nil, nil, 3) +-- res is now {"a", "b", "c,d"} +``` + +Specifying `max <= 0` disables this behavior, meaning that the number of +results won't be limited. + +The optional 6th argument `res` can be a table that `ngx_re.split` will re-use +to hold the results instead of creating a new one, which can improve +performance in hot code paths. It is used like so: + +```lua +local ngx_re = require "ngx.re" + +local my_table = {"hello world"} + +local res, err = ngx_re.split("a,b,c,d", ",", nil, nil, nil, my_table) +-- res/my_table is now {"a", "b", "c", "d"} +``` + +When provided with a `res` table, `ngx_re.split` won't clear the table +for performance reasons, but will rather insert a trailing `nil` value +when the split is completed: + +```lua +local ngx_re = require "ngx.re" + +local my_table = {"W", "X", "Y", "Z"} + +local res, err = ngx_re.split("a,b", ",", nil, nil, nil, my_table) +-- res/my_table is now {"a", "b", nil, "Z"} +``` + +When the trailing `nil` is not enough for your purpose, you should +clear the table yourself before feeding it into the `split` function. + +[Back to TOC](#table-of-contents) + +opt +----- +**syntax:** *ngx_re.opt(option, value)* + +Allows changing of regex settings. Currently, it can only change the +`jit_stack_size` of the PCRE engine, like so: + +```nginx + + init_by_lua_block { require "ngx.re".opt("jit_stack_size", 200 * 1024) } + + server { + location /re { + content_by_lua_block { + -- full regex and string are taken from https://github.com/JuliaLang/julia/issues/8278 + local very_long_string = [[71.163.72.113 - - [30/Jul/2014:16:40:55 -0700] ...]] + local very_complicated_regex = [[([\d\.]+) ([\w.-]+) ([\w.-]+) (\[.+\]) ...]] + local from, to, err = ngx.re.find(very_long_string, very_complicated_regex, "jo") + + -- with the regular jit_stack_size, we would get the error 'pcre_exec() failed: -27' + -- instead, we get a match + ngx.print(from .. "-" .. to) -- prints '1-1563' + } + } + } +``` + +The `jit_stack_size` cannot be set to a value lower than PCRE's default of 32K. + +This method requires the PCRE library enabled in Nginx. + +This feature was first introduced in the `v0.1.12` release. + +[Back to TOC](#table-of-contents) + +Community +========= + +[Back to TOC](#table-of-contents) + +English Mailing List +-------------------- + +The [openresty-en](https://groups.google.com/group/openresty-en) mailing list +is for English speakers. + +[Back to TOC](#table-of-contents) + +Chinese Mailing List +-------------------- + +The [openresty](https://groups.google.com/group/openresty) mailing list is for +Chinese speakers. + +[Back to TOC](#table-of-contents) + +Bugs and Patches +================ + +Please report bugs or submit patches by + +1. creating a ticket on the [GitHub Issue Tracker](https://github.com/openresty/lua-resty-core/issues), +1. or posting to the [OpenResty community](#community). + +[Back to TOC](#table-of-contents) + +Author +====== + +Thibault Charbonnier - ([@thibaultcha](https://github.com/thibaultcha)) + +[Back to TOC](#table-of-contents) + +Copyright and License +===================== + +This module is licensed under the BSD license. + +Copyright (C) 2016-2017, by Yichun "agentzh" Zhang, OpenResty Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[Back to TOC](#table-of-contents) + +See Also +======== +* library [lua-resty-core](https://github.com/openresty/lua-resty-core) +* the ngx_lua module: https://github.com/openresty/lua-nginx-module +* OpenResty: http://openresty.org + +[Back to TOC](#table-of-contents) diff --git a/lib/ngx/semaphore.lua b/lib/ngx/semaphore.lua index dc28c30ab..0d9234b87 100644 --- a/lib/ngx/semaphore.lua +++ b/lib/ngx/semaphore.lua @@ -114,7 +114,8 @@ function _M.wait(self, seconds) -- might need the current function call's activation -- record to hold the reference to our semaphore object -- to prevent it from getting GC'd prematurely. - local ok, err = co_yield() + local ok + ok, err = co_yield() return ok, err end diff --git a/lib/ngx/semaphore.md b/lib/ngx/semaphore.md index aad9576ba..8c9314fa6 100644 --- a/lib/ngx/semaphore.md +++ b/lib/ngx/semaphore.md @@ -332,7 +332,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2015, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2015-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/lib/ngx/ssl.md b/lib/ngx/ssl.md index 8ca2b9871..fc63c24e9 100644 --- a/lib/ngx/ssl.md +++ b/lib/ngx/ssl.md @@ -84,7 +84,14 @@ server { -- assuming the user already defines the my_load_private_key() -- function herself. - local der_pkey = assert(my_load_private_key()) + local pem_pkey = assert(my_load_private_key()) + + local der_pkey, err = ssl.priv_key_pem_to_der(pem_pkey) + if not der_pkey then + ngx.log(ngx.ERR, "failed to convert private key ", + "from PEM to DER: ", err) + return ngx.exit(ngx.ERROR) + end local ok, err = ssl.set_der_priv_key(der_pkey) if not ok then @@ -199,7 +206,7 @@ This function can be called in whatever contexts. set_der_priv_key ---------------- -**syntax:** *ok, err = ssl.set_der_priv_key(der_cert_chain)* +**syntax:** *ok, err = ssl.set_der_priv_key(der_priv_key)* **context:** *ssl_certificate_by_lua** @@ -362,6 +369,10 @@ Sets the SSL certificate chain opaque pointer returned by the Returns `true` on success, or a `nil` value and a string describing the error otherwise. +Note that this `set_cert` function will run slightly faster, in terms of CPU cycles wasted, than the +[set_der_cert](#set_der_cert) variant, since the first function uses opaque cdata pointers +which do not require any additional conversion needed to be performed by the SSL library during the SSL handshake. + This function was first added in version `0.1.7`. [Back to TOC](#table-of-contents) @@ -377,6 +388,10 @@ Sets the SSL private key opaque pointer returned by the Returns `true` on success, or a `nil` value and a string describing the error otherwise. +Note that this `set_priv_key` function will run slightly faster, in terms of CPU cycles wasted, than the +[set_der_priv_key](#set_der_priv_key) variant, since the first function uses opaque cdata pointers +which do not require any additional conversion needed to be performed by the SSL library during the SSL handshake. + This function was first added in version `0.1.7`. [Back to TOC](#table-of-contents) @@ -413,7 +428,7 @@ Please report bugs or submit patches by Author ====== -Yichun Zhang <agentzh@gmail.com> (agentzh), CloudFlare Inc. +Yichun Zhang <agentzh@gmail.com> (agentzh), OpenResty Inc. [Back to TOC](#table-of-contents) @@ -422,7 +437,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2015, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2015-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/lib/ngx/ssl/session.lua b/lib/ngx/ssl/session.lua index cca593efe..6944cf169 100644 --- a/lib/ngx/ssl/session.lua +++ b/lib/ngx/ssl/session.lua @@ -1,4 +1,4 @@ -local _M = {} +-- Copyright (C) Yichun Zhang (agentzh) local ffi = require "ffi" @@ -32,6 +32,9 @@ int ngx_http_lua_ffi_ssl_get_session_id_size(ngx_http_request_t *r, ]] +local _M = { version = base.version } + + -- return session, err function _M.get_serialized_session() local r = getfenv(0).__ngx_req diff --git a/lib/ngx/ssl/session.md b/lib/ngx/ssl/session.md index 30708545f..b6671b37a 100644 --- a/lib/ngx/ssl/session.md +++ b/lib/ngx/ssl/session.md @@ -37,99 +37,99 @@ Synopsis # OpenResty 1.11.2.1+. lua_package_path "/path/to/lua-resty-core/lib/?.lua;;"; -server { - listen 443 ssl; - server_name test.com; +ssl_session_fetch_by_lua_block { + local ssl_sess = require "ngx.ssl.session" + + local sess_id, err = ssl_sess.get_session_id() + if not sess_id then + ngx.log(ngx.ERR, "failed to get session ID: ", err) + -- considered a cache miss, and just return... + return + end + + -- the user is supposed to implement the my_lookup_ssl_session_by_id + -- Lua function used below. She can look up an external memcached + -- or redis cluster, for example. And she can also introduce a local + -- cache layer at the same time... + local sess, err = my_lookup_ssl_session_by_id(sess_id) + if not sess then + if err then + ngx.log(ngx.ERR, "failed to look up the session by ID ", + sess_id, ": ", err) + return + end - # well, we could configure ssl_certificate_by_lua* here as well... - ssl_certificate /path/to/server-cert.pem; - ssl_certificate_key /path/to/server-priv-key.pem; + -- cache miss...just return + return + end - ssl_session_fetch_by_lua_block { - local ssl_sess = require "ngx.ssl.session" + local ok, err = ssl_sess.set_serialized_session(sess) + if not ok then + ngx.log(ngx.ERR, "failed to set SSL session for ID ", sess_id, + ": ", err) + -- consider it as a cache miss... + return + end - local sess_id, err = ssl_sess.get_session_id() - if not sess_id then - ngx.log(ngx.ERR, "failed to get session ID: ", err) - -- considered a cache miss, and just return... - return - end + -- done here, SSL session successfully set and should resume accordingly... +} - -- the user is supposed to implement the my_lookup_ssl_session_by_id - -- Lua function used below. She can look up an external memcached - -- or redis cluster, for example. And she can also introduce a local - -- cache layer at the same time... - local sess, err = my_lookup_ssl_session_by_id(sess_id) +ssl_session_store_by_lua_block { + local ssl_sess = require "ngx.ssl.session" + + local sess_id, err = ssl_sess.get_session_id() + if not sess_id then + ngx.log(ngx.ERR, "failed to get session ID: ", err) + -- just give up + return + end + + local sess, err = ssl_sess.get_serialized_session() + if not sess then + ngx.log(ngx.ERR, "failed to get SSL session from the ", + "current connection: ", err) + -- just give up + return + end + + -- for the best performance, we should avoid creating a closure + -- dynamically here on the hot code path. Instead, we should + -- put this function in one of our own Lua module files. this + -- example is just for demonstration purposes... + local function save_it(premature, sess_id, sess) + -- the user is supposed to implement the + -- my_save_ssl_session_by_id Lua function used below. + -- She can save to an external memcached + -- or redis cluster, for example. And she can also introduce + -- a local cache layer at the same time... + local sess, err = my_save_ssl_session_by_id(sess_id, sess) if not sess then if err then - ngx.log(ngx.ERR, "failed to look up the session by ID ", + ngx.log(ngx.ERR, "failed to save the session by ID ", sess_id, ": ", err) - return + return ngx.exit(ngx.ERROR) end -- cache miss...just return return end + end + + -- create a 0-delay timer here... + local ok, err = ngx.timer.at(0, save_it, sess_id, sess) + if not ok then + ngx.log(ngx.ERR, "failed to create a 0-delay timer: ", err) + return + end +} - local ok, err = ssl_sess.set_serialized_session(sess) - if not ok then - ngx.log(ngx.ERR, "failed to set SSL session for ID ", sess_id, - ": ", err) - -- consider it as a cache miss... - return - end - - -- done here, SSL session successfully set and should resume accordingly... - } - - ssl_session_store_by_lua_block { - local ssl_sess = require "ngx.ssl.session" - - local sess_id, err = ssl_sess.get_session_id() - if not sess_id then - ngx.log(ngx.ERR, "failed to get session ID: ", err) - -- just give up - return - end - - local sess, err = ssl_sess.get_serialized_session() - if not sess then - ngx.log(ngx.ERR, "failed to get SSL session from the ", - "current connection: ", err) - -- just give up - return - end - - -- for the best performance, we should avoid creating a closure - -- dynamically here on the hot code path. Instead, we should - -- put this function in one of our own Lua module files. this - -- example is just for demonstration purposes... - local function save_it(premature, sess_id, sess) - -- the user is supposed to implement the - -- my_save_ssl_session_by_id Lua function used below. - -- She can save to an external memcached - -- or redis cluster, for example. And she can also introduce - -- a local cache layer at the same time... - local sess, err = my_save_ssl_session_by_id(sess_id, sess) - if not sess then - if err then - ngx.log(ngx.ERR, "failed to save the session by ID ", - sess_id, ": ", err) - return ngx.exit(ngx.ERROR) - end - - -- cache miss...just return - return - end - end +server { + listen 443 ssl; + server_name test.com; - -- create a 0-delay timer here... - local ok, err = ngx.timer.at(0, save_it) - if not ok then - ngx.log(ngx.ERR, "failed to create a 0-delay timer: ", err) - return - end - } + # well, we could configure ssl_certificate_by_lua* here as well... + ssl_certificate /path/to/server-cert.pem; + ssl_certificate_key /path/to/server-priv-key.pem; } ``` @@ -243,7 +243,7 @@ Please report bugs or submit patches by Author ====== -Yichun Zhang <agentzh@gmail.com> (agentzh), CloudFlare Inc. +Yichun Zhang <agentzh@gmail.com> (agentzh), OpenResty Inc. [Back to TOC](#table-of-contents) @@ -252,7 +252,7 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2016, by Yichun "agentzh" Zhang, CloudFlare Inc. +Copyright (C) 2016-2017, by Yichun "agentzh" Zhang, OpenResty Inc. All rights reserved. diff --git a/lib/resty/core/base.lua b/lib/resty/core/base.lua index 35e29beae..c0abb6123 100644 --- a/lib/resty/core/base.lua +++ b/lib/resty/core/base.lua @@ -15,15 +15,15 @@ local FREE_LIST_REF = 0 if not ngx.config or not ngx.config.ngx_lua_version - or ngx.config.ngx_lua_version < 10006 + or ngx.config.ngx_lua_version < 10009 then - error("ngx_lua 0.10.6+ required") + error("ngx_lua 0.10.9+ required") end if string.find(jit.version, " 2.0") then - ngx.log(ngx.WARN, "use of lua-resty-core with LuaJIT 2.0 is " - .. "not recommended; use LuaJIT 2.1+ instead") + ngx.log(ngx.ALERT, "use of lua-resty-core with LuaJIT 2.0 is ", + "not recommended; use LuaJIT 2.1+ instead") end @@ -33,7 +33,8 @@ if not ok then end -local ok, clear_tab = pcall(require, "table.clear") +local clear_tab +ok, clear_tab = pcall(require, "table.clear") if not ok then clear_tab = function (tab) for k, _ in pairs(tab) do @@ -95,7 +96,7 @@ local c_buf_type = ffi.typeof("char[?]") local _M = new_tab(0, 16) -_M.version = "0.1.8" +_M.version = "0.1.12" _M.new_tab = new_tab _M.clear_tab = clear_tab diff --git a/lib/resty/core/exit.lua b/lib/resty/core/exit.lua index 2fad312aa..210069cdd 100644 --- a/lib/resty/core/exit.lua +++ b/lib/resty/core/exit.lua @@ -31,7 +31,7 @@ ngx.exit = function (rc) return error("no request found") end errlen[0] = ERR_BUF_SIZE - local rc = C.ngx_http_lua_ffi_exit(r, rc, err, errlen) + rc = C.ngx_http_lua_ffi_exit(r, rc, err, errlen) if rc == 0 then -- print("yielding...") return co_yield() diff --git a/lib/resty/core/misc.lua b/lib/resty/core/misc.lua index 5b7a690e0..2f30528d0 100644 --- a/lib/resty/core/misc.lua +++ b/lib/resty/core/misc.lua @@ -123,7 +123,7 @@ local function is_subreq() return error("API disabled in the current context") end - return rc == 1 and true or false + return rc == 1 end register_getter("is_subrequest", is_subreq) diff --git a/lib/resty/core/regex.lua b/lib/resty/core/regex.lua index 95db44e03..071e6ad29 100644 --- a/lib/resty/core/regex.lua +++ b/lib/resty/core/regex.lua @@ -140,6 +140,7 @@ local _M = { local buf_grow_ratio = 2 + function _M.set_buf_grow_ratio(ratio) buf_grow_ratio = ratio end @@ -154,6 +155,20 @@ local function get_max_regex_cache_size() end +local regex_cache_is_empty = true + + +function _M.is_regex_cache_empty() + return regex_cache_is_empty +end + + +local function lrucache_set_wrapper(...) + regex_cache_is_empty = false + lrucache_set(...) +end + + local function parse_regex_opts(opts) local t = cached_re_opts[opts] if t then @@ -281,11 +296,17 @@ local function collect_captures(compiled, rc, subj, flags, res) end +_M.collect_captures = collect_captures + + local function destroy_compiled_regex(compiled) C.ngx_http_lua_ffi_destroy_regex(ffi_gc(compiled, nil)) end +_M.destroy_compiled_regex = destroy_compiled_regex + + local function re_match_compile(regex, opts) local flags = 0 local pcre_opts = 0 @@ -335,7 +356,7 @@ local function re_match_compile(regex, opts) if compile_once then -- print("inserting compiled regex into cache") - lrucache_set(regex_match_cache, key, compiled) + lrucache_set_wrapper(regex_match_cache, key, compiled) end end @@ -343,6 +364,9 @@ local function re_match_compile(regex, opts) end +_M.re_match_compile = re_match_compile + + local function re_match_helper(subj, regex, opts, ctx, want_caps, res, nth) -- we need to cast this to strings to avoid exceptions when they are -- something else. @@ -485,6 +509,9 @@ local function check_buf_size(buf, buf_size, pos, len, new_len, must_alloc) end +_M.check_buf_size = check_buf_size + + local function re_sub_compile(regex, opts, replace, func) local flags = 0 local pcre_opts = 0 @@ -587,6 +614,9 @@ local function re_sub_compile(regex, opts, replace, func) end +_M.re_sub_compile = re_sub_compile + + local function re_sub_func_helper(subj, regex, replace, opts, global) local compiled, compile_once, flags = re_sub_compile(regex, opts, nil, replace) @@ -641,10 +671,10 @@ local function re_sub_func_helper(subj, regex, replace, opts, global) local res = collect_captures(compiled, rc, subj, flags) - local bit = tostring(replace(res)) - local bit_len = #bit + local piece = tostring(replace(res)) + local piece_len = #piece - local new_dst_len = dst_len + prefix_len + bit_len + local new_dst_len = dst_len + prefix_len + piece_len dst_buf, dst_buf_size, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len, true) @@ -655,9 +685,9 @@ local function re_sub_func_helper(subj, regex, replace, opts, global) dst_pos = dst_pos + prefix_len end - if bit_len > 0 then - ffi_copy(dst_pos, bit, bit_len) - dst_pos = dst_pos + bit_len + if piece_len > 0 then + ffi_copy(dst_pos, piece, piece_len) + dst_pos = dst_pos + piece_len end cp_pos = compiled.captures[1] @@ -683,7 +713,8 @@ local function re_sub_func_helper(subj, regex, replace, opts, global) local suffix_len = subj_len - cp_pos local new_dst_len = dst_len + suffix_len - dst_buf, dst_buf_size, dst_pos, dst_len = + local _ + dst_buf, _, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len, true) @@ -812,7 +843,8 @@ local function re_sub_str_helper(subj, regex, replace, opts, global) local suffix_len = subj_len - cp_pos local new_dst_len = dst_len + suffix_len - dst_buf, dst_buf_size, dst_pos, dst_len = + local _ + dst_buf, _, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len) diff --git a/lib/resty/core/shdict.lua b/lib/resty/core/shdict.lua index 20f40ae74..7ab55eda6 100644 --- a/lib/resty/core/shdict.lua +++ b/lib/resty/core/shdict.lua @@ -19,9 +19,6 @@ local ngx_shared = ngx.shared local getmetatable = getmetatable -local MAX_ERR_MSG_LEN = 128 - - ffi.cdef[[ int ngx_http_lua_ffi_shdict_get(void *zone, const unsigned char *key, size_t key_len, int *value_type, unsigned char **str_value_buf, @@ -101,9 +98,9 @@ local function shdict_store(zone, op, key, value, exptime, flags) return nil, "key too long" end - local str_value_buf - local str_value_len = 0 - local num_value = 0 + local str_val_buf + local str_val_len = 0 + local num_val = 0 local valtyp = type(value) -- print("value type: ", valtyp) @@ -111,27 +108,27 @@ local function shdict_store(zone, op, key, value, exptime, flags) if valtyp == "string" then valtyp = 4 -- LUA_TSTRING - str_value_buf = value - str_value_len = #value + str_val_buf = value + str_val_len = #value elseif valtyp == "number" then valtyp = 3 -- LUA_TNUMBER - num_value = value + num_val = value elseif value == nil then valtyp = 0 -- LUA_TNIL elseif valtyp == "boolean" then valtyp = 1 -- LUA_TBOOLEAN - num_value = value and 1 or 0 + num_val = value and 1 or 0 else return nil, "bad value type" end local rc = C.ngx_http_lua_ffi_shdict_store(zone, op, key, key_len, - valtyp, str_value_buf, - str_value_len, num_value, + valtyp, str_val_buf, + str_val_len, num_val, exptime * 1000, flags, errmsg, forcible) @@ -391,7 +388,7 @@ end if ngx_shared then - local name, dict = next(ngx_shared, nil) + local _, dict = next(ngx_shared, nil) if dict then local mt = getmetatable(dict) if mt then diff --git a/lib/resty/core/worker.lua b/lib/resty/core/worker.lua index 1e9b0963e..0da8086cc 100644 --- a/lib/resty/core/worker.lua +++ b/lib/resty/core/worker.lua @@ -17,7 +17,7 @@ int ngx_http_lua_ffi_worker_count(void); function ngx.worker.exiting() - return C.ngx_http_lua_ffi_worker_exiting() ~= 0 and true or false + return C.ngx_http_lua_ffi_worker_exiting() ~= 0 end diff --git a/t/balancer.t b/t/balancer.t index 511b0da4b..4cde517c5 100644 --- a/t/balancer.t +++ b/t/balancer.t @@ -707,7 +707,7 @@ qr/\[error] .*? upstream prematurely closed connection while reading response he === TEST 16: https (keepalive) ---- skip_nginx: 4: < 1.7.5 +--- skip_nginx: 5: < 1.7.5 --- http_config lua_package_path "$TEST_NGINX_CWD/lib/?.lua;;"; @@ -748,6 +748,7 @@ ok --- grep_error_log eval: qr{hello from balancer by lua!} --- grep_error_log_out hello from balancer by lua! +--- no_check_leak diff --git a/t/count.t b/t/count.t index 74e61bcea..0b61ba9ee 100644 --- a/t/count.t +++ b/t/count.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { -- local verbose = true local verbose = false local outfile = "$Test::Nginx::Util::ErrLogFile" @@ -32,7 +32,7 @@ our $HttpConfig = <<_EOC_; -- jit.opt.start("hotloop=1") -- jit.opt.start("loopunroll=1000000") -- jit.off() - '; + } _EOC_ #no_diff(); @@ -46,14 +46,14 @@ __DATA__ --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local base = require "resty.core.base" local n = 0 for _, _ in pairs(base) do n = n + 1 end ngx.say("base size: ", n) - '; + } } --- request GET /re @@ -69,4 +69,3 @@ probe process("$LIBLUA_PATH").function("rehashtab") { base size: 16 --- no_error_log [error] - diff --git a/t/ctx.t b/t/ctx.t index a848ea0c8..9cceb6f0d 100644 --- a/t/ctx.t +++ b/t/ctx.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;\$prefix/html/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -42,12 +42,12 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { for i = 1, 100 do ngx.ctx.foo = i end ngx.say("ctx.foo = ", ngx.ctx.foo) - '; + } } --- request GET /t @@ -66,12 +66,12 @@ qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):2 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { for i = 1, 100 do ngx.ctx = {foo = i} end ngx.say("ctx.foo = ", ngx.ctx.foo) - '; + } } --- request GET /t @@ -83,4 +83,3 @@ ctx.foo = 100 bad argument --- error_log eval qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):2 loop\]/ - diff --git a/t/decode-base64.t b/t/decode-base64.t index 632d0808e..140d822e8 100644 --- a/t/decode-base64.t +++ b/t/decode-base64.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -27,7 +27,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,13 +41,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64("aGVsbG8=") end ngx.say(s) - '; + } } --- request GET /base64 @@ -65,13 +65,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64("") end ngx.say(s) - '; + } } --- request GET /base64 @@ -88,13 +88,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64("My4xNA==") end ngx.say(s) - '; + } } --- request GET /base64 @@ -112,13 +112,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64("dHJ1ZQ==") end ngx.say(s) - '; + } } --- request GET /base64 @@ -136,7 +136,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64(string.rep("a", 5460)) @@ -146,7 +146,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ else ngx.say(string.len(s)) end - '; + } } --- request GET /base64 @@ -164,7 +164,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.decode_base64(string.rep("a", 5462)) @@ -174,7 +174,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ else ngx.say(string.len(s)) end - '; + } } --- request GET /base64 @@ -185,4 +185,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] -- NYI: - diff --git a/t/encode-base64.t b/t/encode-base64.t index f6bda6978..b022b3ab2 100644 --- a/t/encode-base64.t +++ b/t/encode-base64.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -27,7 +27,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,13 +41,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64("hello") end ngx.say(s) - '; + } } --- request GET /base64 @@ -65,13 +65,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64(nil) end ngx.say(s) - '; + } } --- request GET /base64 @@ -88,13 +88,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64(3.14) end ngx.say(s) - '; + } } --- request GET /base64 @@ -112,13 +112,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64(true) end ngx.say(s) - '; + } } --- request GET /base64 @@ -136,13 +136,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64(string.rep("a", 3073)) end ngx.say(string.len(s)) - '; + } } --- request GET /base64 @@ -160,13 +160,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.encode_base64(string.rep("a", 3071)) end ngx.say(string.len(s)) - '; + } } --- request GET /base64 @@ -184,13 +184,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 200 do s = ngx.encode_base64(3.14, true) end ngx.say(s) - '; + } } --- request GET /base64 @@ -204,17 +204,17 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ -=== TEST 8: set base64 (number) with padding (explictly specified) +=== TEST 8: set base64 (number) with padding (explicitly specified) --- http_config eval: $::HttpConfig --- config location = /base64 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 200 do s = ngx.encode_base64(3.14, false) end ngx.say(s) - '; + } } --- request GET /base64 @@ -225,4 +225,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] -- NYI: - diff --git a/t/errlog.t b/t/errlog.t new file mode 100644 index 000000000..a2857dd13 --- /dev/null +++ b/t/errlog.t @@ -0,0 +1,1244 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +#master_process_enabled(1); +log_level('error'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 2 + 15); + +my $pwd = cwd(); + +add_block_preprocessor(sub { + my $block = shift; + + my $http_config = $block->http_config || ''; + my $init_by_lua_block = $block->init_by_lua_block || 'require "resty.core"'; + + $http_config .= <<_EOC_; + + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + $init_by_lua_block + } +_EOC_ + + $block->set_value("http_config", $http_config); +}); + +#no_diff(); +no_long_string(); +#check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + ngx.log(ngx.ERR, "enter 1") + ngx.log(ngx.ERR, "enter 11") + + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body +log lines:2 +--- grep_error_log eval +qr/enter \d+/ +--- grep_error_log_out eval +[ +"enter 1 +enter 11 +", +"enter 1 +enter 11 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 2: overflow captured error logs +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + ngx.log(ngx.ERR, "enter 1") + ngx.log(ngx.ERR, "enter 22" .. string.rep("a", 4096)) + + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body +log lines:1 +--- grep_error_log eval +qr/enter \d+/ +--- grep_error_log_out eval +[ +"enter 1 +enter 22 +", +"enter 1 +enter 22 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 3: 404 error (not found) +--- http_config + lua_capture_error_log 4m; +--- config + log_by_lua_block { + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.log(ngx.ERR, "capture log line:", #res / 3) + } +--- request +GET /t +--- error_code: 404 +--- grep_error_log eval +qr/capture log line:\d+|No such file or directory/ +--- grep_error_log_out eval +[ +qr/^No such file or directory +capture log line:1 +$/, +qr/^No such file or directory +capture log line:2 +$/ +] +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 4: 500 error +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + content_by_lua_block { + local t = {}/4 + } + } + log_by_lua_block { + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.log(ngx.ERR, "capture log line:", #res / 3) + } +--- request +GET /t +--- error_code: 500 +--- grep_error_log eval +qr/capture log line:\d+|attempt to perform arithmetic on a table value/ +--- grep_error_log_out eval +[ +qr/^attempt to perform arithmetic on a table value +capture log line:1 +$/, +qr/^attempt to perform arithmetic on a table value +capture log line:2 +$/ +] +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 5: no error log +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + echo "hello"; + } + log_by_lua_block { + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.log(ngx.ERR, "capture log line:", #res / 3) + } +--- request +GET /t +--- response_body +hello +--- grep_error_log eval +qr/capture log line:\d+/ +--- grep_error_log_out eval +[ +qr/^capture log line:0 +$/, +qr/^capture log line:1 +$/ +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 6: customize the log path +--- http_config + lua_capture_error_log 4m; + error_log logs/error_http.log error; +--- config + location /t { + error_log logs/error.log error; + access_by_lua_block { + ngx.log(ngx.ERR, "enter access /t") + } + echo "hello"; + } + log_by_lua_block { + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.log(ngx.ERR, "capture log line:", #res / 3) + + } +--- request +GET /t +--- response_body +hello +--- grep_error_log eval +qr/capture log line:\d+|enter access/ +--- grep_error_log_out eval +[ +qr/^enter access +capture log line:1 +$/, +qr/^enter access +capture log line:2 +$/ +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 7: invalid size (< 4k) +--- http_config + lua_capture_error_log 3k; +--- config + location /t { + echo "hello"; + } +--- must_die +--- error_log +invalid capture error log size "3k", minimum size is 4096 +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 8: invalid size (no argu) +--- http_config + lua_capture_error_log; +--- config + location /t { + echo "hello"; + } +--- must_die +--- error_log +invalid number of arguments in "lua_capture_error_log" directive +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 9: without directive + ngx.errlog +--- config + location /t { + access_by_lua_block { + ngx.log(ngx.ERR, "enter 1") + + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs() + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +directive "lua_capture_error_log" is not set +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 10: without directive + ngx.set_filter_level +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.ERR) + if not status then + error(err) + end + } + } +--- request +GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +directive "lua_capture_error_log" is not set +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 11: filter log by level(ngx.INFO) +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.INFO) + if not status then + error(err) + end + + ngx.log(ngx.INFO, "-->1") + ngx.log(ngx.WARN, "-->2") + ngx.log(ngx.ERR, "-->3") + } + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs() + ngx.say("log lines:", #res / 3) + } + } +--- log_level: info +--- request +GET /t +--- response_body +log lines:3 +--- grep_error_log eval +qr/-->\d+/ +--- grep_error_log_out eval +[ +"-->1 +-->2 +-->3 +", +"-->1 +-->2 +-->3 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 12: filter log by level(ngx.WARN) +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + ngx.log(ngx.INFO, "-->1") + ngx.log(ngx.WARN, "-->2") + ngx.log(ngx.ERR, "-->3") + } + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs() + ngx.say("log lines:", #res / 3) + } + } +--- log_level: info +--- request +GET /t +--- response_body +log lines:2 +--- grep_error_log eval +qr/-->\d+/ +--- grep_error_log_out eval +[ +"-->1 +-->2 +-->3 +", +"-->1 +-->2 +-->3 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 13: filter log by level(ngx.CRIT) +--- http_config + lua_capture_error_log 4m; +--- log_level: info +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.CRIT) + if not status then + error(err) + end + + ngx.log(ngx.INFO, "-->1") + ngx.log(ngx.WARN, "-->2") + ngx.log(ngx.ERR, "-->3") + } + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs() + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body +log lines:0 +--- grep_error_log eval +qr/-->\d+/ +--- grep_error_log_out eval +[ +"-->1 +-->2 +-->3 +", +"-->1 +-->2 +-->3 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 14: set max count and reuse table +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + tab_clear = require "table.clear" + ngx.log(ngx.ERR, "enter 1") + ngx.log(ngx.ERR, "enter 22") + ngx.log(ngx.ERR, "enter 333") + + local errlog = require "ngx.errlog" + local res = {} + local err + res, err = errlog.get_logs(2, res) + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + + tab_clear(res) + res, err = errlog.get_logs(2, res) + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body +log lines:2 +log lines:1 +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 15: wrong argument +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level() + if not status then + error(err) + end + } + } +--- request +GET /t +--- error_code: 500 +--- response_body_like: 500 +--- grep_error_log eval +qr/missing \"level\" argument/ +--- grep_error_log_out eval +[ +"missing \"level\" argument +", +"missing \"level\" argument +", +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 16: check the captured error log body +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + ngx.log(ngx.INFO, "-->1") + ngx.log(ngx.WARN, "-->2") + ngx.log(ngx.ERR, "-->3") + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs() + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: -->2, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: -->3, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +--- grep_error_log eval +qr/-->\d+/ +--- grep_error_log_out eval +[ +"-->1 +-->2 +-->3 +", +"-->1 +-->2 +-->3 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 17: flood the capturing buffer (4k) +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + for i = 1, 100 do + ngx.log(ngx.INFO, "--> ", i) + ngx.log(ngx.WARN, "--> ", i) + ngx.log(ngx.ERR, "--> ", i) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs(1000) + ngx.say("log lines: #", #res / 3) + + -- first 3 logs + for i = 1, 3 * 3, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + -- last 3 logs + for i = #res - 8, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Alog lines: #21 +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 90, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 91, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 99, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 100, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 100, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +\z +--- skip_nginx: 2: <1.11.2 +--- wait: 0.1 + + + +=== TEST 18: flood the capturing buffer (5k) +--- http_config + lua_capture_error_log 5k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + for i = 1, 100 do + ngx.log(ngx.INFO, "--> ", i) + ngx.log(ngx.WARN, "--> ", i) + ngx.log(ngx.ERR, "--> ", i) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs(1000) + ngx.say("log lines: #", #res / 3) + + -- first 3 logs + for i = 1, 3 * 3, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + -- last 3 logs + for i = #res - 8, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Alog lines: #26 +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 89, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 99, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 100, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> 100, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +\z +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 19: fetch a few and generate a few, then fetch again (overflown again) +--- http_config + lua_capture_error_log 5k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + for i = 1, 100 do + ngx.log(ngx.INFO, "--> ", i) + ngx.log(ngx.WARN, "--> ", i) + ngx.log(ngx.ERR, "--> ", i) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + + local res = errlog.get_logs(3) + ngx.say("msg count: ", #res / 3) + + -- first 3 logs + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + ngx.log(ngx.ERR, "--> 101") + ngx.log(ngx.ERR, "--> 102") + ngx.log(ngx.ERR, "--> 103") + ngx.log(ngx.ERR, "--> 104") + + local res = errlog.get_logs(3) + ngx.say("msg count: ", #res / 3) + + -- first 3 logs + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + local res = errlog.get_logs(1000) + -- last 3 logs + for i = #res - 8, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Amsg count: 3 +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 89, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +msg count: 3 +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 90, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 90, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 91, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: --> 102, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: --> 103, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: --> 104, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +\z +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 20: fetch a few and generate a few, then fetch again (not overflown again) +--- http_config + lua_capture_error_log 5k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + for i = 1, 100 do + ngx.log(ngx.INFO, "--> ", i) + ngx.log(ngx.WARN, "--> ", i) + ngx.log(ngx.ERR, "--> ", i) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + + local res = errlog.get_logs(3) + ngx.say("msg count: ", #res / 3) + + -- first 3 logs + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + ngx.log(ngx.ERR, "howdy, something new!") + ngx.log(ngx.ERR, "howdy, something even newer!") + + local res = errlog.get_logs(3) + ngx.say("msg count: ", #res / 3) + + -- first 3 logs + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + + local res = errlog.get_logs(1000) + -- last 3 logs + for i = #res - 8, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Amsg count: 3 +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 88, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 89, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +msg count: 3 +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 89, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:5 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[warn\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 90, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 90, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: --> 100, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: howdy, something new!, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: howdy, something even newer!, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +\z +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 21: multi-line error log +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + ngx.log(ngx.ERR, "-->\n", "new line") + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local res = errlog.get_logs() + ngx.say("log lines: #", #res / 3) + + for i = 1, #res, 3 do + ngx.say("log level:", res[i]) + ngx.say("log body:", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Alog lines: #1 +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> +new line, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +\z +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 22: user-supplied Lua table to hold the result (get one log + no log) +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local status, err = errlog.set_filter_level(ngx.WARN) + if not status then + error(err) + end + + ngx.log(ngx.ERR, "-->\n", "new line") + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local t = {} + + for i = 1, 2 do + local res = errlog.get_logs(10, t) + ngx.say("maybe log lines: #", #res / 3) + for j = 1, #res, 3 do + local level, msg = res[j], res[j + 2] + if not level then + break + end + ngx.say("log level:", level) + ngx.say("log body:", msg) + end + ngx.say("end") + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +\Amaybe log lines: #1 +log level:4 +log body:\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*access_by_lua\(nginx.conf:\d+\):\d+: --> +new line, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +end +maybe log lines: #1 +end +\z +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 23: the system default filter level is "debug" +--- config + location /t { + content_by_lua_block { + local errlog = require "ngx.errlog" + ngx.print('Is "debug" the system default filter level? ', + errlog.get_sys_filter_level() == ngx.DEBUG) + } + } +--- log_level: debug +--- request +GET /t +--- response_body chomp +Is "debug" the system default filter level? true + + + +=== TEST 24: the system default filter level is "emerg" +--- config + location /t { + content_by_lua_block { + local errlog = require "ngx.errlog" + ngx.print('Is "emerg" the system default filter level? ', + errlog.get_sys_filter_level() == ngx.EMERG) + } + } +--- log_level: emerg +--- request +GET /t +--- response_body chomp +Is "emerg" the system default filter level? true + + + +=== TEST 25: get system default filter level during Nginx starts (init) +--- init_by_lua_block + require "resty.core" + local errlog = require "ngx.errlog" + package.loaded.log_level = errlog.get_sys_filter_level() + +--- config + location /t { + content_by_lua_block { + local log_level = package.loaded.log_level + + if log_level >= ngx.WARN then + ngx.log(ngx.WARN, "log a warning event") + else + ngx.log(ngx.WARN, "do not log another warning event") + end + } + } +--- log_level: warn +--- request +GET /t +--- error_log +log a warning event +--- no_error_log +do not log another warning event + + + +=== TEST 26: get system default filter level during Nginx worker starts (init worker) +--- http_config + init_worker_by_lua_block { + local errlog = require "ngx.errlog" + package.loaded.log_level = errlog.get_sys_filter_level() + } +--- config + location /t { + content_by_lua_block { + local log_level = package.loaded.log_level + + if log_level >= ngx.WARN then + ngx.log(ngx.WARN, "log a warning event") + else + ngx.log(ngx.WARN, "do not log another warning event") + end + } + } +--- log_level: warn +--- request +GET /t +--- error_log +log a warning event +--- no_error_log +do not log another warning event + + + +=== TEST 27: sanity (with log time) +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + ngx.log(ngx.ERR, "enter 1") + ngx.log(ngx.ERR, "enter 11") + + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs(nil, nil, {fetch_time = true}) + if not res then + error("FAILED " .. err) + end + ngx.say("log lines:", #res / 3) + } + } +--- request +GET /t +--- response_body +log lines:2 +--- grep_error_log eval +qr/enter \d+/ +--- grep_error_log_out eval +[ +"enter 1 +enter 11 +", +"enter 1 +enter 11 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 28: log time eq ngx.now +--- http_config + lua_capture_error_log 4m; +--- config + location /t { + access_by_lua_block { + local now = ngx.now() + ngx.log(ngx.CRIT, "enter 1") + ngx.log(ngx.ERR, "enter 11") + + local errlog = require "ngx.errlog" + local res, err = errlog.get_logs(nil, nil, {fetch_time = true}) + if not res then + error("FAILED " .. err) + end + ngx.say("log lines: ", #res / 3) + + for i = 1, #res, 3 do + ngx.say("log level: ", res[i]) + ngx.say("log time: ", res[i + 1]) + ngx.say("log body: ", res[i + 2]) + ngx.say("same with now: ", res[i + 1] == now) + end + } + } +--- request +GET /t +--- response_body_like chomp +\Alog lines: 2 +log level: 3 +log time: \d+(?:\.\d+)? +log body: \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[crit\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: enter 1, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +same with now: true +log level: 4 +log time: \d{10}(?:\.\d+)? +log body: \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?access_by_lua\(nginx.conf:\d+\):\d+: enter 11, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +same with now: true +--- grep_error_log eval +qr/enter \d+/ +--- grep_error_log_out eval +[ +"enter 1 +enter 11 +", +"enter 1 +enter 11 +" +] +--- skip_nginx: 3: <1.11.2 + + + +=== TEST 29: ringbuf overflow bug +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local msg = string.rep("*", 10) + + for i = 1, 2 do + ngx.log(ngx.ERR, msg .. i) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local msg = string.rep("*", 10) + + for i = 1, 40 do + local res = errlog.get_logs(1) + if res and #res then + ngx.log(ngx.ERR, msg .. i) + end + end + + local res = errlog.get_logs() + for i = 1, #res, 3 do + ngx.say("log level: ", res[i]) + ngx.say("log time: ", res[i + 1]) + ngx.say("log body: ", res[i + 2]) + end + } + } +--- log_level: info +--- request +GET /t +--- response_body_like chomp +log level: 4 +log time: \d+(?:\.\d+)? +log body: \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: \*\*\*\*\*\*\*\*\*\*39, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +log level: 4 +log time: \d{10}(?:\.\d+)? +log body: \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \[error\] (\d+).*?content_by_lua\(nginx.conf:\d+\):\d+: \*\*\*\*\*\*\*\*\*\*40, client: 127.0.0.1, server: localhost, request: "GET /t HTTP/1.1", host: "localhost" +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 30: ringbuf sentinel bug1 +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local msg = string.rep("a", 20) + local bigmsg = string.rep("A", 3000) + + for i = 1, 10 do + ngx.log(ngx.ERR, msg) + end + ngx.log(ngx.ERR, bigmsg) + ngx.log(ngx.ERR, msg) + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + + local res = errlog.get_logs(2) + ngx.say("log lines: #", #res / 3) + + for i = 1, #res, 3 do + ngx.say(string.gsub(res[i + 2], "^.*([Aa][Aa][Aa]).*$", "%1"), "") + end + } + } +--- log_level: info +--- request +GET /t +--- response_body +log lines: #2 +AAA +aaa +--- skip_nginx: 2: <1.11.2 + + + +=== TEST 31: ringbuf sentinel bug2 +--- http_config + lua_capture_error_log 4k; +--- config + location /t { + access_by_lua_block { + local errlog = require "ngx.errlog" + local msg = string.rep("a", 20) + + for i = 1, 20 do + ngx.log(ngx.ERR, msg) + end + } + + content_by_lua_block { + local errlog = require "ngx.errlog" + local msg = string.rep("a", 20) + + local res = errlog.get_logs(18) + ngx.say("log lines: #", #res / 3) + ngx.flush(true) + + for i = 1, 18 do + ngx.log(ngx.ERR, msg) + end + + local bigmsg = string.rep("A", 2000) + ngx.log(ngx.ERR, bigmsg) + + local res = errlog.get_logs() + ngx.say("log lines: #", #res / 3) + ngx.flush(true) + } + } +--- log_level: info +--- request +GET /t +--- response_body +log lines: #18 +log lines: #8 +--- skip_nginx: 2: <1.11.2 diff --git a/t/exit.t b/t/exit.t index 86cebb91d..c4ad4a778 100644 --- a/t/exit.t +++ b/t/exit.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;\$prefix/html/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,9 +41,9 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { ngx.exit(403) - '; + } } --- request GET /t @@ -60,10 +60,10 @@ qr/ -- NYI: (?!FastFunc coroutine.yield)/, --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local foo = require "foo" foo.go() - '; + } } --- user_files >>> foo.lua @@ -83,4 +83,3 @@ GET /t ["[error]", qr/ -- NYI: (?!FastFunc coroutine.yield)/, " bad argument"] - diff --git a/t/md5.t b/t/md5.t index 73a5f16a3..3f88b14fc 100644 --- a/t/md5.t +++ b/t/md5.t @@ -15,11 +15,11 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local v = require "jit.v" v.on("$Test::Nginx::Util::ErrLogFile") require "resty.core" - '; + } _EOC_ #no_diff(); @@ -33,13 +33,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /md5 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5("hello") end ngx.say(s) - '; + } } --- request GET /md5 @@ -56,13 +56,13 @@ qr/\[TRACE 1 content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /md5 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5(nil) end ngx.say(s) - '; + } } --- request GET /md5 @@ -79,13 +79,13 @@ qr/\[TRACE 1 content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location /md5 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5("") end ngx.say(s) - '; + } } --- request GET /md5 @@ -102,13 +102,13 @@ qr/\[TRACE 1 content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location /md5 { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5(3.14) end ngx.say(s) - '; + } } --- request GET /md5 @@ -118,4 +118,3 @@ GET /md5 qr/\[TRACE 1 content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] - diff --git a/t/md5_bin.t b/t/md5_bin.t index decc7e7dd..cc29fd0e9 100644 --- a/t/md5_bin.t +++ b/t/md5_bin.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -27,7 +27,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,13 +41,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /md5_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5_bin("hello") end ngx.say(string.len(s)) - '; + } } --- request GET /md5_bin @@ -64,13 +64,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /md5_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5_bin(nil) end ngx.say(string.len(s)) - '; + } } --- request GET /md5_bin @@ -87,13 +87,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /md5_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5_bin(3.14) end ngx.say(string.len(s)) - '; + } } --- request GET /md5_bin @@ -110,13 +110,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /md5_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.md5_bin(true) end ngx.say(string.len(s)) - '; + } } --- request GET /md5_bin @@ -126,4 +126,3 @@ GET /md5_bin qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] - diff --git a/t/misc.t b/t/misc.t index 213731e01..5f102ca55 100644 --- a/t/misc.t +++ b/t/misc.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;\$prefix/html/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,13 +43,13 @@ __DATA__ --- config location = /t { return 201; - header_filter_by_lua ' + header_filter_by_lua_block { local rc for i = 1, 100 do rc = ngx.is_subrequest end ngx.log(ngx.WARN, "is subrequest: ", rc) - '; + } } --- request GET /t @@ -70,13 +70,13 @@ qr/\[TRACE\s+\d+\s+header_filter_by_lua:3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local rc for i = 1, 100 do rc = ngx.headers_sent end ngx.say("headers sent: ", rc) - '; + } } --- request GET /t @@ -95,14 +95,14 @@ qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { ngx.send_headers() local rc for i = 1, 100 do rc = ngx.headers_sent end ngx.say("headers sent: ", rc) - '; + } } --- request GET /t @@ -114,4 +114,3 @@ headers sent: true bad argument --- error_log eval qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):4 loop\]/ - diff --git a/t/process-type-cache.t b/t/process-type-cache.t new file mode 100644 index 000000000..b49c3944c --- /dev/null +++ b/t/process-type-cache.t @@ -0,0 +1,102 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +BEGIN { + undef $ENV{TEST_NGINX_USE_STAP}; +} + +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +master_on(); +#log_level('info'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 5); + +my $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + proxy_cache_path /tmp/proxy_cache_dir keys_zone=cache_one:200m; + + lua_shared_dict dogs 1m; + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + local verbose = false + if verbose then + local dump = require "jit.dump" + dump.on("b", "$Test::Nginx::Util::ErrLogFile") + else + local v = require "jit.v" + v.on("$Test::Nginx::Util::ErrLogFile") + end + + require "resty.core" + -- jit.off() + } + + init_worker_by_lua_block { + local base = require "resty.core.base" + local v + local typ = (require "ngx.process").type + for i = 1, 400 do + v = typ() + end + + if v == "helper" then + ngx.log(ngx.WARN, "process type: ", v) + end + } +_EOC_ + +#no_diff(); +#no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + ngx.sleep(0.1) + local v + local typ = (require "ngx.process").type + for i = 1, 200 do + v = typ() + end + ngx.say("type: ", v) + } + } +--- request +GET /t +--- response_body +type: worker +--- grep_error_log eval +qr/\[TRACE \d+ init_worker_by_lua:\d loop\]|\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):\d loop\]|process type: \w+/ +--- grep_error_log_out eval +[ +qr/\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d content_by_lua\(nginx.conf:78\):5 loop\] +process type: helper +process type: helper +/, +qr/\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d init_worker_by_lua:5 loop\] +\[TRACE \d content_by_lua\(nginx.conf:78\):5 loop\] +process type: helper +process type: helper +/ +] +--- no_error_log +[error] + -- NYI: +--- skip_nginx: 5: < 1.11.2 +--- wait: 0.2 diff --git a/t/process-type-hup.t b/t/process-type-hup.t new file mode 100644 index 000000000..f023b6c8a --- /dev/null +++ b/t/process-type-hup.t @@ -0,0 +1,88 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +our $SkipReason; + +BEGIN { + if ($ENV{TEST_NGINX_CHECK_LEAK}) { + $SkipReason = "unavailable for the hup tests"; + + } else { + $ENV{TEST_NGINX_USE_HUP} = 1; + undef $ENV{TEST_NGINX_USE_STAP}; + } +} + +use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); +use Cwd qw(cwd); + +#worker_connections(1014); +master_process_enabled(1); +log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 4); + +my $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + require "resty.core" + local process = require "ngx.process" + local ok, err = process.enable_privileged_agent() + if not ok then + ngx.log(ngx.ERR, "enable_privileged_agent failed: ", err) + end + } + + init_worker_by_lua_block { + local base = require "resty.core.base" + local typ = require "ngx.process".type + + if typ() == "privileged agent" then + ngx.log(ngx.WARN, "process type: ", typ()) + end + } +_EOC_ + +#no_diff(); +no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + local typ = require "ngx.process".type + + local f, err = io.open(ngx.config.prefix() .. "/logs/nginx.pid", "r") + if not f then + ngx.say("failed to open nginx.pid: ", err) + return + end + + local pid = f:read() + -- ngx.say("master pid: [", pid, "]") + + f:close() + + ngx.say("type: ", typ()) + os.execute("kill -HUP " .. pid) + } + } +--- request +GET /t +--- response_body +type: worker +--- error_log +init_worker_by_lua:6: process type: privileged +--- no_error_log +[error] +--- skip_nginx: 4: < 1.11.2 +--- wait: 0.1 diff --git a/t/process-type-master.t b/t/process-type-master.t new file mode 100644 index 000000000..8ae6070fe --- /dev/null +++ b/t/process-type-master.t @@ -0,0 +1,90 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +BEGIN { + undef $ENV{TEST_NGINX_USE_STAP}; +} + +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +master_process_enabled(1); +#log_level('error'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 5); + +my $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + lua_shared_dict dogs 1m; + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + local verbose = false + if verbose then + local dump = require "jit.dump" + dump.on("b", "$Test::Nginx::Util::ErrLogFile") + else + local v = require "jit.v" + v.on("$Test::Nginx::Util::ErrLogFile") + end + + require "resty.core" + -- jit.off() + } + + init_worker_by_lua_block { + local v + local typ = (require "ngx.process").type + for i = 1, 400 do + v = typ() + end + + ngx.log(ngx.WARN, "process type: ", v) + } +_EOC_ + +#no_diff(); +#no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + local v + local typ = (require "ngx.process").type + for i = 1, 400 do + v = typ() + end + + ngx.say("process type: ", v) + } + } +--- request +GET /t +--- response_body +process type: worker +--- grep_error_log eval +qr/\[TRACE \d+ init_worker_by_lua:4 loop\]|\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]|init_worker_by_lua:\d: process type: \w+/ +--- grep_error_log_out eval +[ +qr/\[TRACE 1 init_worker_by_lua:4 loop\] +\[TRACE 2 content_by_lua\(nginx.conf:73\):4 loop\] +init_worker_by_lua:8: process type: worker +/, +qr/\[TRACE 1 init_worker_by_lua:4 loop\] +\[TRACE 2 content_by_lua\(nginx.conf:73\):4 loop\] +init_worker_by_lua:8: process type: worker +/ +] +--- no_error_log +[error] + -- NYI: +--- skip_nginx: 5: < 1.11.2 diff --git a/t/process-type-privileged-agent.t b/t/process-type-privileged-agent.t new file mode 100644 index 000000000..0be6b62c7 --- /dev/null +++ b/t/process-type-privileged-agent.t @@ -0,0 +1,146 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +BEGIN { + undef $ENV{TEST_NGINX_USE_STAP}; +} + +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +master_process_enabled(1); +#log_level('error'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 5 - 3); + +my $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + local verbose = false + if verbose then + local dump = require "jit.dump" + dump.on("b", "$Test::Nginx::Util::ErrLogFile") + else + local v = require "jit.v" + v.on("$Test::Nginx::Util::ErrLogFile") + end + + require "resty.core" + local process = require "ngx.process" + local ok, err = process.enable_privileged_agent() + if not ok then + ngx.log(ngx.ERR, "enable_privileged_agent failed: ", err) + end + } + + init_worker_by_lua_block { + local base = require "resty.core.base" + local v + local typ = (require "ngx.process").type + for i = 1, 400 do + v = typ() + end + + if v == "privileged agent" then + ngx.log(ngx.WARN, "process type: ", v) + end + } +_EOC_ + +#no_diff(); +#no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + ngx.sleep(0.1) + local v + local typ = require "ngx.process".type + for i = 1, 200 do + v = typ() + end + + ngx.say("type: ", v) + } + } +--- request +GET /t +--- response_body +type: worker +--- grep_error_log eval +qr/\[TRACE \d+ init_worker_by_lua:\d+ loop\]|\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):\d+ loop\]|init_worker_by_lua:\d+: process type: \w+/ +--- grep_error_log_out eval +[ +qr/\[TRACE \d init_worker_by_lua:5 loop\] +(?:\[TRACE \d init_worker_by_lua:5 loop\] +)?\[TRACE \d content_by_lua\(nginx.conf:81\):5 loop\] +init_worker_by_lua:10: process type: privileged +/, +qr/\[TRACE \d init_worker_by_lua:5 loop\] +(?:\[TRACE \d init_worker_by_lua:5 loop\] +)?\[TRACE \d content_by_lua\(nginx.conf:81\):5 loop\] +init_worker_by_lua:10: process type: privileged +/ +] +--- no_error_log +[error] + -- NYI: +--- skip_nginx: 5: < 1.11.2 +--- wait: 0.2 + + + +=== TEST 2: `enable_privileged_agent` disabled +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + local process = require "ngx.process" + local ok, err = process.enable_privileged_agent() + if not ok then + error(err) + end + } + } +--- request +GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log eval +qr/\[error\] .*? API disabled in the current context/ +--- skip_nginx: 3: < 1.11.2 + + + +=== TEST 3: `enable_privileged_agent` not patched +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + local process = require "ngx.process" + local ok, err = process.enable_privileged_agent() + if not ok then + error(err) + end + } + } +--- request +GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +missing privileged agent process patch in the nginx core +API disabled in the current context +--- skip_nginx: 4: >= 1.11.2 diff --git a/t/re-find.t b/t/re-find.t index 3b2c889bb..772ec3b6d 100644 --- a/t/re-find.t +++ b/t/re-find.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { -- local verbose = true local verbose = false local outfile = "$Test::Nginx::Util::ErrLogFile" @@ -32,7 +32,7 @@ our $HttpConfig = <<_EOC_; -- jit.opt.start("hotloop=1") -- jit.opt.start("loopunroll=1000000") -- jit.off() - '; + } _EOC_ #no_diff(); @@ -47,7 +47,7 @@ __DATA__ --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local from, to, err local find = ngx.re.find local s = "a" @@ -65,7 +65,7 @@ __DATA__ ngx.say("from: ", from) ngx.say("to: ", to) ngx.say("matched: ", string.sub(s, from, to)) - '; + } } --- request GET /re @@ -86,7 +86,7 @@ bad argument type --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local from, to, err local find = ngx.re.find local s = "a" @@ -104,7 +104,7 @@ bad argument type ngx.say("from: ", from) ngx.say("to: ", to) ngx.say("matched: ", string.sub(s, from, to)) - '; + } } --- request GET /re @@ -125,7 +125,7 @@ NYI --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local from, to, err local find = ngx.re.find local s = "b" @@ -143,7 +143,7 @@ NYI ngx.say("from: ", from) ngx.say("to: ", to) ngx.say("matched: ", string.sub(s, from, to)) - '; + } } --- request GET /re @@ -161,7 +161,7 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local s = "hello, 1234" local from, to, err for i = 1, 100 do @@ -178,7 +178,7 @@ NYI end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -196,7 +196,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local s = "hello, 1234" local from, to, err for i = 1, 400 do @@ -213,7 +213,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -231,7 +231,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local s = "hello, 1234" local from, to, err for i = 1, 100 do @@ -247,7 +247,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -260,4 +260,3 @@ matched: 234 NYI --- error_log eval qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ - diff --git a/t/re-match.t b/t/re-match.t index 02a856c80..84e7e0def 100644 --- a/t/re-match.t +++ b/t/re-match.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { -- local verbose = true local verbose = false local outfile = "$Test::Nginx::Util::ErrLogFile" @@ -32,7 +32,7 @@ our $HttpConfig = <<_EOC_; -- jit.opt.start("hotloop=1") -- jit.opt.start("loopunroll=1000000") -- jit.off() - '; + } _EOC_ #no_diff(); @@ -47,7 +47,7 @@ __DATA__ --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 400 do @@ -66,7 +66,7 @@ __DATA__ -- ngx.say("$2: ", m[2]) -- ngx.say("$3: ", m[3]) -- collectgarbage() - '; + } } --- request GET /re @@ -86,7 +86,7 @@ bad argument type --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 400 do @@ -103,7 +103,7 @@ bad argument type ngx.say("matched: ", m[0]) ngx.say("$1: ", m[1]) -- collectgarbage() - '; + } } --- request GET /re @@ -123,7 +123,7 @@ NYI --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 200 do @@ -140,7 +140,7 @@ NYI ngx.say("matched: ", m[0]) ngx.say("$1: ", m[1]) -- collectgarbage() - '; + } } --- request GET /re @@ -158,7 +158,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 100 do @@ -175,7 +175,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ ngx.say("matched: ", m[0]) ngx.say("$1: ", m[1]) -- collectgarbage() - '; + } } --- request GET /re @@ -194,11 +194,11 @@ bad argument type --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 100 do - m, err = match("hello, 1234", [[(\\d)(\\d+)]]) + m, err = match("hello, 1234", [[(\d)(\d+)]]) end if err then ngx.log(ngx.ERR, "failed: ", err) @@ -213,7 +213,7 @@ bad argument type ngx.say("$2: ", m[2]) ngx.say("$3: ", m[3]) -- collectgarbage() - '; + } } --- request GET /re @@ -234,11 +234,11 @@ NYI --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 100 do - m, err = match("hello, 1234", [[(\\d)(\\d+)]], "jo") + m, err = match("hello, 1234", [[(\d)(\d+)]], "jo") end if err then ngx.log(ngx.ERR, "failed: ", err) @@ -254,7 +254,7 @@ NYI ngx.say("$3: ", m[3]) -- ngx.say(table.maxn(m)) -- collectgarbage() - '; + } } --- request GET /re @@ -276,7 +276,7 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 100 do @@ -294,7 +294,7 @@ NYI end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -317,7 +317,7 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 200 do @@ -335,7 +335,7 @@ NYI end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -355,7 +355,7 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m, err local match = ngx.re.match for i = 1, 100 do @@ -378,7 +378,7 @@ NYI end ngx.say("not matched!") end - '; + } } --- request GET /re @@ -402,7 +402,7 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local new_tab = require "table.new" local clear_tab = require "table.clear" local m @@ -422,7 +422,7 @@ NYI else ngx.say("not matched!") end - '; + } } --- request GET /re @@ -445,7 +445,7 @@ qr/\[TRACE\s+\d+\s+/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m = ngx.re.match("hello!", "(hello)(, .+)?(!)", "jo") if m then @@ -456,7 +456,7 @@ qr/\[TRACE\s+\d+\s+/ else ngx.say("not matched!") end - '; + } } --- request GET /re @@ -477,7 +477,7 @@ qr/\[TRACE\s+\d+\s+/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m = ngx.re.match("hello", "(hello)(, .+)?(!)?", "jo") if m then @@ -488,7 +488,7 @@ qr/\[TRACE\s+\d+\s+/ else ngx.say("not matched!") end - '; + } } --- request GET /re @@ -509,7 +509,7 @@ qr/\[TRACE\s+\d+\s+/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m = ngx.re.match("hello!", "(?hello)(?, .+)?(?!)", "jo") if m then @@ -523,7 +523,7 @@ qr/\[TRACE\s+\d+\s+/ else ngx.say("not matched!") end - '; + } } --- request GET /re @@ -547,8 +547,8 @@ qr/\[TRACE\s+\d+\s+/ --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' - local m = ngx.re.match(12345, [=[(\\d+)]=], "jo") + content_by_lua_block { + local m = ngx.re.match(12345, [=[(\d+)]=], "jo") if m then ngx.say(m[0]) @@ -556,7 +556,7 @@ qr/\[TRACE\s+\d+\s+/ else ngx.say("not matched") end - '; + } } --- request GET /re @@ -573,7 +573,7 @@ attempt to get length of local 'subj' (a number value) --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local m = ngx.re.match(12345, "123", "jo") if m then @@ -581,7 +581,7 @@ attempt to get length of local 'subj' (a number value) else ngx.say("not matched") end - '; + } } --- request GET /re @@ -590,4 +590,3 @@ attempt to get length of local 'subj' (a number value) --- no_error_log [error] attempt to get length of local 'regex' (a number value) - diff --git a/t/re-opt.t b/t/re-opt.t new file mode 100644 index 000000000..18f66a307 --- /dev/null +++ b/t/re-opt.t @@ -0,0 +1,179 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +#master_process_enabled(1); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * blocks() * 3; + +our $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + -- local verbose = true + local verbose = false + local outfile = "$Test::Nginx::Util::ErrLogFile" + -- local outfile = "/tmp/v.log" + if verbose then + local dump = require "jit.dump" + dump.on(nil, outfile) + else + local v = require "jit.v" + v.on(outfile) + end + + require "resty.core" + -- jit.opt.start("hotloop=1") + -- jit.opt.start("loopunroll=1000000") + -- jit.off() + } +_EOC_ + +no_diff(); +no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: default jit_stack_size too small +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + -- regex is taken from https://github.com/JuliaLang/julia/issues/8278 + local very_long_string = [[71.163.72.113 - - [30/Jul/2014:16:40:55 -0700] "GET emptymind.org/thevacantwall/wp-content/uploads/2013/02/DSC_006421.jpg HTTP/1.1" 200 492513 "http://images.search.yahoo.com/images/view;_ylt=AwrB8py9gdlTGEwADcSjzbkF;_ylu=X3oDMTI2cGZrZTA5BHNlYwNmcC1leHAEc2xrA2V4cARvaWQDNTA3NTRiMzYzY2E5OTEwNjBiMjc2YWJhMjkxMTEzY2MEZ3BvcwM0BGl0A2Jpbmc-?back=http%3A%2F%2Fus.yhs4.search.yahoo.com%2Fyhs%2Fsearch%3Fei%3DUTF-8%26p%3Dapartheid%2Bwall%2Bin%2Bpalestine%26type%3Dgrvydef%26param1%3D1%26param2%3Dsid%253Db01676f9c26355f014f8a9db87545d61%2526b%253DChrome%2526ip%253D71.163.72.113%2526p%253Dgroovorio%2526x%253DAC811262A746D3CD%2526dt%253DS940%2526f%253D7%2526a%253Dgrv_tuto1_14_30%26hsimp%3Dyhs-fullyhosted_003%26hspart%3Dironsource&w=588&h=387&imgurl=occupiedpalestine.files.wordpress.com%2F2012%2F08%2F5-peeking-through-the-wall.jpg%3Fw%3D588%26h%3D387&rurl=http%3A%2F%2Fwww.stopdebezetting.com%2Fwereldpers%2Fcompare-the-berlin-wall-vs-israel-s-apartheid-wall-in-palestine.html&size=49.0KB&name=...+%3Cb%3EApartheid+wall+in+Palestine%3C%2Fb%3E...+%7C+Or+you+go+peeking+through+the+%3Cb%3Ewall%3C%2Fb%3E&p=apartheid+wall+in+palestine&oid=50754b363ca991060b276aba291113cc&fr2=&fr=&tt=...+%3Cb%3EApartheid+wall+in+Palestine%3C%2Fb%3E...+%7C+Or+you+go+peeking+through+the+%3Cb%3Ewall%3C%2Fb%3E&b=0&ni=21&no=4&ts=&tab=organic&sigr=13evdtqdq&sigb=19k7nsjvb&sigi=12o2la1db&sigt=12lia2m0j&sign=12lia2m0j&.crumb=.yUtKgFI6DE&hsimp=yhs-fullyhosted_003&hspart=ironsource" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36]] + local very_complicated_regex = [[([\d\.]+) ([\w.-]+) ([\w.-]+) (\[.+\]) "([^"\r\n]*|[^"\r\n\[]*\[.+\][^"]+|[^"\r\n]+.[^"]+)" (\d{3}) (\d+|-) ("(?:[^"]|\")+)"? ("(?:[^"]|\")+)"?]] + local from, to, err = ngx.re.find(very_long_string, very_complicated_regex, "jo") + if from or to then + ngx.say("from: ", from) + ngx.say("to: ", to) + else + if err then + ngx.say("error: ", err) + return + end + ngx.say("not matched!") + end + } + } +--- request + GET /re +--- response_body +error: pcre_exec() failed: -27 +--- no_error_log +[error] +--- timeout: 10 + + + +=== TEST 2: increase jit_stack_size +--- http_config eval +qq{ + lua_package_path "$::pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + -- local verbose = true + local verbose = false + local outfile = "$Test::Nginx::Util::ErrLogFile" + -- local outfile = "/tmp/v.log" + if verbose then + local dump = require "jit.dump" + dump.on(nil, outfile) + else + local v = require "jit.v" + v.on(outfile) + end + + require "resty.core" + -- jit.opt.start("hotloop=1") + -- jit.opt.start("loopunroll=1000000") + -- jit.off() + + local ngx_re = require "ngx.re" + ngx_re.opt("jit_stack_size", 128 * 1024) + } +} +--- config + location /re { + content_by_lua_block { + -- regex is taken from https://github.com/JuliaLang/julia/issues/8278 + local very_long_string = [[71.163.72.113 - - [30/Jul/2014:16:40:55 -0700] "GET emptymind.org/thevacantwall/wp-content/uploads/2013/02/DSC_006421.jpg HTTP/1.1" 200 492513 "http://images.search.yahoo.com/images/view;_ylt=AwrB8py9gdlTGEwADcSjzbkF;_ylu=X3oDMTI2cGZrZTA5BHNlYwNmcC1leHAEc2xrA2V4cARvaWQDNTA3NTRiMzYzY2E5OTEwNjBiMjc2YWJhMjkxMTEzY2MEZ3BvcwM0BGl0A2Jpbmc-?back=http%3A%2F%2Fus.yhs4.search.yahoo.com%2Fyhs%2Fsearch%3Fei%3DUTF-8%26p%3Dapartheid%2Bwall%2Bin%2Bpalestine%26type%3Dgrvydef%26param1%3D1%26param2%3Dsid%253Db01676f9c26355f014f8a9db87545d61%2526b%253DChrome%2526ip%253D71.163.72.113%2526p%253Dgroovorio%2526x%253DAC811262A746D3CD%2526dt%253DS940%2526f%253D7%2526a%253Dgrv_tuto1_14_30%26hsimp%3Dyhs-fullyhosted_003%26hspart%3Dironsource&w=588&h=387&imgurl=occupiedpalestine.files.wordpress.com%2F2012%2F08%2F5-peeking-through-the-wall.jpg%3Fw%3D588%26h%3D387&rurl=http%3A%2F%2Fwww.stopdebezetting.com%2Fwereldpers%2Fcompare-the-berlin-wall-vs-israel-s-apartheid-wall-in-palestine.html&size=49.0KB&name=...+%3Cb%3EApartheid+wall+in+Palestine%3C%2Fb%3E...+%7C+Or+you+go+peeking+through+the+%3Cb%3Ewall%3C%2Fb%3E&p=apartheid+wall+in+palestine&oid=50754b363ca991060b276aba291113cc&fr2=&fr=&tt=...+%3Cb%3EApartheid+wall+in+Palestine%3C%2Fb%3E...+%7C+Or+you+go+peeking+through+the+%3Cb%3Ewall%3C%2Fb%3E&b=0&ni=21&no=4&ts=&tab=organic&sigr=13evdtqdq&sigb=19k7nsjvb&sigi=12o2la1db&sigt=12lia2m0j&sign=12lia2m0j&.crumb=.yUtKgFI6DE&hsimp=yhs-fullyhosted_003&hspart=ironsource" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36]] + local very_complicated_regex = [[([\d\.]+) ([\w.-]+) ([\w.-]+) (\[.+\]) "([^"\r\n]*|[^"\r\n\[]*\[.+\][^"]+|[^"\r\n]+.[^"]+)" (\d{3}) (\d+|-) ("(?:[^"]|\")+)"? ("(?:[^"]|\")+)"?]] + local from, to, err = ngx.re.find(very_long_string, very_complicated_regex, "jo") + if from or to then + ngx.say("from: ", from) + ngx.say("to: ", to) + else + if err then + ngx.say("error: ", err) + return + end + ngx.say("not matched!") + end + } + } +--- request + GET /re +--- response_body +from: 1 +to: 1563 +--- no_error_log +[error] +--- timeout: 10 + + + +=== TEST 3: jit_stack_size change disallowed once regex cache is populated +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local status, err = pcall(ngx_re.opt, "jit_stack_size", 128 * 1024) + if err then ngx.log(ngx.ERR, err) end + local s = "hello, 1234" + local from, to = ngx.re.find(s, "(hello world)|([0-9])", "jo") + ngx.say("from: ", from) + ngx.say("to: ", to) + } + } +--- request + GET /re +--- response_body +from: 8 +to: 8 + +--- grep_error_log eval +qr/changing jit stack size is not allowed when some regexs have already been compiled and cached/ + +--- grep_error_log_out eval +["", "changing jit stack size is not allowed when some regexs have already been compiled and cached\n"] +--- timeout: 10 + + + +=== TEST 4: passing unknown options to ngx_re.opt throws an error +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local status, err = pcall(ngx_re.opt, "foo", 123) + ngx.say(err) + } + } +--- request + GET /re +--- response_body_like chomp +unrecognized option name$ +--- no_error_log +[error] +--- timeout: 10 diff --git a/t/re-split.t b/t/re-split.t new file mode 100644 index 000000000..0a9cd444c --- /dev/null +++ b/t/re-split.t @@ -0,0 +1,1183 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +#worker_connections(1014); +#master_process_enabled(1); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * blocks() * 4 + (2 * repeat_each()); + +my $pwd = cwd(); + +our $HttpConfig = <<_EOC_; + lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + init_by_lua_block { + -- local verbose = true + local verbose = false + local outfile = "$Test::Nginx::Util::ErrLogFile" + -- local outfile = "/tmp/v.log" + if verbose then + local dump = require "jit.dump" + dump.on(nil, outfile) + else + local v = require "jit.v" + v.on(outfile) + end + + require "resty.core" + -- jit.opt.start("hotloop=1") + -- jit.opt.start("loopunroll=1000000") + -- jit.off() + } +_EOC_ + +no_diff(); +no_long_string(); +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: split matches, no submatch, no jit compile, no regex cache +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d", ",") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 2: split matches, no submatch, no jit compile, no regex cache +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a;,b;,c;,d;e", ";,") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d;e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 3: split matches, no submatch, jit compile, regex cache +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d", ",", "jo") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 4: split matches + submatch (matching) +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a;,b;,c;,d,e", "(;),") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +; +b +; +c +; +d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 5: split matches + submatch (not matching) +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", "(;)|,") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 6: split matches + max limiter +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, 3) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 7: split matches + submatch + max limiter +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", "(,)", nil, nil, 3) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +, +b +, +c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 8: split matches + max limiter set to 0 +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, 0) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 9: split matches + max limiter set to a negative value +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, -1) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 10: split matches + max limiter set to 1 +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, 1) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a,b,c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 11: split matches, provided res table +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local my_table = {} + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, nil, my_table) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 12: split matches, provided res table (non-cleared) +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local my_table = {} + + for i = 1, 10 do + my_table[i] = i.." hello world" + end + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, nil, my_table) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i in ipairs(my_table) do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 13: split matches, provided res table + max limiter +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local my_table = {"hello, world"} + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, 3, my_table) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #my_table do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 14: split matches, provided res table (non-cleared) + max limiter +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local my_table = {} + + for i = 1, 10 do + my_table[i] = i.." hello world" + end + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, nil, 3, my_table) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i in ipairs(my_table) do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +b +c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 15: split matches, provided res table + max limiter + sub-match capturing group +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local my_table = {"hello, world"} + + local res, err = ngx_re.split("a,b,c,d,e", "(,)", nil, nil, 3, my_table) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #my_table do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +a +, +b +, +c,d,e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 16: split matches, ctx arg +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, { pos = 5 }) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +c +d +e +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 17: split matches, trailing subjects +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split(",a,b,c,d,", ",") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + if res[i] == "" then + ngx.say("_blank_") + else + ngx.say(res[i]) + end + end + } + } +--- request +GET /re +--- response_body +_blank_ +a +b +c +d +_blank_ +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] +attempt to get length of local 'regex' (a number value) + + + +=== TEST 18: split matches, real use-case +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("abcd,erfg,ghij;hello world;aaa", ",|;") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +abcd +erfg +ghij +hello world +aaa +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 19: split no matches +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("abcd", ",") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +abcd +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 20: subject is not a string type +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split(1234512345, "23", "jo") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + } + } +--- request +GET /re +--- response_body +1 +451 +45 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] +attempt to get length of local 'subj' (a number value) + + + +=== TEST 21: split matches, pos is larger than subject length +--- http_config eval: $::HttpConfig +--- config + location = /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("a,b,c,d,e", ",", nil, { pos = 10 }) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +len: 0 +--- no_error_log +[error] +[TRACE + + + +=== TEST 22: regex is "" +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("12345", "", "jo") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +1 +2 +3 +4 +5 +len: 5 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 23: regex is "" with max +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("12345", "", "jo", nil, 3) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +1 +2 +345 +len: 3 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 24: regex is "" with pos +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("12345", "", "jo", { pos = 2 }) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +2 +3 +4 +5 +len: 4 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 25: regex is "" with pos larger than subject length +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("12345", "", "jo", { pos = 10 }) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +len: 0 +--- no_error_log +[error] +[TRACE + + + +=== TEST 26: regex is "" with pos & max +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("12345", "", "jo", { pos = 2 }, 2) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + for i = 1, #res do + ngx.say(res[i]) + end + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +2 +345 +len: 2 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 27: no match separator (github issue #104) +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("abcd", "|") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +a:b:c:d +len: 4 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 28: no match separator (github issue #104) & max +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("abcd", "|", nil, nil, 2) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +a:bcd +len: 2 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 29: no match separator bis (github issue #104) +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("abcd", "()") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +a::b::c::d +len: 7 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 30: behavior with /^/ differs from Perl's split +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\ncd\nef", "^") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +cd +ef +len: 1 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 31: behavior with /^/m +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\ncd\nef", "^", "m") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +:cd +:ef +len: 3 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 32: behavior with /^()/m (capture) +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\ncd\nef", "^()", "m") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +::cd +::ef +len: 5 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 33: behavior with /^/m & max +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\ncd\nef", "^", "m", nil, 2) + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +:cd +ef +len: 2 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 34: behavior with /^\d/m +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\n1cdefg\n2hij", "^\\d", "m") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +:cdefg +:hij +len: 3 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] + + + +=== TEST 35: behavior with /^(\d)/m (capture) +--- http_config eval: $::HttpConfig +--- config + location /re { + content_by_lua_block { + local ngx_re = require "ngx.re" + + local res, err = ngx_re.split("ab\n1cdefg\n2hij", "^(\\d)", "m") + if err then + ngx.log(ngx.ERR, "failed: ", err) + return + end + + ngx.say(table.concat(res, ":")) + + ngx.say("len: ", #res) + } + } +--- request +GET /re +--- response_body +ab +:1:cdefg +:2:hij +len: 5 +--- error_log eval +qr/\[TRACE \d+/ +--- no_error_log +[error] diff --git a/t/re-sub.t b/t/re-sub.t index f8af6918a..d0d32da3c 100644 --- a/t/re-sub.t +++ b/t/re-sub.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { -- local verbose = true local verbose = false local outfile = "$Test::Nginx::Util::ErrLogFile" @@ -32,7 +32,7 @@ our $HttpConfig = <<_EOC_; -- jit.opt.start("hotloop=1") -- jit.opt.start("loopunroll=1000000") -- jit.off() - '; + } _EOC_ #no_diff(); @@ -47,7 +47,7 @@ __DATA__ --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local sub = ngx.re.sub for i = 1, 350 do @@ -59,7 +59,7 @@ __DATA__ end ngx.say("s: ", s) ngx.say("n: ", n) - '; + } } --- request GET /re @@ -80,7 +80,7 @@ NYI --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local sub = ngx.re.sub for i = 1, 400 do @@ -92,7 +92,7 @@ NYI end ngx.say("s: ", s) ngx.say("n: ", n) - '; + } } --- request GET /re @@ -112,7 +112,7 @@ bad argument type --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local function f(m) return "[" .. m[0] .. "(" .. m[1] .. ")]" @@ -127,7 +127,7 @@ bad argument type end ngx.say("s: ", s) ngx.say("n: ", n) - '; + } } --- request GET /re @@ -148,7 +148,7 @@ qr/NYI (?!bytecode 51 at)/, --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local sub = ngx.re.sub for i = 1, 350 do @@ -160,7 +160,7 @@ qr/NYI (?!bytecode 51 at)/, end ngx.say("s: ", s) ngx.say("n: ", n) - '; + } } --- request GET /re @@ -182,7 +182,7 @@ NYI --- config location = /re { access_log off; - content_by_lua ' + content_by_lua_block { local m, err local gsub = ngx.re.gsub local subj = string.rep("bcbd", 2048) @@ -195,7 +195,7 @@ NYI end ngx.say("s: ", s) ngx.say("n: ", n) - '; + } } --- request GET /re @@ -214,7 +214,7 @@ bad argument type --- config location = /t { - content_by_lua ' + content_by_lua_block { local data = [[ INNER INNER @@ -229,7 +229,7 @@ location = /t { end, "s") ngx.print(res) - '; + } } --- request @@ -250,7 +250,7 @@ NYI --- config location = /t { - content_by_lua ' + content_by_lua_block { local data = [[ INNER INNER @@ -265,7 +265,7 @@ location = /t { end, "s") ngx.print(res) - '; + } } --- request @@ -286,7 +286,7 @@ NYI --- config location = /t { - content_by_lua ' + content_by_lua_block { function test() local data = [[ OUTER {FIRST} @@ -314,7 +314,7 @@ location = /t { end test() - '; + } } --- request GET /t @@ -332,11 +332,11 @@ NYI --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local newstr, n, err = ngx.re.sub(1234, "([0-9])[0-9]", 5, "jo") ngx.say(newstr) - '; + } } --- request GET /re @@ -352,7 +352,7 @@ attempt to get length of local 'subj' (a number value) --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local lookup = function(m) -- note we are returning a number type here return 5 @@ -360,7 +360,7 @@ attempt to get length of local 'subj' (a number value) local newstr, n, err = ngx.re.sub("hello, 1234", "([0-9])[0-9]", lookup, "jo") ngx.say(newstr) - '; + } } --- request GET /re @@ -376,7 +376,7 @@ attempt to get length of local 'bit' (a number value) --- http_config eval: $::HttpConfig --- config location /re { - content_by_lua ' + content_by_lua_block { local lookup = function(m) -- note we are returning a number type here return 5 @@ -384,7 +384,7 @@ attempt to get length of local 'bit' (a number value) local newstr, n, err = ngx.re.gsub("hello, 1234", "([0-9])[0-9]", lookup, "jo") ngx.say(newstr) - '; + } } --- request GET /re diff --git a/t/request.t b/t/request.t index 3d13035c2..f6be77bf0 100644 --- a/t/request.t +++ b/t/request.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,7 +43,7 @@ __DATA__ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local headers for i = 1, 200 do @@ -57,7 +57,7 @@ __DATA__ for _, k in ipairs(keys) do ngx.say(k, ": ", headers[k]) end - '; + } } --- request GET /t @@ -86,7 +86,7 @@ qr/ -- NYI: (?!return to lower frame)/, --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local headers for i = 1, 200 do @@ -100,7 +100,7 @@ qr/ -- NYI: (?!return to lower frame)/, for _, k in ipairs(keys) do ngx.say(k, ": ", headers[k]) end - '; + } } --- request GET /t @@ -127,7 +127,7 @@ qr/\[TRACE \d+ .*? -> 1\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local headers for i = 1, 200 do @@ -141,7 +141,7 @@ qr/\[TRACE \d+ .*? -> 1\]/ for _, k in ipairs(keys) do ngx.say(k, ": ", headers[k]) end - '; + } } --- request GET /t @@ -165,7 +165,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local headers, header for i = 1, 100 do @@ -181,7 +181,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ for _, k in ipairs(keys) do ngx.say(k, ": ", headers[k]) end - '; + } } --- request GET /t @@ -208,7 +208,7 @@ qr/ -- NYI: (?!return to lower frame at)(?!C function 0x[0-9a-f]+ at content_by_ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local args for i = 1, 200 do @@ -231,7 +231,7 @@ qr/ -- NYI: (?!return to lower frame at)(?!C function 0x[0-9a-f]+ at content_by_ ngx.say(k, ": ", v) end end - '; + } } --- request GET /t?a=3%200&foo%20bar=&a=hello&blah @@ -253,7 +253,7 @@ qr/\[TRACE \d+ .*? -> \d+\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local args for i = 1, 200 do @@ -276,7 +276,7 @@ qr/\[TRACE \d+ .*? -> \d+\]/ ngx.say(k, ": ", v) end end - '; + } } --- request GET /t? @@ -294,7 +294,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.start_time() @@ -305,7 +305,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ ngx.say(">= 0.099: ", elapsed >= 0.099) ngx.say("< 0.11: ", elapsed < 0.11) -- ngx.say(t, " ", elapsed) - '; + } } --- request GET /t @@ -328,13 +328,13 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.get_method() end ngx.say("method: ", t) - '; + } } --- request GET /t @@ -355,13 +355,13 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.get_method() end ngx.say("method: ", t) - '; + } } --- request OPTIONS /t @@ -382,14 +382,14 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.get_method() end ngx.say("method: ", t) ngx.req.discard_body() - '; + } } --- request POST /t @@ -411,14 +411,14 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.get_method() end ngx.say("method: ", t) ngx.req.discard_body() - '; + } } --- request BLAH /t @@ -440,14 +440,14 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.req.get_method() end ngx.say("method: ", t) ngx.req.discard_body() - '; + } } --- request CONNECT /t @@ -469,13 +469,13 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do ngx.req.set_method(ngx.HTTP_PUT) end ngx.say("method: ", ngx.req.get_method()) - '; + } } --- request GET /t @@ -496,13 +496,13 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do ngx.req.set_header("foo", i) end ngx.say("header foo: ", ngx.var.http_foo) - '; + } } --- request GET /t @@ -523,13 +523,13 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do ngx.req.set_header("foo", nil) end ngx.say("header foo: ", type(ngx.var.http_foo)) - '; + } } --- request GET /t @@ -550,14 +550,14 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { ngx.req.set_header("foo", "hello") local t for i = 1, 500 do t = ngx.req.clear_header("foo") end ngx.say("header foo: ", type(ngx.var.http_foo)) - '; + } } --- request GET /t @@ -570,4 +570,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ [error] bad argument type stitch - diff --git a/t/response.t b/t/response.t index 885101887..47451236f 100644 --- a/t/response.t +++ b/t/response.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,12 +43,12 @@ __DATA__ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { for i = 1, 100 do ngx.header["Foo"] = i end ngx.say("Foo: ", ngx.header["Foo"]) - '; + } } --- request GET /t @@ -68,13 +68,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { for i = 1, 200 do ngx.header["Foo"] = i ngx.header["Foo"] = nil end ngx.say("Foo: ", ngx.header["Foo"]) - '; + } } --- request GET /t @@ -95,7 +95,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { for i = 1, 200 do ngx.header["Foo"] = {i, i + 1} end @@ -105,7 +105,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/ else ngx.say("Foo: ", v) end - '; + } } --- request GET /t @@ -125,14 +125,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local v for i = 1, 100 do ngx.header["Foo"] = i v = ngx.header["Foo"] end ngx.say("Foo: ", v) - '; + } } --- request GET /t @@ -155,13 +155,13 @@ qr/ -- NYI: (?!return to lower frame)/, --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local v for i = 1, 100 do v = ngx.header["Foo"] end ngx.say("Foo: ", v) - '; + } } --- request GET /t @@ -182,14 +182,14 @@ stitch --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { ngx.header["Foo"] = {"foo", "bar"} local v for i = 1, 100 do v = ngx.header["Foo"] end ngx.say("Foo: ", table.concat(v, ", ")) - '; + } } --- request GET /t @@ -209,7 +209,7 @@ stitch --- http_config eval: $::HttpConfig --- config location /lua { - content_by_lua ' + content_by_lua_block { ngx.header.cache_control = { "private", "no-store" } ngx.header.cache_control = { "no-cache", "blah", "foo" } local v @@ -217,7 +217,7 @@ stitch v = ngx.header.cache_control end ngx.say("Cache-Control: ", table.concat(v, ", ")) - '; + } } --- request GET /lua @@ -231,4 +231,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):5 (?:loop|-> \d+)\]/ [error] -- NYI: stitch - diff --git a/t/semaphore.t b/t/semaphore.t index 18c838985..509e317cc 100644 --- a/t/semaphore.t +++ b/t/semaphore.t @@ -1304,7 +1304,7 @@ count in A: 0 -=== TEST 26: kill a light thread that is waiting on a semaphore(no resource) +=== TEST 26: kill a light thread that is waiting on a semaphore (no resource) --- http_config eval: $::HttpConfig --- config location /test { @@ -1337,7 +1337,7 @@ ok -=== TEST 27: kill a light thread that is waiting on a semaphore(after post) +=== TEST 27: kill a light thread that is waiting on a semaphore (after post) --- http_config eval: $::HttpConfig --- config location /test { @@ -1774,7 +1774,7 @@ GET /test -=== TEST 39: basic semaphore count(negative number) +=== TEST 39: basic semaphore count (negative number) --- http_config eval: $::HttpConfig --- config location /test { diff --git a/t/sha1_bin.t b/t/sha1_bin.t index 818794191..05fe51081 100644 --- a/t/sha1_bin.t +++ b/t/sha1_bin.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -27,7 +27,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,13 +41,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /sha1_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.sha1_bin("hello") end ngx.say(string.len(s)) - '; + } } --- request GET /sha1_bin @@ -64,13 +64,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /sha1_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.sha1_bin(nil) end ngx.say(string.len(s)) - '; + } } --- request GET /sha1_bin @@ -87,13 +87,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /sha1_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.sha1_bin(3.14) end ngx.say(string.len(s)) - '; + } } --- request GET /sha1_bin @@ -110,13 +110,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /sha1_bin { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.sha1_bin(true) end ngx.say(string.len(s)) - '; + } } --- request GET /sha1_bin @@ -126,4 +126,3 @@ GET /sha1_bin qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] - diff --git a/t/shdict.t b/t/shdict.t index 5d1f415fe..b5f94eb77 100644 --- a/t/shdict.t +++ b/t/shdict.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -42,7 +42,7 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -58,7 +58,7 @@ __DATA__ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -78,7 +78,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):11 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -90,7 +90,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):11 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -110,7 +110,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -122,7 +122,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -142,7 +142,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -154,7 +154,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -174,7 +174,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -186,7 +186,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -206,7 +206,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -218,7 +218,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -238,7 +238,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -250,7 +250,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -271,7 +271,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags, stale local dogs = ngx.shared.dogs @@ -284,7 +284,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value: ", val) ngx.say("flags: ", flags) ngx.say("stale: ", stale) - '; + } } --- request GET /t @@ -305,7 +305,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags, stale local dogs = ngx.shared.dogs @@ -323,7 +323,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value: ", val) ngx.say("flags: ", flags) ngx.say("stale: ", stale) - '; + } } --- request GET /t @@ -344,7 +344,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):12 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val local dogs = ngx.shared.dogs @@ -359,7 +359,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):12 loop\]/ end ngx.say("value: ", val) ngx.say("err: ", err) - '; + } } --- request GET /t @@ -378,23 +378,23 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):11 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val local dogs = ngx.shared.dogs -- local cd = ffi.cast("void *", dogs) dogs:set("foo", 56) - for i = 1, 100 do + for i = 1, 150 do val, err = dogs:incr("foo", 2.1) end ngx.say("value: ", val) ngx.say("err: ", err) - '; + } } --- request GET /t --- response_body -value: 266 +value: 371 err: nil --- error_log eval qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ @@ -408,7 +408,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -425,7 +425,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -445,7 +445,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -462,7 +462,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -482,7 +482,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -494,7 +494,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -514,7 +514,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -526,7 +526,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -546,7 +546,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -558,7 +558,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -578,7 +578,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -591,7 +591,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -611,7 +611,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -623,7 +623,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -643,7 +643,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -661,7 +661,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -681,7 +681,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -699,7 +699,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -719,7 +719,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -737,7 +737,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -757,7 +757,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -770,7 +770,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/ ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t @@ -791,14 +791,14 @@ stitch --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local val, flags local dogs = ngx.shared.dogs local ok, err = dogs:set(nil, "bar") if not ok then ngx.say("failed to set: ", err) end - '; + } } --- request GET /t @@ -815,14 +815,14 @@ failed to set: nil key --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local val, flags local dogs = ngx.shared.dogs local value, err = dogs:get(nil, "bar") if not ok then ngx.say("failed to get: ", err) end - '; + } } --- request GET /t @@ -839,14 +839,14 @@ failed to get: nil key --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local val, flags local dogs = ngx.shared.dogs local value, err = dogs:get_stale(nil, "bar") if not ok then ngx.say("failed to get stale: ", err) end - '; + } } --- request GET /t @@ -863,14 +863,14 @@ failed to get stale: nil key --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local val, flags local dogs = ngx.shared.dogs local value, err = dogs:incr(nil, 32) if not value then ngx.say("failed to incr: ", err) end - '; + } } --- request GET /t @@ -887,7 +887,7 @@ failed to incr: nil key --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val, flags local dogs = ngx.shared.dogs @@ -900,7 +900,7 @@ failed to incr: nil key ngx.say("value type: ", type(val)) ngx.say("value: ", val) ngx.say("flags: ", flags) - '; + } } --- request GET /t diff --git a/t/ssl-session-fetch.t b/t/ssl-session-fetch.t index 2fcb8aed5..07dbfe3fd 100644 --- a/t/ssl-session-fetch.t +++ b/t/ssl-session-fetch.t @@ -1,4 +1,4 @@ -# vim:set ft=ts=4 sw=4 et fdm=marker: +# vim:set ft= ts=4 sw=4 et fdm=marker: use Test::Nginx::Socket::Lua; use Cwd qw(abs_path realpath cwd); @@ -31,15 +31,15 @@ __DATA__ === TEST 1: get resume session id serialized --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_fetch_by_lua_block { + local ssl = require "ngx.ssl.session" + local sid = ssl.get_session_id() + print("session id: ", sid) + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_fetch_by_lua_block { - local ssl = require "ngx.ssl.session" - local sid = ssl.get_session_id() - print("session id: ", sid) - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -112,21 +112,21 @@ qr/ssl_session_fetch_by_lua_block:4: session id: [a-fA-f\d]+/s, === TEST 2: attempt to fetch new session in lua_ctx during resumption. --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_fetch_by_lua_block { + local ssl = require "ngx.ssl.session" + local sess, err = ssl.get_serialized_session() + if sess then + print("session size: ", #sess) + end + + if err then + print("get session error: ", err) + end + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_fetch_by_lua_block { - local ssl = require "ngx.ssl.session" - local sess, err = ssl.get_serialized_session() - if sess then - print("session size: ", #sess) - end - - if err then - print("get session error: ", err) - end - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -203,32 +203,32 @@ Use a tmp file to store and resume session. This is for testing only. In practice, never store session in plaintext on persistent storage. --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_store_by_lua_block { + local ssl = require "ngx.ssl.session" - server { - listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; - server_name test.com; - ssl_session_store_by_lua_block { - local ssl = require "ngx.ssl.session" + local sid = ssl.get_session_id() + print("session id: ", sid) + local sess = ssl.get_serialized_session() + print("session size: ", #sess) - local sid = ssl.get_session_id() - print("session id: ", sid) - local sess = ssl.get_serialized_session() - print("session size: ", #sess) + local f = assert(io.open("$TEST_NGINX_SERVER_ROOT/html/session.tmp", "w")) + f:write(sess) + f:close() + } - local f = assert(io.open("t/servroot/html/session.tmp", "w")) - f:write(sess) - f:close() - } + ssl_session_fetch_by_lua_block { + local ssl = require "ngx.ssl.session" + local sid = ssl.get_session_id() + print("session id: ", sid) + local f = assert(io.open("$TEST_NGINX_SERVER_ROOT/html/session.tmp")) + local sess = f:read("*a") + f:close() + ssl.set_serialized_session(sess) + } - ssl_session_fetch_by_lua_block { - local ssl = require "ngx.ssl.session" - local sid = ssl.get_session_id() - print("session id: ", sid) - local f = assert(io.open("t/servroot/html/session.tmp")) - local sess = f:read("*a") - f:close() - ssl.set_serialized_session(sess) - } + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; @@ -304,27 +304,27 @@ Session resumption should fail, but the handshake should be able to carry on and negotiate a new session. --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_store_by_lua_block { + local ssl = require "ngx.ssl.session" + + local sid = ssl.get_session_id() + print("session id: ", sid) + } + + ssl_session_fetch_by_lua_block { + local ssl = require "ngx.ssl.session" + local sid = ssl.get_session_id() + print("session id: ", sid) + local sess = "==garbage data==" + local ok, err = ssl.set_serialized_session(sess) + if not ok or err then + print("failed to resume session: ", err) + end + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_store_by_lua_block { - local ssl = require "ngx.ssl.session" - - local sid = ssl.get_session_id() - print("session id: ", sid) - } - - ssl_session_fetch_by_lua_block { - local ssl = require "ngx.ssl.session" - local sid = ssl.get_session_id() - print("session id: ", sid) - local sess = "==garbage data==" - local ok, err = ssl.set_serialized_session(sess) - if not ok or err then - print("failed to resume session: ", err) - end - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; diff --git a/t/ssl-session-store.t b/t/ssl-session-store.t index 8542b08ef..d42e0598e 100644 --- a/t/ssl-session-store.t +++ b/t/ssl-session-store.t @@ -31,15 +31,15 @@ __DATA__ === TEST 1: get new session serialized --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_store_by_lua_block { + local ssl = require "ngx.ssl.session" + local sess = ssl.get_serialized_session() + print("session size: ", #sess) + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_store_by_lua_block { - local ssl = require "ngx.ssl.session" - local sess = ssl.get_serialized_session() - print("session size: ", #sess) - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -103,15 +103,15 @@ qr/ssl_session_store_by_lua_block:4: session size: \d+/s === TEST 2: get new session id serialized --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_store_by_lua_block { + local ssl = require "ngx.ssl.session" + local sid = ssl.get_session_id() + print("session id: ", sid) + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_store_by_lua_block { - local ssl = require "ngx.ssl.session" - local sid = ssl.get_session_id() - print("session id: ", sid) - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -175,51 +175,51 @@ qr/ssl_session_store_by_lua_block:4: session id: [a-fA-f\d]+/s === TEST 3: store the session via timer to memcached --- http_config lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;"; + ssl_session_store_by_lua_block { + local ssl = require "ngx.ssl.session" + local function f(premature, key, value) + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT) + if not ok then + ngx.log(ngx.ERR, "failed to connect to memc: ", err) + return + end + + local bytes, err = sock:send("set " .. key .. " 0 0 " + .. tostring(#value) .. " \r\n" + .. value .. "\r\n") + if not bytes then + ngx.log(ngx.ERR, "failed to send set command: ", err) + return + end + + local res, err = sock:receive() + if not res then + ngx.log(ngx.ERR, "failed to receive memc reply: ", err) + return + end + + print("received memc reply: ", res) + end + + local sid = ssl.get_session_id() + print("session id: ", sid) + local sess = ssl.get_serialized_session() + print("session size: ", #sess) + + local ok, err = ngx.timer.at(0, f, sid, sess) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; - ssl_session_store_by_lua_block { - local ssl = require "ngx.ssl.session" - local function f(premature, key, value) - local sock = ngx.socket.tcp() - - sock:settimeout(5000) - - local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT) - if not ok then - ngx.log(ngx.ERR, "failed to connect to memc: ", err) - return - end - - local bytes, err = sock:send("set " .. key .. " 0 0 " - .. tostring(#value) .. " \r\n" - .. value .. "\r\n") - if not bytes then - ngx.log(ngx.ERR, "failed to send set command: ", err) - return - end - - local res, err = sock:receive() - if not res then - ngx.log(ngx.ERR, "failed to receive memc reply: ", err) - return - end - - print("received memc reply: ", res) - end - - local sid = ssl.get_session_id() - print("session id: ", sid) - local sess = ssl.get_serialized_session() - print("session size: ", #sess) - - local ok, err = ngx.timer.at(0, f, sid, sess) - if not ok then - ngx.log(ngx.ERR, "failed to create timer: ", err) - return - end - } ssl_protocols SSLv3; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; diff --git a/t/ssl.t b/t/ssl.t index a1c5e2f49..4ba67e63f 100644 --- a/t/ssl.t +++ b/t/ssl.t @@ -1,4 +1,4 @@ -# vim:set ft=ts=4 sw=4 et fdm=marker: +# vim:set ft= ts=4 sw=4 et fdm=marker: use Test::Nginx::Socket::Lua; use Cwd qw(cwd); @@ -83,7 +83,7 @@ __DATA__ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -194,7 +194,7 @@ sslv3 alert handshake failure while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -293,7 +293,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -393,7 +393,7 @@ read SNI name from Lua: test.com while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -509,7 +509,7 @@ read SNI name from Lua: nil, type: nil while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -547,6 +547,7 @@ qr/Using unix socket file .*?nginx\.sock/ --- no_error_log [error] [alert] +--- no_check_leak @@ -629,7 +630,7 @@ qr/Using unix socket file .*?nginx\.sock/ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -665,6 +666,7 @@ Using IPv4 address: 127.0.0.1 --- no_error_log [error] [alert] +--- no_check_leak @@ -747,7 +749,7 @@ Using IPv4 address: 127.0.0.1 while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -784,6 +786,7 @@ Using IPv6 address: 0.0.0.1 [error] [alert] --- skip_eval: 6: system("ping6 -c 1 ::1 >/dev/null 2>&1") ne 0 +--- no_check_leak @@ -869,7 +872,7 @@ Using IPv6 address: 0.0.0.1 while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -996,7 +999,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1521,7 +1524,7 @@ ssl cert by lua done while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1654,7 +1657,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1787,7 +1790,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1911,7 +1914,7 @@ qr/\[error\] .*? failed to parse pem cert: PEM_read_bio_X509_AUX\(\) failed/ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -2035,7 +2038,7 @@ qr/\[error\] .*? failed to parse pem cert: PEM_read_bio_X509\(\) failed/ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end diff --git a/t/status.t b/t/status.t index e611b785c..c45c5c016 100644 --- a/t/status.t +++ b/t/status.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;\$prefix/html/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,13 +43,13 @@ __DATA__ --- config location = /t { return 201; - header_filter_by_lua ' + header_filter_by_lua_block { local sum = 0 for i = 1, 100 do sum = sum + ngx.status end ngx.log(ngx.WARN, "sum: ", sum) - '; + } } --- request GET /t @@ -71,12 +71,12 @@ qr/\[TRACE\s+\d+\s+header_filter_by_lua:3 loop\]/ --- config location = /t { return 201; - header_filter_by_lua ' + header_filter_by_lua_block { for i = 100, 200 do ngx.status = i end ngx.log(ngx.WARN, "status: ", ngx.status) - '; + } } --- request GET /t @@ -89,4 +89,3 @@ GET /t ["status: 200,", qr/\[TRACE\s+\d+\s+header_filter_by_lua:2 loop\]/ ] - diff --git a/t/time.t b/t/time.t index b9e1c7c40..c5338364f 100644 --- a/t/time.t +++ b/t/time.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { -- local verbose = true local verbose = false local outfile = "$Test::Nginx::Util::ErrLogFile" @@ -32,7 +32,7 @@ our $HttpConfig = <<_EOC_; -- jit.opt.start("hotloop=1") -- jit.opt.start("loopunroll=1000000") -- jit.off() - '; + } _EOC_ #no_diff(); @@ -47,7 +47,7 @@ __DATA__ --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.now() @@ -58,7 +58,7 @@ __DATA__ ngx.say(">= 0.099: ", elapsed >= 0.099) ngx.say("< 0.11: ", elapsed < 0.11) -- ngx.say(t, " ", elapsed) - '; + } } --- request GET /t @@ -81,7 +81,7 @@ stitch --- config location = /t { access_log off; - content_by_lua ' + content_by_lua_block { local t for i = 1, 500 do t = ngx.time() @@ -89,7 +89,7 @@ stitch ngx.say(t > 1400960598) local diff = os.time() - t ngx.say(diff <= 1) - '; + } } --- request GET /t @@ -103,4 +103,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ [error] bad argument type stitch - diff --git a/t/uri.t b/t/uri.t index cd531d458..277090b50 100644 --- a/t/uri.t +++ b/t/uri.t @@ -15,7 +15,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -27,7 +27,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -41,13 +41,13 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.unescape_uri("hello%20world") end ngx.say(s) - '; + } } --- request GET /uri @@ -64,13 +64,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.unescape_uri(nil) end ngx.say(s) - '; + } } --- request GET /uri @@ -86,13 +86,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.unescape_uri(3.14) end ngx.say(s) - '; + } } --- request GET /uri @@ -109,13 +109,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri("hello world") end ngx.say(s) - '; + } } --- request GET /uri @@ -132,13 +132,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri("helloworld") end ngx.say(s) - '; + } } --- request GET /uri @@ -155,13 +155,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri(nil) end ngx.say(s) - '; + } } --- request GET /uri @@ -177,13 +177,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri(3.14) end ngx.say(s) - '; + } } --- request GET /uri @@ -200,13 +200,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri(string.rep("a", 4097)) end ngx.say(s) - '; + } } --- request GET /uri @@ -222,13 +222,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri(string.rep(" ", 1365)) end ngx.say(s) - '; + } } --- request GET /uri @@ -244,13 +244,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- http_config eval: $::HttpConfig --- config location = /uri { - content_by_lua ' + content_by_lua_block { local s for i = 1, 100 do s = ngx.escape_uri(string.rep(" ", 1366)) end ngx.say(s) - '; + } } --- request GET /uri @@ -259,4 +259,3 @@ GET /uri qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] - diff --git a/t/var.t b/t/var.t index a92464169..bdb0e592b 100644 --- a/t/var.t +++ b/t/var.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,14 +43,14 @@ __DATA__ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val for i = 1, 100 do val = ngx.var.foo end ngx.say("value: ", val) - '; + } } --- request GET /t @@ -69,14 +69,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val for i = 1, 100 do val = ngx.var.FOO end ngx.say("value: ", val) - '; + } } --- request GET /t @@ -95,14 +95,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val for i = 1, 100 do val = ngx.var[0] end ngx.say("value: ", val) - '; + } } --- request GET /t @@ -121,14 +121,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location ~ '^(/t)' { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val for i = 1, 100 do val = ngx.var[1] end ngx.say("value: ", val) - '; + } } --- request GET /t @@ -147,14 +147,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" local val = "hello" for i = 1, 100 do ngx.var.foo = val end ngx.say("value: ", val) - '; + } } --- request GET /t @@ -173,13 +173,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" for i = 1, 100 do ngx.var.foo = nil end ngx.say("value: ", ngx.var.foo) - '; + } } --- request GET /t @@ -198,13 +198,13 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- config location = /t { set $foo hello; - content_by_lua ' + content_by_lua_block { local ffi = require "ffi" for i = 1, 100 do ngx.var.foo = i end ngx.say("value: ", ngx.var.foo) - '; + } } --- request GET /t @@ -215,4 +215,3 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ --- no_error_log [error] -- NYI: - diff --git a/t/worker.t b/t/worker.t index 1083b1448..80ff4174b 100644 --- a/t/worker.t +++ b/t/worker.t @@ -16,7 +16,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -28,7 +28,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -42,14 +42,14 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local v local exiting = ngx.worker.exiting for i = 1, 400 do v = exiting() end ngx.say(v) - '; + } } --- request GET /t @@ -68,7 +68,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local v local pid = ngx.worker.pid for i = 1, 400 do @@ -76,7 +76,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ end ngx.say(v == tonumber(ngx.var.pid)) ngx.say(v) - '; + } } --- request GET /t @@ -96,14 +96,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local v local id = ngx.worker.id for i = 1, 400 do v = id() end ngx.say("worker id: ", v) - '; + } } --- request GET /t @@ -123,14 +123,14 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):4 loop\]/ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local v local count = ngx.worker.count for i = 1, 400 do v = count() end ngx.say("workers: ", v) - '; + } } --- request GET /t diff --git a/t/worker_count_5.t b/t/worker_count_5.t index c0d68282a..488ec521c 100644 --- a/t/worker_count_5.t +++ b/t/worker_count_5.t @@ -17,7 +17,7 @@ my $pwd = cwd(); our $HttpConfig = <<_EOC_; lua_shared_dict dogs 1m; lua_package_path "$pwd/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; - init_by_lua ' + init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" @@ -29,7 +29,7 @@ our $HttpConfig = <<_EOC_; require "resty.core" -- jit.off() - '; + } _EOC_ #no_diff(); @@ -43,14 +43,14 @@ __DATA__ --- http_config eval: $::HttpConfig --- config location = /t { - content_by_lua ' + content_by_lua_block { local v local count = ngx.worker.count for i = 1, 400 do v = count() end ngx.say("workers: ", v) - '; + } } --- request GET /t diff --git a/valgrind.suppress b/valgrind.suppress index 3a49ed39c..472352e2c 100644 --- a/valgrind.suppress +++ b/valgrind.suppress @@ -58,3 +58,8 @@ fun:epoll_ctl fun:ngx_epoll_test_rdhup } +{ + + Memcheck:Cond + obj:* +}