diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..6fe6f35cec --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.t linguist-language=Text diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..e6359b0a07 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,23 @@ +This place is for bug reports and development discussions only. For general questions and +discussions, please join the openresty-en mailing list instead: https://openresty.org/en/community.html + +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, +and your operating system version. +* 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. + +Please, do not use Chinese here. This place is considered English only. If you +really want to use Chinese, please join and post to the openresty (Chinese) +mailing list instead. Please see https://openresty.org/en/community.html Thanks for +your cooperation. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..5e833bab31 --- /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-nginx-module project. diff --git a/.github/workflows/semantic-pull-request.yml b/.github/workflows/semantic-pull-request.yml new file mode 100644 index 0000000000..12b87cb3c1 --- /dev/null +++ b/.github/workflows/semantic-pull-request.yml @@ -0,0 +1,30 @@ +name: "Lint PR" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # Configure which types are allowed. + # Default: https://github.com/commitizen/conventional-commit-types + types: | + bugfix # bug fixes + change # backward incompatible changes + doc # documentation changes including code comments + editor # code editor related configurations + feature # implementing a new feature + optimize # performance optimizations + refactor # code refactoring and other code rearrangement + style # coding style changes + tests # test suite changes diff --git a/.gitignore b/.gitignore index a316fe18a9..5a8d398bb8 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ test/blib test.sh t.sh t/t.sh +t/servroot* test/t/servroot/ releng reset @@ -128,7 +129,7 @@ src/logby.[ch] src/sleep.[ch] a.patch all -build1[0-3] +build1[0-9] g buildroot/ src/headerfilterby.[ch] @@ -142,12 +143,38 @@ ERRORS src/bodyfilterby.[ch] src/tcp.[ch] src/initby.[ch] +src/initworkerby.[ch] src/socket.[ch] src/udp.[ch] src/method.[ch] tre src/phase.[ch] src/probe.h +src/uthread.[ch] +src/timer.[ch] +src/config.[ch] +src/worker.[ch] +src/certby.[ch] +src/storeby.[ch] +src/fetchby.[ch] +src/ssl.[ch] +src/ocsp.c +src/lex.[ch] +src/balancer.[ch] +src/semaphore.[ch] *.plist lua +ttimer Makefile +tsubreq +tthread +addr2line +hup +theaders +src/ngx_http_lua_autoconf.h +src/autoconf.h +src/filters.c +src/filters.h +src/ringbuf.c +src/ringbuf.h +src/pipe.[ch] diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index db339a7d34..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "deps/ngx_devel_kit"] - path = deps/ngx_devel_kit - url = git://github.com/simpl/ngx_devel_kit.git diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000000..f1a8a2e255 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,43 @@ +--- +pull_request_rules: + - name: warn on conflicts + conditions: + - conflict + actions: + comment: + message: This pull request is now in conflict :( + label: + add: + - conflict + - name: remove conflict label if not needed + conditions: + - -conflict + actions: + label: + remove: + - conflict + - name: add label needs-test-cases + conditions: + - files~=^src/ + - -files~=^t/ + actions: + label: + add: + - needs-test-cases + - name: remove label needs-test-cases + conditions: + - label=needs-test-cases + - files~=^src/ + - files~=^t/ + actions: + label: + remove: + - needs-test-cases + - name: add label could-be-merged + conditions: + - "#approved-reviews-by>=2" + - status-success=Travis CI - Pull Request + actions: + label: + add: + - could-be-merged diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..4aebcf6996 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,159 @@ +dist: focal + +branches: + only: + - "master" + +os: linux + +language: c + +compiler: + - gcc + +addons: + apt: + packages: + - ack + - axel + - cpanminus + - libtest-base-perl + - libtext-diff-perl + - liburi-perl + - libwww-perl + - libtest-longstring-perl + - liblist-moreutils-perl + - libgd-dev + - time + - cmake + - libunwind-dev + - wget + - libbrotli1 + - lsb-release + - wget + - gnupg + - ca-certificates + +cache: + directories: + - download-cache + +env: + global: + - JOBS=3 + - 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 + #- PCRE2_PREFIX=/usr/local/openresty/pcre2 + - PCRE2_PREFIX=/opt/pcre2 + - PCRE2_LIB=$PCRE2_PREFIX/lib + - PCRE2_INC=$PCRE2_PREFIX/include + #- OPENSSL_PREFIX=/usr/local/openresty/openssl3 + - OPENSSL_PREFIX=/opt/openssl3 + - OPENSSL_LIB=$OPENSSL_PREFIX/lib + - OPENSSL_INC=$OPENSSL_PREFIX/include + - LIBDRIZZLE_PREFIX=/opt/drizzle + - LIBDRIZZLE_INC=$LIBDRIZZLE_PREFIX/include/libdrizzle-1.0 + - LIBDRIZZLE_LIB=$LIBDRIZZLE_PREFIX/lib + - LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH + - DRIZZLE_VER=2011.07.21 + - TEST_NGINX_SLEEP=0.006 + - MALLOC_PERTURB_=9 + jobs: + - NGINX_VERSION=1.29.2 OPENSSL_VER=3.5.4 OPENSSL_PATCH_VER=3.5.4 TEST_NGINX_TIMEOUT=5 PCRE2_VER=10.46 + - NGINX_VERSION=1.29.2 OPENSSL_VER=3.5.4 OPENSSL_PATCH_VER=3.5.4 TEST_NGINX_TIMEOUT=5 PCRE2_VER=10.46 TEST_NGINX_USE_HTTP2=1 + - NGINX_VERSION=1.29.2 OPENSSL_VER=3.5.4 OPENSSL_PATCH_VER=3.5.4 TEST_NGINX_USE_HTTP3=1 TEST_NGINX_QUIC_IDLE_TIMEOUT=3 PCRE2_VER=10.46 + - NGINX_VERSION=1.29.2 BORINGSSL=1 TEST_NGINX_USE_HTTP3=1 TEST_NGINX_QUIC_IDLE_TIMEOUT=3 PCRE2_VER=10.46 + +services: + - memcached + - redis + - mysql + +before_install: + - '! grep -n -P ''(?<=.{80}).+'' --color `find src -name ''*.c''` `find . -name ''*.h''` || (echo "ERROR: Found C source lines exceeding 80 columns." > /dev/stderr; exit 1)' + - '! grep -n -P ''\t+'' --color `find src -name ''*.c''` `find . -name ''*.h''` || (echo "ERROR: Cannot use tabs." > /dev/stderr; exit 1)' + - /usr/bin/env perl $(command -v cpanm) --sudo --notest Test::Nginx IPC::Run > build.log 2>&1 || (cat build.log && exit 1) + - wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add - + - echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list + - sudo apt-get update + - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openresty-pcre2 openresty-openssl3 openresty-pcre2-dev openresty-openssl3-dev + + +install: + - if [ ! -f download-cache/drizzle7-$DRIZZLE_VER.tar.gz ]; then wget -P download-cache https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/drizzle7-$DRIZZLE_VER.tar.gz; fi + - if [ -n "$PCRE2_VER" ] && [ ! -f download-cache/pcre2-$PCRE2_VER.tar.gz ]; then wget -P download-cache https://github.com/PCRE2Project/pcre2/releases/download/pcre2-${PCRE2_VER}/pcre2-${PCRE2_VER}.tar.gz; fi + - if [ -n "$OPENSSL_VER" ] && [ ! -f download-cache/openssl-$OPENSSL_VER.tar.gz ]; then wget -P download-cache https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VER/openssl-$OPENSSL_VER.tar.gz || wget -P download-cache https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz || wget -P download-cache https://www.openssl.org/source/old/${OPENSSL_VER//[a-z]/}/openssl-$OPENSSL_VER.tar.gz; fi + - wget https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/boringssl-20230902-x64-focal.tar.gz + - wget https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/curl-h3-x64-focal.tar.gz + - git clone https://github.com/openresty/test-nginx.git + - git clone https://github.com/openresty/openresty.git ../openresty + - git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx + - git clone https://github.com/openresty/openresty-devel-utils.git + - git clone https://github.com/openresty/mockeagain.git + - git clone https://github.com/openresty/lua-cjson.git lua-cjson + - git clone https://github.com/openresty/lua-upstream-nginx-module.git ../lua-upstream-nginx-module + - git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module + - git clone https://github.com/openresty/nginx-eval-module.git ../nginx-eval-module + - git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module + - git clone https://github.com/FRiCKLE/ngx_coolkit.git ../coolkit-nginx-module + - git clone https://github.com/openresty/headers-more-nginx-module.git ../headers-more-nginx-module + - git clone https://github.com/openresty/drizzle-nginx-module.git ../drizzle-nginx-module + - git clone https://github.com/openresty/set-misc-nginx-module.git ../set-misc-nginx-module + - git clone https://github.com/openresty/memc-nginx-module.git ../memc-nginx-module + - git clone https://github.com/openresty/rds-json-nginx-module.git ../rds-json-nginx-module + - git clone https://github.com/openresty/srcache-nginx-module.git ../srcache-nginx-module + - git clone https://github.com/openresty/redis2-nginx-module.git ../redis2-nginx-module + - git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core + - git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache + - git clone https://github.com/openresty/lua-resty-mysql.git ../lua-resty-mysql + - git clone https://github.com/spacewander/lua-resty-rsa.git ../lua-resty-rsa + - git clone https://github.com/openresty/lua-resty-string.git ../lua-resty-string + - git clone https://github.com/openresty/stream-lua-nginx-module.git ../stream-lua-nginx-module + - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2 + +before_script: + - mysql -uroot -e "create database ngx_test; CREATE USER 'ngx_test'@'%' IDENTIFIED WITH mysql_native_password BY 'ngx_test'; grant all on ngx_test.* to 'ngx_test'@'%'; flush privileges;" + +script: + - sudo tar -C / -xf curl-h3-x64-focal.tar.gz + - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl-h3/bin:$PATH + - ngx-releng > check.txt || true + - lines=`wc -l check.txt | awk '{print $1}'`; if [ $lines -gt 5 ]; then cat check.txt; exit 1; fi + - sudo iptables -I OUTPUT 1 -p udp --dport 10086 -j REJECT + - sudo iptables -I OUTPUT -p tcp --dst 127.0.0.2 --dport 12345 -j DROP + - sudo iptables -I OUTPUT -p udp --dst 127.0.0.2 --dport 12345 -j DROP + - sudo ip route add prohibit 0.0.0.1/32 + - sudo sysctl -w kernel.pid_max=10000 + - cd luajit2/ + - 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 .. + - tar xzf download-cache/drizzle7-$DRIZZLE_VER.tar.gz && cd drizzle7-$DRIZZLE_VER + - ./configure --prefix=$LIBDRIZZLE_PREFIX --without-server > build.log 2>&1 || (cat build.log && exit 1) + - make libdrizzle-1.0 -j$JOBS > build.log 2>&1 || (cat build.log && exit 1) + - sudo make install-libdrizzle-1.0 > build.log 2>&1 || (cat build.log && exit 1) + - cd ../mockeagain/ && make CC=$CC -j$JOBS && cd .. + - cd lua-cjson/ && make -j$JOBS && sudo make install && cd .. + - if [ -n "$PCRE2_VER" ]; then tar zxf download-cache/pcre2-$PCRE2_VER.tar.gz; cd pcre2-$PCRE2_VER/; ./configure --prefix=$PCRE2_PREFIX --enable-jit --enable-utf > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo PATH=$PATH make install > build.log 2>&1 || (cat build.log && exit 1); cd ..; fi + - if [ -n "$OPENSSL_VER" ]; then tar zxf download-cache/openssl-$OPENSSL_VER.tar.gz; cd openssl-$OPENSSL_VER/; patch -p1 < ../../openresty/patches/openssl-$OPENSSL_PATCH_VER-sess_set_get_cb_yield.patch; ./config shared enable-ssl3 enable-ssl3-method -g --prefix=$OPENSSL_PREFIX --libdir=lib -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 ..; fi + - if [ -n "$BORINGSSL" ]; then sudo rm -fr /usr/local/openresty/openssl3/ && sudo mkdir -p /usr/local/openresty/openssl3 && sudo tar -C /usr/local/openresty/openssl3 -xf boringssl-20230902-x64-focal.tar.gz --strip-components=1; fi + - export NGX_BUILD_CC=$CC + - sh util/build-without-ssl.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1) + - sh util/build-with-dd.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1) + - rm -fr buildroot + - sh util/build.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1) + - nginx -V + - python3 ./util/nc_server.py & + - ldd `which nginx`|grep -E 'luajit|ssl|pcre' + - export LD_PRELOAD=$PWD/mockeagain/mockeagain.so + - export LD_LIBRARY_PATH=$PWD/mockeagain:$LD_LIBRARY_PATH + - export TEST_NGINX_HTTP3_CRT=$PWD/t/cert/http3/http3.crt + - export TEST_NGINX_HTTP3_KEY=$PWD/t/cert/http3/http3.key + - export TEST_NGINX_RESOLVER=8.8.4.4 + - dig +short myip.opendns.com @resolver1.opendns.com || exit 0 + - dig +short @$TEST_NGINX_RESOLVER openresty.org || exit 0 + - dig +short @$TEST_NGINX_RESOLVER agentzh.org || exit 0 + - /usr/bin/env perl $(command -v prove) -I. -Itest-nginx/inc -Itest-nginx/lib -r t/ diff --git a/Changes b/Changes deleted file mode 100644 index 703f73ded4..0000000000 --- a/Changes +++ /dev/null @@ -1,51 +0,0 @@ -0.2.0 - 5 July 2011 -* now we support ngx.var[1], ngx.var[2], and etc to refer to the nginx regex capturing variables \$1, \$2, and etc in Lua. this resolved github issue #43. thanks Tobia Conforto for reporting it. - -* now we use the same value overriding mechanism as ngx_rewrite's set command for ngx.var.VAR = new_value. Assigning values to special variables like $limit_rate and $args should now work; also writing to built-in variables that are not changeable (like $arg_PARAMETER) will result in a 500 error page, as expected, now. thanks Richard Kearsley for reporting it. - -* fixed the lua_code_cache off warning when the lua_code_cache is explicitly on. thanks Feng Xingguo. - -* applied the patch from cyberty to add ngx.http_time() function to expose the nginx core function ngx_http_time to the Lua land. - -* fixed an issue on i386: we now use off_t consistently. mixing it with size_t on 32-bit systems can cause Bad Things. this fixed github issue #42. thanks moodydeath. - -* fixed an issue on i386: fixed a formatter mismatch issue in ngx_http_echo_adjust_subrequest. thanks Wang Bin. This caused incorrect subrequest Content-Length header when a body is specified. - -* now in the subrequest capturing processor, we worked around an issue in ngx_http_static_module that when it issues 301 redirect for directory access w/o a trailing slash, it does not inject r->headers_out.location into the r->headers_out.headers list. thanks moodydeath for reporting it in the discussion of github issue #41. - -* fixed a bug in ngx.location.capture() and ngx.location.capture_multi() that we could not capture locations with internal redirections in them. thanks moodydeath for reporting it in github issue #41. - -* fixed redundant last chunk issue for ngx.exec() invocation at rewrite and access phases: we should quit the current core_run_phases cycle; this also fixed github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location. - -* fixed ngx.exit(status) where status >= 200 and status < 300 for access_by_lua* and rewrite_by_lua*: it should quit the whole request altegother and skip all those subsequent phase handlers (if any). thanks moodydeath for reporting it. - -* fixed github issue #39: setting differnt response headers in Lua with common prefix might interfere with each other. thanks moodydeath. - -* fixed GitHub issue #38: request headers did not forward to subrequests when the "method" or "body" option is explicitly specified by a non-nil value for ngx.location.capture(). thanks Richard Kearsley. - -* fixed a bug in output header set; we should always set the header->hash to 1. thanks moodydeath for reporting it. - -* fixed spots that trigger the "variable set but not used" warning issued by gcc 4.6.0. - -* now we turn the ngx.req.header table into an ngx.req.get_headers() function; we also added ngx.req.set_header(name, value) and ngx.req.clear_header(name). thanks moodydeath. - -* now we make ngx_devel_kit (NDK) optional. thanks Kirill A. Korinskiy. - -* removed a duplicate definition of the ngx_str_set macro caught by ctags; also fixed a warning thrown by gcc -O3 on Mac OS X 10.6. - -* added patch to use PCRE related Lua extensions in ngx_lua (chaoslawful) - -* now we change the way we process HTTP 1.0 requests by automatically buffering all the user outputs generated by ngx.print()/ngx.say() calls, which is much more natural than the old broken way. - -* fixed the "ngx.exec() after ngx.location.capture() hanging" bug for rewrite_by_lua* and access_by_lua* as well. thanks Wendal Chen. - -* applied a patch from moodydeath to introduce the "ngx.is_subrequest" attribute. - -* now we encourage use of the client_body_in_single_buffer directive instead of big client_body_buffer_size when lua_need_request_body is turned on. - -* fixed the config script and added extra linking options needed by LuaJIT in 64-bit Mac OS X. - -* fixed the zero size alert caused by ngx.print("") in Lua. - -* now we always allocate r->request_body for subrequests when the method option is specified for ngx.location.capture*. this prevents accidental inheritance of parent request's request body when client_body_buffer_size < client_max_body_size. - diff --git a/README b/README deleted file mode 100644 index b04ebfe6e5..0000000000 --- a/README +++ /dev/null @@ -1,5327 +0,0 @@ -Name - ngx_lua - Embed the power of Lua into Nginx - - *This module is not distributed with the Nginx source.* See the - installation instructions. - -Status - This module is under active development and is production ready. - -Version - This document describes ngx_lua v0.6.3 - () released on 25 - August 2012. - -Synopsis - # set search paths for pure Lua external libraries (';;' is the default path): - lua_package_path '/foo/bar/?.lua;/blah/?.lua;;'; - - # set search paths for Lua external libraries written in C (can also use ';;'): - lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;'; - - server { - location /inline_concat { - # MIME type determined by default_type: - default_type 'text/plain'; - - set $a "hello"; - set $b "world"; - # inline Lua script - set_by_lua $res "return ngx.arg[1]..ngx.arg[2]" $a $b; - echo $res; - } - - location /rel_file_concat { - set $a "foo"; - set $b "bar"; - # script path relative to nginx prefix - # $ngx_prefix/conf/concat.lua contents: - # - # return ngx.arg[1]..ngx.arg[2] - # - set_by_lua_file $res conf/concat.lua $a $b; - echo $res; - } - - location /abs_file_concat { - set $a "fee"; - set $b "baz"; - # absolute script path not modified - set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b; - echo $res; - } - - location /lua_content { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua "ngx.say('Hello,world!')"; - } - - location /nginx_var { - # MIME type determined by default_type: - default_type 'text/plain'; - - # try access /nginx_var?a=hello,world - content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')"; - } - - location /request_body { - # force reading request body (default off) - lua_need_request_body on; - client_max_body_size 50k; - client_body_buffer_size 50k; - - content_by_lua 'ngx.print(ngx.var.request_body)'; - } - - # transparent non-blocking I/O in Lua via subrequests - location /lua { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua ' - local res = ngx.location.capture("/some_other_location") - if res.status == 200 then - ngx.print(res.body) - end'; - } - - # GET /recur?num=5 - location /recur { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua ' - local num = tonumber(ngx.var.arg_num) or 0 - - if num > 50 then - ngx.say("num too big") - return - end - - ngx.say("num is: ", num) - - if num > 0 then - res = ngx.location.capture("/recur?num=" .. tostring(num - 1)) - ngx.print("status=", res.status, " ") - ngx.print("body=", res.body) - else - ngx.say("end") - end - '; - } - - location /foo { - rewrite_by_lua ' - res = ngx.location.capture("/memc", - { args = { cmd = 'incr', key = ngx.var.uri } } - ) - '; - - proxy_pass http://blah.blah.com; - } - - location /blah { - access_by_lua ' - local res = ngx.location.capture("/auth") - - if res.status == ngx.HTTP_OK then - return - end - - if res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - '; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } - - location /mixed { - rewrite_by_lua_file /path/to/rewrite.lua; - access_by_lua_file /path/to/access.lua; - content_by_lua_file /path/to/content.lua; - } - - # use nginx var in code path - # WARN: contents in nginx var must be carefully filtered, - # otherwise there'll be great security risk! - location ~ ^/app/(.+) { - content_by_lua_file /path/to/lua/app/root/$1.lua; - } - - location / { - lua_need_request_body on; - - client_max_body_size 100k; - client_body_buffer_size 100k; - - access_by_lua ' - -- check the client IP address is in our black list - if ngx.var.remote_addr == "132.5.72.3" then - ngx.exit(ngx.HTTP_FORBIDDEN) - end - - -- check if the request body contains bad words - if ngx.var.request_body and - string.match(ngx.var.request_body, "fsck") - then - return ngx.redirect("/terms_of_use.html") - end - - -- tests passed - '; - - # proxy_pass/fastcgi_pass/etc settings - } - } - -Description - This module embeds Lua, via the standard Lua interpreter or LuaJIT, into - Nginx and by leveraging Nginx's subrequests, allows the integration of - the powerful Lua threads (Lua coroutines) into the Nginx event model. - - Unlike Apache's mod_lua - () and Lighttpd's - mod_magnet (), Lua - code executed using this module can be *100% non-blocking* on network - traffic as long as the Nginx API for Lua provided by this module is used - to handle requests to upstream services such as mysql, postgresql, - memcached, redis, or upstream http web services. (See - ngx.location.capture, ngx.location.capture_multi, ngx.socket.tcp, - [[HttpDrizzleModule]], ngx_postgres - (), [[HttpMemcModule]], - [[HttpRedis2Module]] and [[HttpProxyModule]] modules for details). - - The Lua interpreter or LuaJIT instance is shared across all the requests - in a single nginx worker process but request contexts are segregated - using lightweight Lua coroutines. Loaded Lua modules persist in the - nginx worker process level resulting in a small memory footprint even - when under heavy loads. - -Directives - lua_code_cache - syntax: *lua_code_cache on | off* - - default: *lua_code_cache on* - - context: *main, server, location, location if* - - Enables or disables the Lua code cache for set_by_lua_file, - content_by_lua_file, rewrite_by_lua_file, and access_by_lua_file, and - also force Lua module reloading on a per-request basis. - - The Lua files referenced in set_by_lua_file, content_by_lua_file, - access_by_lua_file, and rewrite_by_lua_file will not be cached and the - Lua "package.loaded" table will be cleared at the entry point of every - request (such that Lua modules will not be cached either). With this in - place, developers can adopt an edit-and-refresh approach. - - Please note however, that Lua code written inline within nginx.conf such - as those specified by set_by_lua, content_by_lua, access_by_lua, and - rewrite_by_lua will *always* be cached because only the Nginx config - file parser can correctly parse the "nginx.conf" file and the only ways - to to reload the config file are to send a "HUP" signal or to restart - Nginx. - - The "ngx_lua" module does not currently support the "stat" mode - available with the Apache "mod_lua" module but this is planned for - implementation in the future. - - Disabling the Lua code cache is strongly discouraged for production use - and should only be used during development as it has a significant - negative impact on overall performance. In addition, race conditions - when reloading Lua modules are common for concurrent requests when the - code cache is disabled. - - lua_regex_cache_max_entries - syntax: *lua_regex_cache_max_entries * - - default: *lua_regex_cache_max_entries 1024* - - context: *http* - - Specifies the maximum number of entries allowed in the worker process - level compiled regex cache. - - The regular expressions used in ngx.re.match, ngx.re.gmatch, ngx.re.sub, - and ngx.re.gsub will be cached within this cache if the regex option "o" - (i.e., compile-once flag) is specified. - - The default number of entries allowed is 1024 and when this limit is - reached, new regular expressions will not be cached (as if the "o" - option was not specified) and there will be one, and only one, warning - in the "error.log" file: - - 2011/08/27 23:18:26 [warn] 31997#0: *1 lua exceeding regex cache max entries (1024), ... - - Do not activate the "o" option for regular expressions (and/or "replace" - string arguments for ngx.re.sub and ngx.re.gsub) that are generated *on - the fly* and give rise to infinite variations to avoid hitting the - specified limit. - - lua_package_path - syntax: *lua_package_path * - - default: *The content of LUA_PATH environ variable or Lua's compiled-in - defaults.* - - context: *main* - - Sets the Lua module search path used by scripts specified by set_by_lua, - content_by_lua and others. The path string is in standard Lua path form, - and ";;" can be used to stand for the original search paths. - - As from the "v0.5.0rc29" release, the special notation $prefix or - "${prefix}" can be used in the search path string to indicate the path - of the "server prefix" usually determined by the "-p PATH" command-line - option while starting the Nginx server. - - lua_package_cpath - syntax: *lua_package_cpath * - - default: *The content of LUA_CPATH environment variable or Lua's - compiled-in defaults.* - - context: *main* - - Sets the Lua C-module search path used by scripts specified by - set_by_lua, content_by_lua and others. The cpath string is in standard - Lua cpath form, and ";;" can be used to stand for the original cpath. - - As from the "v0.5.0rc29" release, the special notation $prefix or - "${prefix}" can be used in the search path string to indicate the path - of the "server prefix" usually determined by the "-p PATH" command-line - option while starting the Nginx server. - - init_by_lua - syntax: *init_by_lua * - - context: *http* - - phase: *loading-config* - - Runs the Lua code specified by the argument "" on the - global Lua VM level when the Nginx master process (if any) is loading - the Nginx config file. - - When Nginx receives the "HUP" signal and starts reloading the config - file, the Lua VM will also be re-created and "init_by_lua" will run - again on the new Lua VM. - - Usually you can register (true) Lua global variables or pre-load Lua - modules at server start-up by means of this hook. Here is an example for - pre-loading Lua modules: - - init_by_lua 'require "cjson"'; - - server { - location = /api { - content_by_lua ' - ngx.say(cjson.encode({dog = 5, cat = 6})) - '; - } - } - - You can also initialize the lua_shared_dict shm storage at this phase. - Here is an example for this: - - lua_shared_dict dogs 1m; - - init_by_lua ' - local dogs = ngx.shared.dogs; - dogs:set("Tom", 56) - '; - - server { - location = /api { - content_by_lua ' - local dogs = ngx.shared.dogs; - ngx.say(dogs:get("Tom")) - '; - } - } - - But note that, the lua_shared_dict's shm storage will not be cleared - through a config reload (via the "HUP" signal, for example). So if you - do *not* want to re-initialize the shm storage in your "init_by_lua" - code in this case, then you just need to set a custom flag in the shm - storage and always check the flag in your "init_by_lua" code. - - Because the Lua code in this context runs before Nginx forks its worker - processes (if any), data or code loaded here will enjoy the - Copy-on-write (COW) () - feature provided by many operating systems among all the worker - processes, thus saving a lot of memory. - - Only a small set of the Nginx API for Lua is supported in this context: - - * Logging APIs: ngx.log and print, - - * Shared Dictionary API: ngx.shared.DICT. - - More Nginx APIs for Lua may be supported in this context upon future - user requests. - - Basically you can safely use Lua libraries that do blocking I/O in this - very context because blocking the master process during server start-up - is completely okay. Even the Nginx core does blocking I/O (at least on - resolving upstream's host names) at the configure-loading phase. - - You should be very careful about potential security vulnerabilities in - your Lua code registered in this context because the Nginx master - process is often run under the "root" account. - - This directive was first introduced in the "v0.5.5" release. - - init_by_lua_file - syntax: *init_by_lua_file * - - context: *http* - - phase: *loading-config* - - Equivalent to init_by_lua, except that the file specified by - "" contains the Lua code or Lua/LuaJIT bytecode - to be executed. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - This directive was first introduced in the "v0.5.5" release. - - set_by_lua - syntax: *set_by_lua $res [$arg1 $arg2 ...]* - - context: *server, server if, location, location if* - - phase: *server-rewrite, rewrite* - - Executes code specified in "" with optional input - arguments "$arg1 $arg2 ...", and returns string output to $res. The code - in "" can make API calls and can retrieve input - arguments from the "ngx.arg" table (index starts from 1 and increases - sequentially). - - This directive is designed to execute short, fast running code blocks as - the Nginx event loop is blocked during code execution. Time consuming - code sequences should therefore be avoided. - - Note that the following API functions are currently disabled within this - context: - - * Output API functions (e.g., ngx.say and ngx.send_headers) - - * Control API functions (e.g., ngx.exit) - - * Subrequest API functions (e.g., ngx.location.capture and - ngx.location.capture_multi) - - * Cosocket API functions (e.g., ngx.socket.tcp and ngx.req.socket). - - In addition, note that this directive can only write out a value to a - single Nginx variable at a time. However, a workaround is possible using - the ngx.var.VARIABLE interface. - - location /foo { - set $diff ''; # we have to predefine the $diff variable here - - set_by_lua $sum ' - local a = 32 - local b = 56 - - ngx.var.diff = a - b; -- write to $diff directly - return a + b; -- return the $sum value normally - '; - - echo "sum = $sum, diff = $diff"; - } - - This directive can be freely mixed with all directives of the - [[HttpRewriteModule]], [[HttpSetMiscModule]], and [[HttpArrayVarModule]] - modules. All of these directives will run in the same order as they - appear in the config file. - - set $foo 32; - set_by_lua $bar 'tonumber(ngx.var.foo) + 1'; - set $baz "bar: $bar"; # $baz == "bar: 33" - - As from the "v0.5.0rc29" release, Nginx variable interpolation is - disabled in the "" argument of this directive and - therefore, the dollar sign character ("$") can be used directly. - - This directive requires the ngx_devel_kit - () module. - - set_by_lua_file - syntax: *set_by_lua_file $res [$arg1 $arg2 - ...]* - - context: *server, server if, location, location if* - - phase: *server-rewrite, rewrite* - - Equivalent to set_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - Nginx variable interpolation is supported in the - "" argument string of this directive. But - special care must be taken for injection attacks. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - When the Lua code cache is turned on (by default), the user code is - loaded once at the first request and cached and the Nginx config must be - reloaded each time the Lua source file is modified. The Lua code cache - can be temporarily disabled during development by switching - lua_code_cache "off" in "nginx.conf" to avoid reloading Nginx. - - This directive requires the ngx_devel_kit - () module. - - content_by_lua - syntax: *content_by_lua * - - context: *location, location if* - - phase: *content* - - Acts as a "content handler" and executes Lua code string specified in - "" for every request. The Lua code may make API calls - and is executed as a new spawned coroutine in an independent global - environment (i.e. a sandbox). - - Do not use this directive and other content handler directives in the - same location. For example, this directive and the proxy_pass directive - should not be used in the same location. - - content_by_lua_file - syntax: *content_by_lua_file * - - context: *location, location if* - - phase: *content* - - Equivalent to content_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - Nginx variables can be used in the "" string to - provide flexibility. This however carries some risks and is not - ordinarily recommended. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - When the Lua code cache is turned on (by default), the user code is - loaded once at the first request and cached and the Nginx config must be - reloaded each time the Lua source file is modified. The Lua code cache - can be temporarily disabled during development by switching - lua_code_cache "off" in "nginx.conf" to avoid reloading Nginx. - - rewrite_by_lua - syntax: *rewrite_by_lua * - - context: *http, server, location, location if* - - phase: *rewrite tail* - - Acts as a rewrite phase handler and executes Lua code string specified - in "" for every request. The Lua code may make API calls - and is executed as a new spawned coroutine in an independent global - environment (i.e. a sandbox). - - Note that this handler always runs *after* the standard - [[HttpRewriteModule]]. So the following will work as expected: - - location /foo { - set $a 12; # create and initialize $a - set $b ""; # create and initialize $b - rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1'; - echo "res = $b"; - } - - because "set $a 12" and "set $b """ run *before* rewrite_by_lua. - - On the other hand, the following will not work as expected: - - ? location /foo { - ? set $a 12; # create and initialize $a - ? set $b ''; # create and initialize $b - ? rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1'; - ? if ($b = '13') { - ? rewrite ^ /bar redirect; - ? break; - ? } - ? - ? echo "res = $b"; - ? } - - because "if" runs *before* rewrite_by_lua even if it is placed after - rewrite_by_lua in the config. - - The right way of doing this is as follows: - - location /foo { - set $a 12; # create and initialize $a - set $b ''; # create and initialize $b - rewrite_by_lua ' - ngx.var.b = tonumber(ngx.var.a) + 1 - if tonumber(ngx.var.b) == 13 then - return ngx.redirect("/bar"); - end - '; - - echo "res = $b"; - } - - Note that the ngx_eval () - module can be approximated by using rewrite_by_lua. For example, - - location / { - eval $res { - proxy_pass http://foo.com/check-spam; - } - - if ($res = 'spam') { - rewrite ^ /terms-of-use.html redirect; - } - - fastcgi_pass ...; - } - - can be implemented in "ngx_lua" as: - - location = /check-spam { - internal; - proxy_pass http://foo.com/check-spam; - } - - location / { - rewrite_by_lua ' - local res = ngx.location.capture("/check-spam") - if res.body == "spam" then - ngx.redirect("/terms-of-use.html") - end - '; - - fastcgi_pass ...; - } - - Just as any other rewrite phase handlers, rewrite_by_lua also runs in - subrequests. - - Note that when calling "ngx.exit(ngx.OK)" within a rewrite_by_lua - handler, the nginx request processing control flow will still continue - to the content handler. To terminate the current request from within a - rewrite_by_lua handler, calling ngx.exit with status >= 200 - ("ngx.HTTP_OK") and status < 300 ("ngx.HTTP_SPECIAL_RESPONSE") for - successful quits and "ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)" (or its - friends) for failures. - - If the [[HttpRewriteModule]]'s rewrite directive is used to change the - URI and initiate location re-lookups (internal redirections), then any - rewrite_by_lua or rewrite_by_lua_file code sequences within the current - location will not be executed. For example, - - location /foo { - rewrite ^ /bar; - rewrite_by_lua 'ngx.exit(503)'; - } - location /bar { - ... - } - - Here the Lua code "ngx.exit(503)" will never run. This will be the case - if "rewrite ^ /bar last" is used as this will similarly initiate an - internal redirection. If the "break" modifier is used instead, there - will be no internal redirection and the "rewrite_by_lua" code will be - executed. - - The "rewrite_by_lua" code will always run at the end of the "rewrite" - request-processing phase unless rewrite_by_lua_no_postpone is turned on. - - rewrite_by_lua_file - syntax: *rewrite_by_lua_file * - - context: *http, server, location, location if* - - phase: *rewrite tail* - - Equivalent to rewrite_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - Nginx variables can be used in the "" string to - provide flexibility. This however carries some risks and is not - ordinarily recommended. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - When the Lua code cache is turned on (by default), the user code is - loaded once at the first request and cached and the Nginx config must be - reloaded each time the Lua source file is modified. The Lua code cache - can be temporarily disabled during development by switching - lua_code_cache "off" in "nginx.conf" to avoid reloading Nginx. - - The "rewrite_by_lua_file" code will always run at the end of the - "rewrite" request-processing phase unless rewrite_by_lua_no_postpone is - turned on. - - access_by_lua - syntax: *access_by_lua * - - context: *http, server, location, location if* - - phase: *access tail* - - Acts as an access phase handler and executes Lua code string specified - in "" for every request. The Lua code may make API calls - and is executed as a new spawned coroutine in an independent global - environment (i.e. a sandbox). - - Note that this handler always runs *after* the standard - [[HttpAccessModule]]. So the following will work as expected: - - location / { - deny 192.168.1.1; - allow 192.168.1.0/24; - allow 10.1.1.0/16; - deny all; - - access_by_lua ' - local res = ngx.location.capture("/mysql", { ... }) - ... - '; - - # proxy_pass/fastcgi_pass/... - } - - That is, if a client IP address is in the blacklist, it will be denied - before the MySQL query for more complex authentication is executed by - access_by_lua. - - Note that the ngx_auth_request - () module can be - approximated by using access_by_lua: - - location / { - auth_request /auth; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } - - can be implemented in "ngx_lua" as: - - location / { - access_by_lua ' - local res = ngx.location.capture("/auth") - - if res.status == ngx.HTTP_OK then - return - end - - if res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - '; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } - - As with other access phase handlers, access_by_lua will *not* run in - subrequests. - - Note that when calling "ngx.exit(ngx.OK)" within a access_by_lua - handler, the nginx request processing control flow will still continue - to the content handler. To terminate the current request from within a - access_by_lua handler, calling ngx.exit with status >= 200 - ("ngx.HTTP_OK") and status < 300 ("ngx.HTTP_SPECIAL_RESPONSE") for - successful quits and "ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)" (or its - friends) for failures. - - access_by_lua_file - syntax: *access_by_lua_file * - - context: *http, server, location, location if* - - phase: *access tail* - - Equivalent to access_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - Nginx variables can be used in the "" string to - provide flexibility. This however carries some risks and is not - ordinarily recommended. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - When the Lua code cache is turned on (by default), the user code is - loaded once at the first request and cached and the Nginx config must be - reloaded each time the Lua source file is modified. The Lua code cache - can be temporarily disabled during development by switching - lua_code_cache "off" in "nginx.conf" to avoid repeatedly reloading - Nginx. - - header_filter_by_lua - syntax: *header_filter_by_lua * - - context: *http, server, location, location if* - - phase: *output-header-filter* - - Uses Lua code specified in "" to define an output header - filter. - - Note that the following API functions are currently disabled within this - context: - - * Output API functions (e.g., ngx.say and ngx.send_headers) - - * Control API functions (e.g., ngx.exit and ngx.exec) - - * Subrequest API functions (e.g., ngx.location.capture and - ngx.location.capture_multi) - - * Cosocket API functions (e.g., ngx.socket.tcp and ngx.req.socket). - - Here is an example of overriding a response header (or adding one if - absent) in our Lua header filter: - - location / { - proxy_pass http://mybackend; - header_filter_by_lua 'ngx.header.Foo = "blah"'; - } - - This directive was first introduced in the "v0.2.1rc20" release. - - header_filter_by_lua_file - syntax: *header_filter_by_lua_file * - - context: *http, server, location, location if* - - phase: *output-header-filter* - - Equivalent to header_filter_by_lua, except that the file specified by - "" contains the Lua code, or as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - This directive was first introduced in the "v0.2.1rc20" release. - - body_filter_by_lua - syntax: *body_filter_by_lua * - - context: *http, server, location, location if* - - phase: *output-body-filter* - - Uses Lua code specified in "" to define an output body - filter. - - The input data chunk is passed via ngx.arg[1] (as a Lua string value) - and the "eof" flag indicating the end of the response body data stream - is passed via ngx.arg[2] (as a Lua boolean value). - - Behind the scene, the "eof" flag is just the "last_buf" flag of the - nginx chain link buffers. And in the context of an Nginx subrequest, - there is no "eof" flag at all, due to the underlying limitation in the - Nginx core. - - The output data stream can be aborted immediately by running the - following Lua statement: - - return ngx.ERROR - - This will truncate the response body and usually result in incomplete - and also invalid responses. - - The Lua code can pass its own modified version of the input data chunk - to the downstream Nginx output body filters by overriding ngx.arg[1] - with a Lua string or a Lua table of strings. For example, to transform - all the lowercase letters in the response body, we can just write: - - location / { - proxy_pass http://mybackend; - body_filter_by_lua 'ngx.arg[1] = string.upper(ngx.arg[1])'; - } - - When setting "nil" or an empty Lua string value to "ngx.arg[1]", no data - chunk will be passed to the downstream Nginx output filters at all. - - Likewise, new "eof" flag can also be specified by setting a boolean - value to ngx.arg[2]. For example, - - location /t { - echo hello world; - echo hiya globe; - - body_filter_by_lua ' - local chunk = ngx.arg[1] - if string.match(chunk, "hello") then - ngx.arg[2] = true -- new eof - return - end - - -- just throw away any remaining chunk data - ngx.arg[1] = nil - '; - } - - Then "GET /t" will just return the output - - hello world - - That is, when the body filter sees a chunk containing the word "hello", - then it will set the "eof" flag to true immediately, resulting in - truncated but still valid responses. - - When the Lua code may change the length of the response body, then it is - required to always clear out the "Content-Length" response header (if - any) in a header filter to enforce streaming output, as in - - location /foo { - # fastcgi_pass/proxy_pass/... - - header_filter_by_lua 'ngx.header.content_length = nil'; - body_filter_by_lua 'ngx.arg[1] = {string.len(arg[1]), "\n"}' - } - - Note that the following API functions are currently disabled within this - context: - - * Output API functions (e.g., ngx.say and ngx.send_headers) - - * Control API functions (e.g., ngx.exit and ngx.exec) - - * Subrequest API functions (e.g., ngx.location.capture and - ngx.location.capture_multi) - - * Cosocket API functions (e.g., ngx.socket.tcp and ngx.req.socket). - - Nginx output filters may be called multiple times for a single request - because response body may be delivered in chunks. Thus, the Lua code - specified by in this directive may also run multiple times in the - lifetime of a single HTTP request. - - This directive was first introduced in the "v0.5.0rc32" release. - - body_filter_by_lua_file - syntax: *body_filter_by_lua_file * - - context: *http, server, location, location if* - - phase: *output-body-filter* - - Equivalent to body_filter_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - This directive was first introduced in the "v0.5.0rc32" release. - - log_by_lua - syntax: *log_by_lua * - - context: *http, server, location, location if* - - phase: *log* - - Run the Lua source code inlined as the "" at the "log" - request processing phase. This does not replace the current access logs, - but runs after. - - Note that the following API functions are currently disabled within this - context: - - * Output API functions (e.g., ngx.say and ngx.send_headers) - - * Control API functions (e.g., ngx.exit) - - * Subrequest API functions (e.g., ngx.location.capture and - ngx.location.capture_multi) - - * Cosocket API functions (e.g., ngx.socket.tcp and ngx.req.socket). - - Here is an example of gathering average data for - $upstream_response_time: - - lua_shared_dict log_dict 5M; - - server { - location / { - proxy_pass http://mybackend; - - log_by_lua ' - local log_dict = ngx.shared.log_dict - local upstream_time = tonumber(ngx.var.upstream_response_time) - - local sum = log_dict:get("upstream_time-sum") or 0 - sum = sum + upstream_time - log_dict:set("upstream_time-sum", sum) - - local newval, err = log_dict:incr("upstream_time-nb", 1) - if not newval and err == "not found" then - log_dict:add("upstream_time-nb", 0) - log_dict:incr("upstream_time-nb", 1) - end - '; - } - - location = /status { - content_by_lua ' - local log_dict = ngx.shared.log_dict - local sum = log_dict:get("upstream_time-sum") - local nb = log_dict:get("upstream_time-nb") - - if nb and sum then - ngx.say("average upstream response time: ", sum / nb, - " (", nb, " reqs)") - else - ngx.say("no data yet") - end - '; - } - } - - This directive was first introduced in the "v0.5.0rc31" release. - - log_by_lua_file - syntax: *log_by_lua_file * - - context: *http, server, location, location if* - - phase: *log* - - Equivalent to log_by_lua, except that the file specified by - "" contains the Lua code, or, as from the - "v0.5.0rc32" release, the Lua/LuaJIT bytecode to be executed. - - When a relative path like "foo/bar.lua" is given, they will be turned - into the absolute path relative to the "server prefix" path determined - by the "-p PATH" command-line option while starting the Nginx server. - - This directive was first introduced in the "v0.5.0rc31" release. - - lua_need_request_body - syntax: *lua_need_request_body * - - default: *off* - - context: *main | server | location* - - phase: *depends on usage* - - Determines whether to force the request body data to be read before - running rewrite/access/access_by_lua* or not. The Nginx core does not - read the client request body by default and if request body data is - required, then this directive should be turned "on" or the - ngx.req.read_body function should be called within the Lua code. - - To read the request body data within the $request_body variable, - client_body_buffer_size must have the same value as - client_max_body_size. Because when the content length exceeds - client_body_buffer_size but less than client_max_body_size, Nginx will - automatically buffer the data into a temporary file on the disk, which - will lead to empty value in the $request_body variable. - - If the current location includes rewrite_by_lua or rewrite_by_lua_file - directives, then the request body will be read just before the - rewrite_by_lua or rewrite_by_lua_file code is run (and also at the - "rewrite" phase). Similarly, if only content_by_lua is specified, the - request body will not be read until the content handler's Lua code is - about to run (i.e., the request body will be read during the content - phase). - - It is recommended however, to use the ngx.req.read_body and - ngx.req.discard_body functions for finer control over the request body - reading process instead. - - This also applies to access_by_lua and access_by_lua_file. - - lua_shared_dict - syntax: *lua_shared_dict * - - default: *no* - - context: *http* - - phase: *depends on usage* - - Declares a shared memory zone, "", to serve as storage for the shm - based Lua dictionary "ngx.shared.". - - The "" argument accepts size units such as "k" and "m": - - http { - lua_shared_dict dogs 10m; - ... - } - - See ngx.shared.DICT for details. - - This directive was first introduced in the "v0.3.1rc22" release. - - lua_socket_connect_timeout - syntax: *lua_socket_connect_timeout