diff --git a/src/deps/src/lua-nginx-module/.travis.yml b/src/deps/src/lua-nginx-module/.travis.yml index d6742ed52..6033ee185 100644 --- a/src/deps/src/lua-nginx-module/.travis.yml +++ b/src/deps/src/lua-nginx-module/.travis.yml @@ -43,7 +43,7 @@ env: - LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1 - LUA_INCLUDE_DIR=$LUAJIT_INC - PCRE_VER=8.45 - - PCRE2_VER=10.37 + - PCRE2_VER=10.42 - PCRE_PREFIX=/opt/pcre - PCRE2_PREFIX=/opt/pcre2 - PCRE_LIB=$PCRE_PREFIX/lib @@ -64,8 +64,8 @@ env: #- NGINX_VERSION=1.21.4 OPENSSL_VER=1.1.0l OPENSSL_PATCH_VER=1.1.0d #- NGINX_VERSION=1.25.1 OPENSSL_VER=1.1.0l OPENSSL_PATCH_VER=1.1.0d - NGINX_VERSION=1.21.4 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f - - NGINX_VERSION=1.25.1 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f USE_PCRE2=Y - - NGINX_VERSION=1.25.1 BORINGSSL=1 TEST_NGINX_USE_HTTP3=1 USE_PCRE2=Y + - NGINX_VERSION=1.27.0 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f USE_PCRE2=Y TEST_NGINX_TIMEOUT=5 + - NGINX_VERSION=1.27.0 BORINGSSL=1 TEST_NGINX_USE_HTTP3=1 USE_PCRE2=Y TEST_NGINX_QUIC_IDLE_TIMEOUT=3 #- NGINX_VERSION=1.25.1 OPENSSL_VER=1.1.1w TEST_NGINX_USE_HTTP2=1 services: @@ -81,7 +81,7 @@ before_install: 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 [ "$USE_PCRE2" != "Y" ] && [ ! -f download-cache/pcre-$PCRE_VER.tar.gz ]; then wget -P download-cache https://downloads.sourceforge.net/project/pcre/pcre/${PCRE_VER}/pcre-${PCRE_VER}.tar.gz; fi - - if [ "$USE_PCRE2" = "Y" ] && [ ! -f download-cache/pcre2-$PCRE2_VER.tar.gz ]; then wget -P download-cache https://downloads.sourceforge.net/project/pcre/pcre2/${PCRE2_VER}/pcre2-${PCRE2_VER}.tar.gz; fi + - if [ "$USE_PCRE2" = "Y" ] && [ ! -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://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 - if [ -n "$OPENSSL_VER" ] && [ ! -f download-cache/openssl-$OPENSSL_VER.tar.gz ]; then 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 diff --git a/src/deps/src/lua-nginx-module/README.markdown b/src/deps/src/lua-nginx-module/README.markdown index d6ec8c94b..29a81c1ca 100644 --- a/src/deps/src/lua-nginx-module/README.markdown +++ b/src/deps/src/lua-nginx-module/README.markdown @@ -966,7 +966,6 @@ TODO * cosocket: add support in the context of [init_by_lua*](#init_by_lua). * cosocket: review and merge aviramc's [patch](https://github.com/openresty/lua-nginx-module/pull/290) for adding the `bsdrecv` method. * cosocket: add configure options for different strategies of handling the cosocket connection exceeding in the pools. -* review and apply vadim-pavlov's patch for [ngx.location.capture](#ngxlocationcapture)'s `extra_headers` option * use `ngx_hash_t` to optimize the built-in header look-up process for [ngx.req.set_header](#ngxreqset_header), and etc. * add `ignore_resp_headers`, `ignore_resp_body`, and `ignore_resp` options to [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi) methods, to allow micro performance tuning on the user side. * add automatic Lua code time slicing support by yielding and resuming the Lua VM actively via Lua's debug hooks. @@ -1012,7 +1011,7 @@ The order in which these modules are added during configuration is important bec filtering chain determines the final output, for example. The correct adding order is shown above. * 3rd-party Lua libraries: - * [lua-cjson](http://www.kyne.com.au/~mark/software/lua-cjson.php) + * [lua-cjson](https://www.kyne.au/~mark/software/lua-cjson.php) * Applications: * mysql: create database 'ngx_test', grant all privileges to user 'ngx_test', password is 'ngx_test' @@ -1144,6 +1143,7 @@ Directives * [log_by_lua_file](#log_by_lua_file) * [balancer_by_lua_block](#balancer_by_lua_block) * [balancer_by_lua_file](#balancer_by_lua_file) +* [balancer_keepalive](#balancer_keepalive) * [lua_need_request_body](#lua_need_request_body) * [ssl_client_hello_by_lua_block](#ssl_client_hello_by_lua_block) * [ssl_client_hello_by_lua_file](#ssl_client_hello_by_lua_file) @@ -2711,6 +2711,29 @@ This directive was first introduced in the `v0.10.0` release. [Back to TOC](#directives) +balancer_keepalive +------------------ + +**syntax:** *balancer_keepalive <total-connections>* + +**context:** *upstream* + +**phase:** *loading-config* + +The `total-connections` parameter sets the maximum number of idle +keepalive connections to upstream servers that are preserved in the cache of +each worker process. When this number is exceeded, the least recently used +connections are closed. + +It should be particularly noted that the keepalive directive does not limit the +total number of connections to upstream servers that an nginx worker process +can open. The connections parameter should be set to a number small enough to +let upstream servers process new incoming connections as well. + +This directive was first introduced in the `v0.10.21` release. + +[Back to TOC](#directives) + lua_need_request_body --------------------- @@ -2722,8 +2745,6 @@ lua_need_request_body **phase:** *depends on usage* -Due to the stream processing feature of HTTP/2 or HTTP/3, this configuration could potentially block the entire request. Therefore, this configuration is effective only when HTTP/2 or HTTP/3 requests send content-length header. For requests with versions lower than HTTP/2, this configuration can still be used without any problems. - Determines whether to force the request body data to be read before running rewrite/access/content_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](#ngxreqread_body) function should be called within the Lua code. To read the request body data within the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable, @@ -3601,7 +3622,7 @@ lua_worker_thread_vm_pool_size **syntax:** *lua_worker_thread_vm_pool_size <size>* -**default:** *lua_worker_thread_vm_pool_size 100* +**default:** *lua_worker_thread_vm_pool_size 10* **context:** *http* @@ -3613,6 +3634,8 @@ The Lua VM in the VM pool is used to execute Lua code in separate thread. The pool is global at Nginx worker level. And it is used to reuse Lua VMs between requests. +**Warning:** Each worker thread uses a separate Lua VM and caches the Lua VM for reuse in subsequent operations. Configuring too many worker threads can result in consuming a lot of memory. + [Back to TOC](#directives) Nginx API for Lua @@ -3717,6 +3740,7 @@ Nginx API for Lua * [ngx.shared.DICT.capacity](#ngxshareddictcapacity) * [ngx.shared.DICT.free_space](#ngxshareddictfree_space) * [ngx.socket.udp](#ngxsocketudp) +* [udpsock:bind](#udpsockbind) * [udpsock:setpeername](#udpsocksetpeername) * [udpsock:send](#udpsocksend) * [udpsock:receive](#udpsockreceive) @@ -4280,6 +4304,8 @@ argument, which supports the options: specify the subrequest's request body (string value only). * `args` specify the subrequest's URI query arguments (both string value and Lua tables are accepted) +* `headers` + specify the subrequest's request headers (Lua table only). this headers will override the original headers of the subrequest. * `ctx` specify a Lua table to be the [ngx.ctx](#ngxctx) table for the subrequest. It can be the current request's [ngx.ctx](#ngxctx) table, which effectively makes the parent and its subrequest to share exactly the same context table. This option was first introduced in the `v0.3.1rc25` release. * `vars` @@ -4431,6 +4457,33 @@ Accessing `/lua` will yield the output dog = hello cat = 32 +The `headers` option can be used to specify the request headers for the subrequest. The value of this option should be a Lua table where the keys are the header names and the values are the header values. For example, + +```lua + +location /foo { + content_by_lua_block { + ngx.print(ngx.var.http_x_test) + } +} + +location /lua { + content_by_lua_block { + local res = ngx.location.capture("/foo", { + headers = { + ["X-Test"] = "aa", + } + }) + ngx.print(res.body) + } +} +``` + +Accessing `/lua` will yield the output + + + aa + The `ctx` option can be used to specify a custom Lua table to serve as the [ngx.ctx](#ngxctx) table for the subrequest. @@ -4788,7 +4841,7 @@ ngx.req.http_version Returns the HTTP version number for the current request as a Lua number. -Current possible values are 2.0, 1.0, 1.1, and 0.9. Returns `nil` for unrecognized values. +Current possible values are 3.0, 2.0, 1.0, 1.1, and 0.9. Returns `nil` for unrecognized values. This method was first introduced in the `v0.7.17` release. @@ -5426,8 +5479,6 @@ Reads the client request body synchronously without blocking the Nginx event loo local args = ngx.req.get_post_args() ``` -Due to the stream processing feature of HTTP/2 or HTTP/3, this api could potentially block the entire request. Therefore, this api is effective only when HTTP/2 or HTTP/3 requests send content-length header. For requests with versions lower than HTTP/2, this api can still be used without any problems. - If the request body is already read previously by turning on [lua_need_request_body](#lua_need_request_body) or by using other modules, then this function does not run and returns immediately. If the request body has already been explicitly discarded, either by the [ngx.req.discard_body](#ngxreqdiscard_body) function or other modules, this function does not run and returns immediately. @@ -5512,6 +5563,8 @@ If the request body has been read into memory, try calling the [ngx.req.get_body To force in-file request bodies, try turning on [client_body_in_file_only](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_in_file_only). +Note that this function is also work for balancer phase but it needs to call [balancer.recreate_request](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request) to make the change take effect after set the request body data or headers. + This function was first introduced in the `v0.3.1rc17` release. See also [ngx.req.get_body_data](#ngxreqget_body_data). @@ -5523,7 +5576,7 @@ ngx.req.set_body_data **syntax:** *ngx.req.set_body_data(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*,* Set the current request's request body using the in-memory data specified by the `data` argument. @@ -5531,6 +5584,8 @@ If the request body has not been read yet, call [ngx.req.read_body](#ngxreqread_ Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively. +Note that this function is also work for balancer phase but it needs to call [balancer.recreate_request](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request) to make the change take effect after set the request body data or headers. + This function was first introduced in the `v0.3.1rc18` release. See also [ngx.req.set_body_file](#ngxreqset_body_file). @@ -5542,7 +5597,7 @@ ngx.req.set_body_file **syntax:** *ngx.req.set_body_file(file_name, auto_clean?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*,* Set the current request's request body using the in-file data specified by the `file_name` argument. @@ -5643,7 +5698,7 @@ Returns a read-only cosocket object that wraps the downstream connection. Only [ In case of error, `nil` will be returned as well as a string describing the error. -Due to the streaming nature of HTTP2 and HTTP3, this API cannot be used when the downstream connection is HTTP2 and HTTP3. +**Note:** This method will block while waiting for client request body to be fully received. Block time depends on the [client_body_timeout](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout) directive and maximum body size specified by the [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. If read timeout occurs or client body size exceeds the defined limit, this function will not return and `408 Request Time-out` or `413 Request Entity Too Large` response will be returned to the client instead. The socket object returned by this method is usually used to read the current request's body in a streaming fashion. Do not turn on the [lua_need_request_body](#lua_need_request_body) directive, and do not mix this call with [ngx.req.read_body](#ngxreqread_body) and [ngx.req.discard_body](#ngxreqdiscard_body). @@ -7526,6 +7581,7 @@ ngx.socket.udp Creates and returns a UDP or datagram-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: +* [bind](#udpsockbind) * [setpeername](#udpsocksetpeername) * [send](#udpsocksend) * [receive](#udpsockreceive) @@ -7540,6 +7596,36 @@ See also [ngx.socket.tcp](#ngxsockettcp). [Back to TOC](#nginx-api-for-lua) +udpsock:bind +------------ +**syntax:** *ok, err = udpsock:bind(address)* + +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*,ssl_session_fetch_by_lua*,ssl_client_hello_by_lua** + +Just like the standard [proxy_bind](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_bind) directive, this api makes the outgoing connection to a upstream server originate from the specified local IP address. + +Only IP addresses can be specified as the `address` argument. + +Here is an example for connecting to a TCP server from the specified local IP address: + +```nginx + + location /test { + content_by_lua_block { + local sock = ngx.socket.udp() + -- assume "192.168.1.10" is the local ip address + local ok, err = sock:bind("192.168.1.10") + if not ok then + ngx.say("failed to bind: ", err) + return + end + sock:close() + } + } +``` + +[Back to TOC](#nginx-api-for-lua) + udpsock:setpeername ------------------- @@ -7916,11 +8002,11 @@ Set client certificate chain and corresponding private key to the TCP socket obj The certificate chain and private key provided will be used later by the [tcpsock:sslhandshake](#tcpsocksslhandshake) method. * `cert` specify a client certificate chain cdata object that will be used while handshaking with -remote server. These objects can be created using [ngx.ssl.parse\_pem\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert) +remote server. These objects can be created using [ngx.ssl.parse\_pem\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert) or [ngx.ssl.parse\_der\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_der_cert) function provided by lua-resty-core. Note that specifying the `cert` option requires corresponding `pkey` be provided too. See below. * `pkey` specify a private key corresponds to the `cert` option above. -These objects can be created using [ngx.ssl.parse\_pem\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_priv_key) +These objects can be created using [ngx.ssl.parse\_pem\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_priv_key) or [ngx.ssl.parse\_der\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_der_priv_key) function provided by lua-resty-core. If both of `cert` and `pkey` are `nil`, this method will clear any existing client certificate and private key diff --git a/src/deps/src/lua-nginx-module/config b/src/deps/src/lua-nginx-module/config index 0e572c8be..24ebd126d 100644 --- a/src/deps/src/lua-nginx-module/config +++ b/src/deps/src/lua-nginx-module/config @@ -289,6 +289,7 @@ HTTP_LUA_SRCS=" \ $ngx_addon_dir/src/ngx_http_lua_worker.c \ $ngx_addon_dir/src/ngx_http_lua_ssl_client_helloby.c \ $ngx_addon_dir/src/ngx_http_lua_ssl_certby.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_export_keying_material.c \ $ngx_addon_dir/src/ngx_http_lua_ssl_ocsp.c \ $ngx_addon_dir/src/ngx_http_lua_lex.c \ $ngx_addon_dir/src/ngx_http_lua_balancer.c \ @@ -354,6 +355,7 @@ HTTP_LUA_DEPS=" \ $ngx_addon_dir/src/ngx_http_lua_ssl_certby.h \ $ngx_addon_dir/src/ngx_http_lua_lex.h \ $ngx_addon_dir/src/ngx_http_lua_balancer.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl_export_keying_material.h \ $ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.h \ $ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.h \ $ngx_addon_dir/src/ngx_http_lua_ssl.h \ @@ -460,7 +462,8 @@ ngx_feature_libs= ngx_feature_name="NGX_HTTP_LUA_HAVE_SIGNALFD" ngx_feature_run=no ngx_feature_incs="#include " -ngx_feature_test="sigset_t set; signalfd(-1, &set, SFD_NONBLOCK|SFD_CLOEXEC);" +ngx_feature_test="sigset_t set = { 0 }; + signalfd(-1, &set, SFD_NONBLOCK|SFD_CLOEXEC);" SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" CC_TEST_FLAGS="-Werror -Wall $CC_TEST_FLAGS" diff --git a/src/deps/src/lua-nginx-module/doc/HttpLuaModule.wiki b/src/deps/src/lua-nginx-module/doc/HttpLuaModule.wiki index 305626c76..a0e6d28fa 100644 --- a/src/deps/src/lua-nginx-module/doc/HttpLuaModule.wiki +++ b/src/deps/src/lua-nginx-module/doc/HttpLuaModule.wiki @@ -2288,6 +2288,26 @@ When a relative path like foo/bar.lua is given, they will be turned This directive was first introduced in the v0.10.0 release. +== balancer_keepalive == + +'''syntax:''' ''balancer_keepalive '' + +'''context:''' ''upstream'' + +'''phase:''' ''loading-config'' + +The total-connections parameter sets the maximum number of idle +keepalive connections to upstream servers that are preserved in the cache of +each worker process. When this number is exceeded, the least recently used +connections are closed. + +It should be particularly noted that the keepalive directive does not limit the +total number of connections to upstream servers that an nginx worker process +can open. The connections parameter should be set to a number small enough to +let upstream servers process new incoming connections as well. + +This directive was first introduced in the v0.10.21 release. + == lua_need_request_body == '''syntax:''' ''lua_need_request_body '' @@ -4637,7 +4657,7 @@ See also [[#ngx.req.get_body_data|ngx.req.get_body_data]]. '''syntax:''' ''ngx.req.set_body_data(data)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*'' Set the current request's request body using the in-memory data specified by the data argument. @@ -4645,6 +4665,8 @@ If the request body has not been read yet, call [[#ngx.req.read_body|ngx.req.rea Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively. +Note that this function is also work for balancer phase but it needs to call [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request balancer.recreate_request] to make the change take effect after set the request body data or headers. + This function was first introduced in the v0.3.1rc18 release. See also [[#ngx.req.set_body_file|ngx.req.set_body_file]]. @@ -4653,7 +4675,7 @@ See also [[#ngx.req.set_body_file|ngx.req.set_body_file]]. '''syntax:''' ''ngx.req.set_body_file(file_name, auto_clean?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, balancer_by_lua*'' Set the current request's request body using the in-file data specified by the file_name argument. @@ -4665,6 +4687,8 @@ Please ensure that the file specified by the file_name argument exi Whether the previous request body has been read into memory or buffered into a disk file, it will be freed or the disk file will be cleaned up immediately, respectively. +Note that this function is also work for balancer phase but it needs to call [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md#recreate_request balancer.recreate_request] to make the change take effect after set the request body data or headers. + This function was first introduced in the v0.3.1rc18 release. See also [[#ngx.req.set_body_data|ngx.req.set_body_data]]. @@ -4741,8 +4765,7 @@ Returns a read-only cosocket object that wraps the downstream connection. Only [ In case of error, nil will be returned as well as a string describing the error. -Due to the streaming nature of HTTP2 and HTTP3, this API cannot be used when the downstream connection is HTTP2 and HTTP3. - +'''Note:''' This method will block while waiting for client request body to be fully received. Block time depends on the [http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout client_body_timeout] directive and maximum body size specified by the [http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size client_max_body_size] directive. If read timeout occurs or client body size exceeds the defined limit, this function will not return and 408 Request Time-out or 413 Request Entity Too Large response will be returned to the client instead. The socket object returned by this method is usually used to read the current request's body in a streaming fashion. Do not turn on the [[#lua_need_request_body|lua_need_request_body]] directive, and do not mix this call with [[#ngx.req.read_body|ngx.req.read_body]] and [[#ngx.req.discard_body|ngx.req.discard_body]]. If any request body data has been pre-read into the Nginx core request header buffer, the resulting cosocket object will take care of this to avoid potential data loss resulting from such pre-reading. diff --git a/src/deps/src/lua-nginx-module/src/api/ngx_http_lua_api.h b/src/deps/src/lua-nginx-module/src/api/ngx_http_lua_api.h index 193c44e3a..4b374f56e 100644 --- a/src/deps/src/lua-nginx-module/src/api/ngx_http_lua_api.h +++ b/src/deps/src/lua-nginx-module/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10026 +#define ngx_http_lua_version 10027 typedef struct ngx_http_lua_co_ctx_s ngx_http_lua_co_ctx_t; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_accessby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_accessby.c index 2bf40aaa8..d40eab123 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_accessby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_accessby.c @@ -137,26 +137,6 @@ ngx_http_lua_access_handler(ngx_http_request_t *r) } if (llcf->force_read_body && !ctx->read_body_done) { - -#if (NGX_HTTP_V2) - if (r->main->stream && r->headers_in.content_length_n < 0) { - ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "disable lua_need_request_body, since " - "http2 read_body may break http2 stream process"); - goto done; - } -#endif - -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30 - && r->headers_in.content_length_n < 0) - { - ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "disable lua_need_request_body, since " - "http2 read_body may break http2 stream process"); - goto done; - } -#endif r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; @@ -174,12 +154,6 @@ ngx_http_lua_access_handler(ngx_http_request_t *r) } } -#if defined(NGX_HTTP_V3) || defined(NGX_HTTP_V2) - -done: - -#endif - dd("calling access handler"); return llcf->access_handler(r); } diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.c index af4da7338..ae0f1380b 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.c @@ -15,10 +15,35 @@ #include "ngx_http_lua_util.h" #include "ngx_http_lua_directive.h" +#define NGX_BALANCER_DEF_HOST_LEN 32 +typedef struct { + ngx_queue_t queue; + ngx_queue_t hnode; + ngx_uint_t hash; + ngx_http_lua_srv_conf_t *lscf; + ngx_connection_t *connection; + socklen_t socklen; + ngx_sockaddr_t sockaddr; + ngx_sockaddr_t local_sockaddr; + ngx_str_t host; + /* try to avoid allocating memory from the connection pool */ + u_char host_data[NGX_BALANCER_DEF_HOST_LEN]; +} ngx_http_lua_balancer_ka_item_t; /*balancer keepalive item*/ + struct ngx_http_lua_balancer_peer_data_s { - /* the round robin data must be first */ - ngx_http_upstream_rr_peer_data_t rrp; + ngx_uint_t keepalive_requests; + ngx_msec_t keepalive_timeout; + + void *data; + + ngx_event_get_peer_pt original_get_peer; + ngx_event_free_peer_pt original_free_peer; + +#if (NGX_HTTP_SSL) + ngx_event_set_peer_session_pt original_set_session; + ngx_event_save_peer_session_pt original_save_session; +#endif ngx_http_lua_srv_conf_t *conf; ngx_http_request_t *request; @@ -28,15 +53,18 @@ struct ngx_http_lua_balancer_peer_data_s { struct sockaddr *sockaddr; socklen_t socklen; + ngx_addr_t *local; - ngx_str_t *host; - in_port_t port; + ngx_str_t host; + ngx_str_t *addr_text; int last_peer_state; #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) - unsigned cloned_upstream_conf; /* :1 */ + unsigned cloned_upstream_conf:1; #endif + + unsigned keepalive:1; }; @@ -45,6 +73,9 @@ static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data); static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data); +static ngx_int_t +ngx_http_lua_upstream_get_ssl_name(ngx_http_request_t *r, + ngx_http_upstream_t *u); #endif static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us); @@ -56,6 +87,18 @@ static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r); static void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state); +static void ngx_http_lua_balancer_notify_peer(ngx_peer_connection_t *pc, + void *data, ngx_uint_t type); +static void ngx_http_lua_balancer_close(ngx_connection_t *c); +static void ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev); +static void ngx_http_lua_balancer_close_handler(ngx_event_t *ev); +static ngx_connection_t *ngx_http_lua_balancer_get_cached_item( + ngx_http_lua_srv_conf_t *lscf, ngx_peer_connection_t *pc, ngx_str_t *name); +static ngx_uint_t ngx_http_lua_balancer_calc_hash(ngx_str_t *name, + struct sockaddr *sockaddr, socklen_t socklen, ngx_addr_t *local); + + +static struct sockaddr *ngx_http_lua_balancer_default_server_sockaddr; ngx_int_t @@ -131,8 +174,10 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, u_char *name; ngx_str_t *value; ngx_http_lua_srv_conf_t *lscf = conf; + ngx_url_t url; ngx_http_upstream_srv_conf_t *uscf; + ngx_http_upstream_server_t *us; dd("enter"); @@ -188,11 +233,42 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, lscf->balancer.src_key = cache_key; + /* balancer setup */ + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + if (uscf->servers->nelts == 0) { + us = ngx_array_push(uscf->servers); + if (us == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(us, sizeof(ngx_http_upstream_server_t)); + ngx_memzero(&url, sizeof(ngx_url_t)); + + ngx_str_set(&url.url, "0.0.0.1"); + url.default_port = 80; + + if (ngx_parse_url(cf->pool, &url) != NGX_OK) { + return NGX_CONF_ERROR; + } + + us->name = url.url; + us->addrs = url.addrs; + us->naddrs = url.naddrs; + + ngx_http_lua_balancer_default_server_sockaddr = us->addrs[0].sockaddr; + } + if (uscf->peer.init_upstream) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "load balancing method redefined"); + + lscf->balancer.original_init_upstream = uscf->peer.init_upstream; + + } else { + lscf->balancer.original_init_upstream = + ngx_http_upstream_init_round_robin; } uscf->peer.init_upstream = ngx_http_lua_balancer_init; @@ -208,16 +284,58 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, static ngx_int_t -ngx_http_lua_balancer_init(ngx_conf_t *cf, - ngx_http_upstream_srv_conf_t *us) +ngx_http_lua_balancer_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { - if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { + ngx_uint_t i; + ngx_uint_t bucket_cnt; + ngx_queue_t *buckets; + ngx_http_lua_srv_conf_t *lscf; + ngx_http_lua_balancer_ka_item_t *cached; + + lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); + + ngx_conf_init_uint_value(lscf->balancer.max_cached, 32); + + if (lscf->balancer.original_init_upstream(cf, us) != NGX_OK) { return NGX_ERROR; } - /* this callback is called upon individual requests */ + lscf->balancer.original_init_peer = us->peer.init; + us->peer.init = ngx_http_lua_balancer_init_peer; + /* allocate cache items and add to free queue */ + + cached = ngx_pcalloc(cf->pool, + sizeof(ngx_http_lua_balancer_ka_item_t) + * lscf->balancer.max_cached); + if (cached == NULL) { + return NGX_ERROR; + } + + ngx_queue_init(&lscf->balancer.cache); + ngx_queue_init(&lscf->balancer.free); + + for (i = 0; i < lscf->balancer.max_cached; i++) { + ngx_queue_insert_head(&lscf->balancer.free, &cached[i].queue); + cached[i].lscf = lscf; + } + + bucket_cnt = lscf->balancer.max_cached / 2; + bucket_cnt = bucket_cnt > 0 ? bucket_cnt : 1; + buckets = ngx_pcalloc(cf->pool, sizeof(ngx_queue_t) * bucket_cnt); + + if (buckets == NULL) { + return NGX_ERROR; + } + + for (i = 0; i < bucket_cnt; i++) { + ngx_queue_init(&buckets[i]); + } + + lscf->balancer.buckets = buckets; + lscf->balancer.bucket_cnt = bucket_cnt; + return NGX_OK; } @@ -226,33 +344,39 @@ static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { - ngx_http_lua_srv_conf_t *bcf; + ngx_http_lua_srv_conf_t *lscf; ngx_http_lua_balancer_peer_data_t *bp; + lscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); + + if (lscf->balancer.original_init_peer(r, us) != NGX_OK) { + return NGX_ERROR; + } + bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); if (bp == NULL) { return NGX_ERROR; } - r->upstream->peer.data = &bp->rrp; - - if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { - return NGX_ERROR; - } + bp->conf = lscf; + bp->request = r; + bp->data = r->upstream->peer.data; + bp->original_get_peer = r->upstream->peer.get; + bp->original_free_peer = r->upstream->peer.free; + r->upstream->peer.data = bp; r->upstream->peer.get = ngx_http_lua_balancer_get_peer; r->upstream->peer.free = ngx_http_lua_balancer_free_peer; + r->upstream->peer.notify = ngx_http_lua_balancer_notify_peer; #if (NGX_HTTP_SSL) + bp->original_set_session = r->upstream->peer.set_session; + bp->original_save_session = r->upstream->peer.save_session; + r->upstream->peer.set_session = ngx_http_lua_balancer_set_session; r->upstream->peer.save_session = ngx_http_lua_balancer_save_session; #endif - bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); - - bp->conf = bcf; - bp->request = r; - return NGX_OK; } @@ -260,25 +384,30 @@ ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) { + void *pdata; lua_State *L; ngx_int_t rc; + ngx_connection_t *c; ngx_http_request_t *r; +#if (NGX_HTTP_SSL) + ngx_http_upstream_t *u; +#endif ngx_http_lua_ctx_t *ctx; ngx_http_lua_srv_conf_t *lscf; - ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_balancer_peer_data_t *bp = data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, - "lua balancer peer, tries: %ui", pc->tries); - - lscf = bp->conf; + "lua balancer: get peer, tries: %ui", pc->tries); r = bp->request; +#if (NGX_HTTP_SSL) + u = r->upstream; +#endif + lscf = bp->conf; ngx_http_lua_assert(lscf->balancer.handler && r); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); - if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { @@ -299,18 +428,18 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) bp->sockaddr = NULL; bp->socklen = 0; bp->more_tries = 0; + bp->keepalive_requests = 0; + bp->keepalive_timeout = 0; + bp->keepalive = 0; bp->total_tries++; - lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - - /* balancer_by_lua does not support yielding and - * there cannot be any conflicts among concurrent requests, - * thus it is safe to store the peer data in the main conf. - */ - lmcf->balancer_peer_data = bp; + pdata = r->upstream->peer.data; + r->upstream->peer.data = bp; rc = lscf->balancer.handler(r, lscf, L); + r->upstream->peer.data = pdata; + if (rc == NGX_ERROR) { return NGX_ERROR; } @@ -332,25 +461,60 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) } } + if (bp->local != NULL) { + pc->local = bp->local; + } + if (bp->sockaddr && bp->socklen) { pc->sockaddr = bp->sockaddr; pc->socklen = bp->socklen; + pc->name = bp->addr_text; pc->cached = 0; pc->connection = NULL; - pc->name = bp->host; - - bp->rrp.peers->single = 0; if (bp->more_tries) { r->upstream->peer.tries += bp->more_tries; } - dd("tries: %d", (int) r->upstream->peer.tries); + if (bp->keepalive) { +#if (NGX_HTTP_SSL) + if (bp->host.len == 0 && u->ssl) { + ngx_http_lua_upstream_get_ssl_name(r, u); + bp->host = u->ssl_name; + } +#endif + + c = ngx_http_lua_balancer_get_cached_item(lscf, pc, &bp->host); + + if (c) { + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: keepalive reusing connection %p," + " host: %V, name: %V", + c, bp->addr_text, &bp->host); + return NGX_DONE; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: keepalive no free connection, " + "host: %V, name: %v", bp->addr_text, &bp->host); + } return NGX_OK; } - return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp); + rc = bp->original_get_peer(pc, bp->data); + if (rc == NGX_ERROR) { + return rc; + } + + if (pc->sockaddr == ngx_http_lua_balancer_default_server_sockaddr) { + ngx_log_error(NGX_LOG_ERR, pc->log, 0, + "lua balancer: no peer set"); + + return NGX_ERROR; + } + + return rc; } @@ -413,10 +577,20 @@ static void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) { - ngx_http_lua_balancer_peer_data_t *bp = data; + ngx_uint_t hash; + ngx_str_t *host; + ngx_queue_t *q; + ngx_connection_t *c; + ngx_http_upstream_t *u; + ngx_http_lua_balancer_ka_item_t *item; + ngx_http_lua_balancer_peer_data_t *bp = data; + ngx_http_lua_srv_conf_t *lscf = bp->conf; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, - "lua balancer free peer, tries: %ui", pc->tries); + "lua balancer: free peer, tries: %ui", pc->tries); + + u = bp->request->upstream; + c = pc->connection; if (bp->sockaddr && bp->socklen) { bp->last_peer_state = (int) state; @@ -425,12 +599,229 @@ ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, pc->tries--; } + if (bp->keepalive) { + if (state & NGX_PEER_FAILED + || c == NULL + || c->read->eof + || c->read->error + || c->read->timedout + || c->write->error + || c->write->timedout) + { + goto invalid; + } + + if (bp->keepalive_requests + && c->requests >= bp->keepalive_requests) + { + goto invalid; + } + + if (!u->keepalive) { + goto invalid; + } + + if (!u->request_body_sent) { + goto invalid; + } + + if (ngx_terminate || ngx_exiting) { + goto invalid; + } + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + goto invalid; + } + + if (ngx_queue_empty(&lscf->balancer.free)) { + q = ngx_queue_last(&lscf->balancer.cache); + + item = ngx_queue_data(q, ngx_http_lua_balancer_ka_item_t, + queue); + ngx_queue_remove(q); + ngx_queue_remove(&item->hnode); + + ngx_http_lua_balancer_close(item->connection); + + } else { + q = ngx_queue_head(&lscf->balancer.free); + ngx_queue_remove(q); + + item = ngx_queue_data(q, ngx_http_lua_balancer_ka_item_t, + queue); + } + + host = &bp->host; + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: keepalive saving connection %p, " + "host: %V, name: %V", + c, bp->addr_text, host); + + ngx_queue_insert_head(&lscf->balancer.cache, q); + hash = ngx_http_lua_balancer_calc_hash(host, + bp->sockaddr, bp->socklen, + bp->local); + item->hash = hash; + hash %= lscf->balancer.bucket_cnt; + ngx_queue_insert_head(&lscf->balancer.buckets[hash], &item->hnode); + item->connection = c; + pc->connection = NULL; + + c->read->delayed = 0; + ngx_add_timer(c->read, bp->keepalive_timeout); + + if (c->write->timer_set) { + ngx_del_timer(c->write); + } + + c->write->handler = ngx_http_lua_balancer_dummy_handler; + c->read->handler = ngx_http_lua_balancer_close_handler; + + c->data = item; + c->idle = 1; + c->log = ngx_cycle->log; + c->read->log = ngx_cycle->log; + c->write->log = ngx_cycle->log; + c->pool->log = ngx_cycle->log; + + item->socklen = pc->socklen; + ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); + if (pc->local) { + ngx_memcpy(&item->local_sockaddr, + pc->local->sockaddr, pc->local->socklen); + + } else { + ngx_memzero(&item->local_sockaddr, + sizeof(item->local_sockaddr)); + } + + if (host->data && host->len) { + if (host->len <= sizeof(item->host_data)) { + ngx_memcpy(item->host_data, host->data, host->len); + item->host.data = item->host_data; + item->host.len = host->len; + + } else { + item->host.data = ngx_pstrdup(c->pool, bp->addr_text); + if (item->host.data == NULL) { + ngx_http_lua_balancer_close(c); + + ngx_queue_remove(&item->queue); + ngx_queue_remove(&item->hnode); + ngx_queue_insert_head(&item->lscf->balancer.free, + &item->queue); + return; + } + + item->host.len = bp->addr_text->len; + } + + } else { + ngx_str_null(&item->host); + } + + if (c->read->ready) { + ngx_http_lua_balancer_close_handler(c->read); + } + + return; + +invalid: + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer: keepalive not saving connection %p", + c); + } + return; } - /* fallback */ + bp->original_free_peer(pc, bp->data, state); +} - ngx_http_upstream_free_round_robin_peer(pc, data, state); + +static void +ngx_http_lua_balancer_notify_peer(ngx_peer_connection_t *pc, void *data, + ngx_uint_t type) +{ +#ifdef NGX_HTTP_UPSTREAM_NOTIFY_CACHED_CONNECTION_ERROR + if (type == NGX_HTTP_UPSTREAM_NOTIFY_CACHED_CONNECTION_ERROR) { + pc->tries--; + } +#endif +} + + +static void +ngx_http_lua_balancer_close(ngx_connection_t *c) +{ +#if (NGX_HTTP_SSL) + if (c->ssl) { + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; + + if (ngx_ssl_shutdown(c) == NGX_AGAIN) { + c->ssl->handler = ngx_http_lua_balancer_close; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua balancer: keepalive shutdown " + "connection %p failed", c); + return; + } + } +#endif + + ngx_destroy_pool(c->pool); + ngx_close_connection(c); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua balancer: keepalive closing connection %p", c); +} + + +static void +ngx_http_lua_balancer_dummy_handler(ngx_event_t *ev) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, + "lua balancer: dummy handler"); +} + + +static void +ngx_http_lua_balancer_close_handler(ngx_event_t *ev) +{ + ngx_http_lua_balancer_ka_item_t *item; + + int n; + char buf[1]; + ngx_connection_t *c; + + c = ev->data; + if (c->close || c->read->timedout) { + goto close; + } + + n = recv(c->fd, buf, 1, MSG_PEEK); + + if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { + ev->ready = 0; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + goto close; + } + + return; + } + +close: + + item = c->data; + c->log = ev->log; + + ngx_http_lua_balancer_close(c); + + ngx_queue_remove(&item->queue); + ngx_queue_remove(&item->hnode); + ngx_queue_insert_head(&item->lscf->balancer.free, &item->queue); } @@ -446,7 +837,7 @@ ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data) return NGX_OK; } - return ngx_http_upstream_set_round_robin_peer_session(pc, &bp->rrp); + return bp->original_set_session(pc, bp->data); } @@ -460,8 +851,7 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) return; } - ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp); - return; + bp->original_save_session(pc, bp->data); } #endif @@ -469,13 +859,14 @@ ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) int ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, - const u_char *addr, size_t addr_len, int port, char **err) + const u_char *addr, size_t addr_len, int port, + const u_char *host, size_t host_len, + char **err) { ngx_url_t url; ngx_http_lua_ctx_t *ctx; ngx_http_upstream_t *u; - ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_balancer_peer_data_t *bp; if (r == NULL) { @@ -501,18 +892,6 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, return NGX_ERROR; } - lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - - /* we cannot read r->upstream->peer.data here directly because - * it could be overridden by other modules like - * ngx_http_upstream_keepalive_module. - */ - bp = lmcf->balancer_peer_data; - if (bp == NULL) { - *err = "no upstream peer data found"; - return NGX_ERROR; - } - ngx_memzero(&url, sizeof(ngx_url_t)); url.url.data = ngx_palloc(r->pool, addr_len); @@ -536,34 +915,116 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, return NGX_ERROR; } + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + if (url.addrs && url.addrs[0].sockaddr) { bp->sockaddr = url.addrs[0].sockaddr; bp->socklen = url.addrs[0].socklen; - bp->host = &url.addrs[0].name; + bp->addr_text = &url.addrs[0].name; } else { *err = "no host allowed"; return NGX_ERROR; } + if (host && host_len) { + bp->host.data = ngx_palloc(r->pool, host_len); + if (bp->host.data == NULL) { + *err = "no memory"; + return NGX_ERROR; + } + + ngx_memcpy(bp->host.data, host, host_len); + bp->host.len = host_len; + +#if (NGX_HTTP_SSL) + if (u->ssl) { + u->ssl_name = bp->host; + } +#endif + + } else { + ngx_str_null(&bp->host); + } + return NGX_OK; } int -ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, - long connect_timeout, long send_timeout, long read_timeout, - char **err) +ngx_http_lua_ffi_balancer_bind_to_local_addr(ngx_http_request_t *r, + const u_char *addr, size_t addr_len, + u_char *errbuf, size_t *errbuf_size) { + u_char *p; ngx_http_lua_ctx_t *ctx; ngx_http_upstream_t *u; + ngx_int_t rc; -#if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) - ngx_http_upstream_conf_t *ucf; -#endif - ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_balancer_peer_data_t *bp; + if (r == NULL) { + p = ngx_snprintf(errbuf, *errbuf_size, "no request found"); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + p = ngx_snprintf(errbuf, *errbuf_size, "no upstream found"); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + p = ngx_snprintf(errbuf, *errbuf_size, "no ctx found"); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + p = ngx_snprintf(errbuf, *errbuf_size, + "API disabled in the current context"); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + + if (bp->local == NULL) { + bp->local = ngx_palloc(r->pool, sizeof(ngx_addr_t) + addr_len); + if (bp->local == NULL) { + p = ngx_snprintf(errbuf, *errbuf_size, "no memory"); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + } + + rc = ngx_parse_addr_port(r->pool, bp->local, (u_char *) addr, addr_len); + if (rc == NGX_ERROR) { + p = ngx_snprintf(errbuf, *errbuf_size, "invalid addr %s", addr); + *errbuf_size = p - errbuf; + return NGX_ERROR; + } + + bp->local->name.len = addr_len; + bp->local->name.data = (u_char *) (bp->local + 1); + ngx_memcpy(bp->local->name.data, addr, addr_len); + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_balancer_enable_keepalive(ngx_http_request_t *r, + unsigned long timeout, unsigned int max_requests, char **err) +{ + ngx_http_upstream_t *u; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_balancer_peer_data_t *bp; + if (r == NULL) { *err = "no request found"; return NGX_ERROR; @@ -587,15 +1048,60 @@ ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, return NGX_ERROR; } - lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; - bp = lmcf->balancer_peer_data; - if (bp == NULL) { - *err = "no upstream peer data found"; + if (!(bp->sockaddr && bp->socklen)) { + *err = "no current peer set"; + return NGX_ERROR; + } + + bp->keepalive_timeout = (ngx_msec_t) timeout; + bp->keepalive_requests = (ngx_uint_t) max_requests; + bp->keepalive = 1; + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, long read_timeout, + char **err) +{ + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + +#if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + ngx_http_upstream_conf_t *ucf; + ngx_http_lua_balancer_peer_data_t *bp; +#endif + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; return NGX_ERROR; } #if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; + if (!bp->cloned_upstream_conf) { /* we clone the upstream conf for the current request so that * we do not affect other requests at all. */ @@ -650,12 +1156,10 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, int count, char **err) { #if (nginx_version >= 1007005) - ngx_uint_t max_tries, total; + ngx_uint_t max_tries, total; #endif - ngx_http_lua_ctx_t *ctx; - ngx_http_upstream_t *u; - - ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; ngx_http_lua_balancer_peer_data_t *bp; if (r == NULL) { @@ -681,13 +1185,7 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, return NGX_ERROR; } - lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - - bp = lmcf->balancer_peer_data; - if (bp == NULL) { - *err = "no upstream peer data found"; - return NGX_ERROR; - } + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; #if (nginx_version >= 1007005) max_tries = r->upstream->conf->next_upstream_tries; @@ -713,12 +1211,10 @@ int ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, int *status, char **err) { - ngx_http_lua_ctx_t *ctx; - ngx_http_upstream_t *u; - ngx_http_upstream_state_t *state; - + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + ngx_http_upstream_state_t *state; ngx_http_lua_balancer_peer_data_t *bp; - ngx_http_lua_main_conf_t *lmcf; if (r == NULL) { *err = "no request found"; @@ -743,13 +1239,7 @@ ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, return NGX_ERROR; } - lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - - bp = lmcf->balancer_peer_data; - if (bp == NULL) { - *err = "no upstream peer data found"; - return NGX_ERROR; - } + bp = (ngx_http_lua_balancer_peer_data_t *) u->peer.data; if (r->upstream_states && r->upstream_states->nelts > 1) { state = r->upstream_states->elts; @@ -802,11 +1292,221 @@ ngx_http_lua_ffi_balancer_recreate_request(ngx_http_request_t *r, /* u->request_bufs already contains a valid request buffer * remove it from chain first */ - u->request_bufs = u->request_bufs->next; + u->request_bufs = r->request_body->bufs; } return u->create_request(r); } +int +ngx_http_lua_ffi_balancer_set_upstream_tls(ngx_http_request_t *r, int on, + char **err) +{ + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; + return NGX_ERROR; + } + + if (on == 0) { + u->ssl = 0; + u->schema.len = sizeof("http://") - 1; + + } else { + u->ssl = 1; + u->schema.len = sizeof("https://") - 1; + } + + return NGX_OK; +} + + +char * +ngx_http_lua_balancer_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_int_t n; + ngx_str_t *value; + +#if 0 + ngx_http_upstream_srv_conf_t *uscf; +#endif + ngx_http_lua_srv_conf_t *lscf = conf; + + if (lscf->balancer.max_cached != NGX_CONF_UNSET_UINT) { + return "is duplicate"; + } + + /* read options */ + + value = cf->args->elts; + + n = ngx_atoi(value[1].data, value[1].len); + + if (n == NGX_ERROR || n == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\" in \"%V\" directive", + &value[1], &cmd->name); + return NGX_CONF_ERROR; + } + + lscf->balancer.max_cached = n; + + return NGX_CONF_OK; +} + + +#if (NGX_HTTP_SSL) +static ngx_int_t +ngx_http_lua_upstream_get_ssl_name(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + u_char *p, *last; + ngx_str_t name; + + if (u->conf->ssl_name) { + if (ngx_http_complex_value(r, u->conf->ssl_name, &name) != NGX_OK) { + return NGX_ERROR; + } + + } else { + name = u->ssl_name; + } + + if (name.len == 0) { + goto done; + } + + /* + * ssl name here may contain port, notably if derived from $proxy_host + * or $http_host; we have to strip it. eg: www.example.com:443 + */ + + p = name.data; + last = name.data + name.len; + + if (*p == '[') { + p = ngx_strlchr(p, last, ']'); + + if (p == NULL) { + p = name.data; + } + } + + p = ngx_strlchr(p, last, ':'); + + if (p != NULL) { + name.len = p - name.data; + } + +done: + + u->ssl_name = name; + + return NGX_OK; +} +#endif + + +static ngx_uint_t +ngx_http_lua_balancer_calc_hash(ngx_str_t *name, + struct sockaddr *sockaddr, socklen_t socklen, ngx_addr_t *local) +{ + ngx_uint_t hash; + + hash = ngx_hash_key_lc(name->data, name->len); + hash ^= ngx_hash_key((u_char *) sockaddr, socklen); + if (local != NULL) { + hash ^= ngx_hash_key((u_char *) local->sockaddr, local->socklen); + } + + return hash; +} + + +static ngx_connection_t * +ngx_http_lua_balancer_get_cached_item(ngx_http_lua_srv_conf_t *lscf, + ngx_peer_connection_t *pc, ngx_str_t *name) +{ + ngx_uint_t hash; + ngx_queue_t *q; + ngx_queue_t *head; + ngx_connection_t *c; + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_addr_t *local; + ngx_http_lua_balancer_ka_item_t *item; + + sockaddr = pc->sockaddr; + socklen = pc->socklen; + local = pc->local; + + hash = ngx_http_lua_balancer_calc_hash(name, sockaddr, socklen, pc->local); + head = &lscf->balancer.buckets[hash % lscf->balancer.bucket_cnt]; + + c = NULL; + for (q = ngx_queue_head(head); + q != ngx_queue_sentinel(head); + q = ngx_queue_next(q)) + { + item = ngx_queue_data(q, ngx_http_lua_balancer_ka_item_t, hnode); + if (item->hash != hash) { + continue; + } + + if (name->len == item->host.len + && ngx_memn2cmp((u_char *) &item->sockaddr, + (u_char *) sockaddr, + item->socklen, socklen) == 0 + && ngx_strncasecmp(name->data, + item->host.data, name->len) == 0 + && (local == NULL + || ngx_memn2cmp((u_char *) &item->local_sockaddr, + (u_char *) local->sockaddr, + socklen, local->socklen) == 0)) + { + c = item->connection; + ngx_queue_remove(q); + ngx_queue_remove(&item->queue); + ngx_queue_insert_head(&lscf->balancer.free, &item->queue); + c->idle = 0; + c->sent = 0; + c->log = pc->log; + c->read->log = pc->log; + c->write->log = pc->log; + c->pool->log = pc->log; + + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + + pc->cached = 1; + pc->connection = c; + return c; + } + } + + return NULL; +} + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.h b/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.h index bb49dc02c..34db2fe82 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.h +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_balancer.h @@ -23,5 +23,7 @@ char *ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, char *ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_balancer_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); #endif /* _NGX_HTTP_LUA_BALANCER_H_INCLUDED_ */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_bodyfilterby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_bodyfilterby.c index 78e3b5c2d..c0484c8de 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_bodyfilterby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_bodyfilterby.c @@ -532,9 +532,23 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, if (last) { ctx->seen_last_in_filter = 1; - /* the "in" chain cannot be NULL and we set the "last_buf" or - * "last_in_chain" flag in the last buf of "in" */ + /* the "in" chain cannot be NULL except that we set arg[1] = "" + * before arg[2] = true + */ + if (in == NULL) { + in = ngx_http_lua_chain_get_free_buf(r->connection->log, + r->pool, + &ctx->free_bufs, 0); + if (in == NULL) { + return luaL_error(L, "no memory"); + } + in->buf->tag = (ngx_buf_tag_t) &ngx_http_lua_body_filter; + lmcf->body_filter_chain = in; + } + + /* we set the "last_buf" or "last_in_chain" flag + * in the last buf of "in" */ for (cl = in; cl; cl = cl->next) { if (cl->next == NULL) { if (r == r->main) { diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_common.h b/src/deps/src/lua-nginx-module/src/ngx_http_lua_common.h index 4c946297f..cc2d36a38 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_common.h +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_common.h @@ -167,7 +167,7 @@ typedef struct ngx_http_lua_co_ctx_s ngx_http_lua_co_ctx_t; typedef struct ngx_http_lua_sema_mm_s ngx_http_lua_sema_mm_t; -typedef union ngx_http_lua_srv_conf_u ngx_http_lua_srv_conf_t; +typedef struct ngx_http_lua_srv_conf_s ngx_http_lua_srv_conf_t; typedef struct ngx_http_lua_main_conf_s ngx_http_lua_main_conf_t; @@ -258,13 +258,6 @@ struct ngx_http_lua_main_conf_s { ngx_str_t exit_worker_src; u_char *exit_worker_chunkname; - ngx_http_lua_balancer_peer_data_t *balancer_peer_data; - /* neither yielding nor recursion is possible in - * balancer_by_lua*, so there cannot be any races among - * concurrent requests and it is safe to store the peer - * data pointer in the main conf. - */ - ngx_chain_t *body_filter_chain; /* neither yielding nor recursion is possible in * body_filter_by_lua*, so there cannot be any races among @@ -323,7 +316,7 @@ struct ngx_http_lua_main_conf_s { }; -union ngx_http_lua_srv_conf_u { +struct ngx_http_lua_srv_conf_s { struct { #if (NGX_HTTP_SSL) ngx_http_lua_srv_conf_handler_pt ssl_cert_handler; @@ -359,6 +352,14 @@ union ngx_http_lua_srv_conf_u { } srv; struct { + ngx_uint_t max_cached; + ngx_queue_t cache; + ngx_queue_t free; + ngx_queue_t *buckets; + ngx_uint_t bucket_cnt; + ngx_http_upstream_init_pt original_init_upstream; + ngx_http_upstream_init_peer_pt original_init_peer; + ngx_http_lua_srv_conf_handler_pt handler; ngx_str_t src; u_char *src_key; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_contentby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_contentby.c index 2014d52d8..5e2ae5520 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_contentby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_contentby.c @@ -196,26 +196,6 @@ ngx_http_lua_content_handler(ngx_http_request_t *r) } if (llcf->force_read_body && !ctx->read_body_done) { - -#if (NGX_HTTP_V2) - if (r->main->stream && r->headers_in.content_length_n < 0) { - ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "disable lua_need_request_body, since " - "http2 read_body may break http2 stream process"); - goto done; - } -#endif - -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30 - && r->headers_in.content_length_n < 0) - { - ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "disable lua_need_request_body, since " - "http2 read_body may break http2 stream process"); - goto done; - } -#endif r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; @@ -234,12 +214,6 @@ ngx_http_lua_content_handler(ngx_http_request_t *r) } } -#if defined(NGX_HTTP_V3) || defined(NGX_HTTP_V2) - -done: - -#endif - dd("setting entered"); ctx->entered_content_phase = 1; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_initworkerby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_initworkerby.c index 449e604ac..edb68df08 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_initworkerby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_initworkerby.c @@ -297,6 +297,8 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) (void) lmcf->init_worker_handler(cycle->log, lmcf, lmcf->lua); + ngx_http_lua_set_req(lmcf->lua, NULL); + ngx_destroy_pool(c->pool); return NGX_OK; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_module.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_module.c index fb10bf933..63367f46b 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_module.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_module.c @@ -33,7 +33,9 @@ #include "ngx_http_lua_ssl_session_fetchby.h" #include "ngx_http_lua_headers.h" #include "ngx_http_lua_headers_out.h" +#if !(NGX_WIN32) #include "ngx_http_lua_pipe.h" +#endif static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); @@ -494,6 +496,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_balancer_handler_file }, + { ngx_string("balancer_keepalive"), + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, + ngx_http_lua_balancer_keepalive, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_lua_srv_conf_t, balancer.max_cached), + NULL }, + { ngx_string("lua_socket_keepalive_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF |NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, @@ -1141,7 +1150,7 @@ ngx_http_lua_init_main_conf(ngx_conf_t *cf, void *conf) #endif if (lmcf->worker_thread_vm_pool_size == NGX_CONF_UNSET_UINT) { - lmcf->worker_thread_vm_pool_size = 100; + lmcf->worker_thread_vm_pool_size = 10; } if (ngx_http_lua_init_builtin_headers_out(cf, lmcf) != NGX_OK) { @@ -1188,6 +1197,8 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf) * lscf->srv.ssl_sess_fetch_chunkname = NULL; * lscf->srv.ssl_sess_fetch_src_key = NULL; * + * lscf->balancer.original_init_upstream = NULL; + * lscf->balancer.original_init_peer = NULL; * lscf->balancer.handler = NULL; * lscf->balancer.src = { 0, NULL }; * lscf->balancer.chunkname = NULL; @@ -1202,7 +1213,7 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf) #endif lscf->balancer.src_ref = LUA_REFNIL; - + lscf->balancer.max_cached = NGX_CONF_UNSET_UINT; return lscf; } @@ -1503,7 +1514,11 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, (NGX_CONF_BITMASK_SET |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 - |NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3)); + |NGX_SSL_TLSv1_2 +#ifdef NGX_SSL_TLSv1_3 + |NGX_SSL_TLSv1_3 +#endif + )); ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_regex.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_regex.c index 1b52fa233..646b483e1 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_regex.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_regex.c @@ -591,7 +591,11 @@ ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, re_comp.captures = 0; } else { +#if (NGX_PCRE2) + ovecsize = (re_comp.captures + 1) * 2; +#else ovecsize = (re_comp.captures + 1) * 3; +#endif } dd("allocating cap with size: %d", (int) ovecsize); @@ -684,21 +688,21 @@ ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, { int rc, exec_opts = 0; size_t *ov; - ngx_uint_t ovecsize, n, i; + ngx_uint_t ovecpair, n, i; ngx_pool_t *old_pool; if (flags & NGX_LUA_RE_MODE_DFA) { - ovecsize = 2; + ovecpair = 1; re->ncaptures = 0; } else { - ovecsize = (re->ncaptures + 1) * 3; + ovecpair = re->ncaptures + 1; } old_pool = ngx_http_lua_pcre_malloc_init(NULL); if (ngx_regex_match_data == NULL - || ovecsize > ngx_regex_match_data_size) + || ovecpair > ngx_regex_match_data_size) { /* * Allocate a match data if not yet allocated or smaller than @@ -709,8 +713,8 @@ ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, pcre2_match_data_free(ngx_regex_match_data); } - ngx_regex_match_data_size = ovecsize; - ngx_regex_match_data = pcre2_match_data_create(ovecsize / 3, NULL); + ngx_regex_match_data_size = ovecpair; + ngx_regex_match_data = pcre2_match_data_create(ovecpair, NULL); if (ngx_regex_match_data == NULL) { rc = PCRE2_ERROR_NOMEMORY; @@ -741,7 +745,7 @@ ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, #if (NGX_DEBUG) ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "pcre2_match failed: flags 0x%05Xd, options 0x%08Xd, " - "rc %d, ovecsize %ui", flags, exec_opts, rc, ovecsize); + "rc %d, ovecpair %ui", flags, exec_opts, rc, ovecpair); #endif goto failed; @@ -753,11 +757,11 @@ ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, #if (NGX_DEBUG) ngx_log_debug5(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "pcre2_match: flags 0x%05Xd, options 0x%08Xd, rc %d, " - "n %ui, ovecsize %ui", flags, exec_opts, rc, n, ovecsize); + "n %ui, ovecpair %ui", flags, exec_opts, rc, n, ovecpair); #endif - if (!(flags & NGX_LUA_RE_MODE_DFA) && n > ovecsize / 3) { - n = ovecsize / 3; + if (n > ovecpair) { + n = ovecpair; } for (i = 0; i < n; i++) { diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_req_body.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_req_body.c index 61ab99904..5d69735cd 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_req_body.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_req_body.c @@ -85,23 +85,6 @@ ngx_http_lua_ngx_req_read_body(lua_State *L) return luaL_error(L, "request object not found"); } -/* http2 read body may break http2 stream process */ -#if (NGX_HTTP_V2) - if (r->main->stream && r->headers_in.content_length_n < 0) { - return luaL_error(L, "http2 requests are not supported" - " without content-length header"); - } -#endif - -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30 - && r->headers_in.content_length_n < 0) - { - return luaL_error(L, "http3 requests are not supported" - " without content-length header"); - } -#endif - r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; @@ -349,23 +332,6 @@ ngx_http_lua_ngx_req_get_body_file(lua_State *L) return luaL_error(L, "request object not found"); } -/* http2 read body may break http2 stream process */ -#if (NGX_HTTP_V2) - if (r->main->stream && r->headers_in.content_length_n < 0) { - return luaL_error(L, "http2 requests are not supported" - " without content-length header"); - } -#endif - -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30 - && r->headers_in.content_length_n < 0) - { - return luaL_error(L, "http3 requests are not supported" - " without content-length header"); - } -#endif - ngx_http_lua_check_fake_request(L, r); if (r->request_body == NULL || r->request_body->temp_file == NULL) { diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_rewriteby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_rewriteby.c index c56bba5d7..4109f288e 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_rewriteby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_rewriteby.c @@ -140,12 +140,7 @@ ngx_http_lua_rewrite_handler(ngx_http_request_t *r) return NGX_DONE; } -/* http2 read body may break http2 stream process */ -#if (NGX_HTTP_V2) - if (llcf->force_read_body && !ctx->read_body_done && !r->main->stream) { -#else if (llcf->force_read_body && !ctx->read_body_done) { -#endif r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_server_rewriteby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_server_rewriteby.c index 997262eeb..be860693f 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_server_rewriteby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_server_rewriteby.c @@ -102,13 +102,8 @@ ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r) return NGX_DONE; } -/* TODO: lscf do not have force_read_body - * http2 read body may break http2 stream process */ -#if (NGX_HTTP_V2) - if (llcf->force_read_body && !ctx->read_body_done && !r->main->stream) { -#else + /* TODO: lscf do not have force_read_body */ if (llcf->force_read_body && !ctx->read_body_done) { -#endif r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_shdict.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_shdict.c index c63eb3c10..146974d95 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_shdict.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_shdict.c @@ -210,7 +210,7 @@ ngx_http_lua_shdict_lookup(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, dd("time to live: %lld", (long long) ms); - if (ms < 0) { + if (ms <= 0) { dd("node already expired"); return NGX_DONE; } diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_tcp.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_tcp.c index 230679fa7..5010dfa6e 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_tcp.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_tcp.c @@ -861,13 +861,7 @@ ngx_http_lua_socket_tcp_bind(lua_State *L) return luaL_error(L, "no ctx found"); } - ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE - | NGX_HTTP_LUA_CONTEXT_ACCESS - | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT - | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH - | NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO); + ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE); luaL_checktype(L, 1, LUA_TTABLE); @@ -5385,6 +5379,34 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); + r = ngx_http_lua_get_req(L); + if (r == NULL) { + return luaL_error(L, "no request found"); + } + + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + + /* luaL_checkinteger will throw error if the argument is not a number. + * e.g.: bad argument \#2 to '?' (number expected, got string) + * + * We should check the argument in advance; otherwise, + * throwing an exception in the middle can compromise data integrity. + * e.g.: set pc->connection to NULL without following cleanup. + */ + if (n >= 2 && !lua_isnil(L, 2)) { + timeout = (ngx_msec_t) luaL_checkinteger(L, 2); + + } else { + timeout = llcf->keepalive_timeout; + } + + if (n >= 3 && !lua_isnil(L, 3)) { + pool_size = luaL_checkinteger(L, 3); + + } else { + pool_size = llcf->pool_size; + } + lua_rawgeti(L, 1, SOCKET_CTX_INDEX); u = lua_touserdata(L, -1); lua_pop(L, 1); @@ -5411,11 +5433,6 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) return 2; } - r = ngx_http_lua_get_req(L); - if (r == NULL) { - return luaL_error(L, "no request found"); - } - if (u->request != r) { return luaL_error(L, "bad request"); } @@ -5486,18 +5503,8 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) /* stack: obj timeout? size? pools cache_key */ - llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); - if (spool == NULL) { /* create a new socket pool for the current peer key */ - - if (n >= 3 && !lua_isnil(L, 3)) { - pool_size = luaL_checkinteger(L, 3); - - } else { - pool_size = llcf->pool_size; - } - if (pool_size <= 0) { msg = lua_pushfstring(L, "bad \"pool_size\" option value: %d", pool_size); @@ -5561,13 +5568,6 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) ngx_del_timer(c->write); } - if (n >= 2 && !lua_isnil(L, 2)) { - timeout = (ngx_msec_t) luaL_checkinteger(L, 2); - - } else { - timeout = llcf->keepalive_timeout; - } - #if (NGX_DEBUG) if (timeout == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -5747,6 +5747,16 @@ ngx_http_lua_socket_keepalive_close_handler(ngx_event_t *ev) "lua tcp socket keepalive close handler check stale events"); n = recv(c->fd, buf, 1, MSG_PEEK); +#if (NGX_HTTP_SSL) + /* ignore ssl protocol data like change cipher spec */ + if (n == 1 && c->ssl != NULL) { + n = c->recv(c, (unsigned char *) buf, 1); + if (n == NGX_AGAIN) { + n = -1; + ngx_socket_errno = NGX_EAGAIN; + } + } +#endif if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { /* stale event */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.c index 10285f6d0..e2ba790fc 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.c @@ -54,16 +54,19 @@ static void ngx_http_lua_socket_udp_read_handler(ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); static void ngx_http_lua_socket_udp_handle_success(ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); -static ngx_int_t ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc); +static ngx_int_t ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc, + ngx_addr_t *local); static int ngx_http_lua_socket_udp_close(lua_State *L); static ngx_int_t ngx_http_lua_socket_udp_resume(ngx_http_request_t *r); static void ngx_http_lua_udp_resolve_cleanup(void *data); static void ngx_http_lua_udp_socket_cleanup(void *data); +static int ngx_http_lua_socket_udp_bind(lua_State *L); enum { SOCKET_CTX_INDEX = 1, SOCKET_TIMEOUT_INDEX = 2, + SOCKET_BIND_INDEX = 3, }; @@ -100,6 +103,9 @@ ngx_http_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L) lua_pushcfunction(L, ngx_http_lua_socket_udp_close); lua_setfield(L, -2, "close"); /* ngx socket mt */ + lua_pushcfunction(L, ngx_http_lua_socket_udp_bind); + lua_setfield(L, -2, "bind"); + lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); lua_rawset(L, LUA_REGISTRYINDEX); @@ -159,6 +165,7 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L) ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_str_t host; + ngx_addr_t *local; int port; ngx_resolver_ctx_t *rctx, temp; ngx_http_core_loc_conf_t *clcf; @@ -291,6 +298,13 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L) u->read_timeout = u->conf->read_timeout; } + lua_rawgeti(L, 1, SOCKET_BIND_INDEX); + local = lua_touserdata(L, -1); + lua_pop(L, 1); + if (local != NULL) { + u->local = local; + } + ngx_memzero(&url, sizeof(ngx_url_t)); url.url.len = host.len; @@ -618,7 +632,7 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, return 2; } - rc = ngx_http_lua_udp_connect(uc); + rc = ngx_http_lua_udp_connect(uc, u->local); if (rc != NGX_OK) { u->socket_errno = ngx_socket_errno; @@ -721,6 +735,56 @@ ngx_http_lua_socket_error_retval_handler(ngx_http_request_t *r, } +static int +ngx_http_lua_socket_udp_bind(lua_State *L) +{ + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + int n; + u_char *text; + size_t len; + ngx_addr_t *local; + + n = lua_gettop(L); + + if (n != 2) { + return luaL_error(L, "expecting 2 arguments, but got %d", + lua_gettop(L)); + } + + r = ngx_http_lua_get_req(L); + if (r == NULL) { + return luaL_error(L, "no request found"); + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return luaL_error(L, "no ctx found"); + } + + ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE); + + luaL_checktype(L, 1, LUA_TTABLE); + + text = (u_char *) luaL_checklstring(L, 2, &len); + + local = ngx_http_lua_parse_addr(L, text, len); + if (local == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "bad address"); + return 2; + } + + lua_rawseti(L, 1, SOCKET_BIND_INDEX); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua udp socket bind ip: %V", &local->name); + + lua_pushinteger(L, 1); + return 1; +} + + static int ngx_http_lua_socket_udp_send(lua_State *L) { @@ -1340,7 +1404,7 @@ ngx_http_lua_socket_udp_handle_success(ngx_http_request_t *r, static ngx_int_t -ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc) +ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc, ngx_addr_t *local) { int rc; ngx_int_t event; @@ -1413,8 +1477,19 @@ ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc) return NGX_ERROR; } } + #endif + if (local != NULL) { + fprintf(stderr, "=== have local address\n"); + if (bind(s, local->sockaddr, local->socklen) == -1) { + ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno, + "bind(%V) failed", &local->name); + + return NGX_ERROR; + } + } + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "connect to %V, fd:%d #%d", &uc->server, s, c->number); diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.h b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.h index 83333461d..61245b364 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.h +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_socket_udp.h @@ -42,6 +42,8 @@ struct ngx_http_lua_socket_udp_upstream_s { ngx_http_request_t *request; ngx_http_lua_udp_connection_t udp_connection; + ngx_addr_t *local; + ngx_msec_t read_timeout; ngx_http_upstream_resolved_t *resolved; @@ -53,7 +55,7 @@ struct ngx_http_lua_socket_udp_upstream_s { ngx_http_lua_co_ctx_t *co_ctx; - unsigned waiting; /* :1 */ + unsigned waiting:1; /* :1 */ }; diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_certby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_certby.c index b8e70ddef..0901f06ea 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_certby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_certby.c @@ -1172,6 +1172,81 @@ ngx_http_lua_ffi_parse_pem_cert(const u_char *pem, size_t pem_len, } +void * +ngx_http_lua_ffi_parse_der_cert(const char *data, size_t len, + char **err) +{ + BIO *bio; + X509 *x509; + STACK_OF(X509) *chain; + + if (data == NULL || len == 0) { + *err = "invalid argument"; + ERR_clear_error(); + return NULL; + } + + bio = BIO_new_mem_buf((char *) data, len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NULL; + } + + x509 = d2i_X509_bio(bio, NULL); + if (x509 == NULL) { + *err = "d2i_X509_bio() failed"; + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + chain = sk_X509_new_null(); + if (chain == NULL) { + *err = "sk_X509_new_null() failed"; + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + if (sk_X509_push(chain, x509) == 0) { + *err = "sk_X509_push() failed"; + sk_X509_free(chain); + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + /* read rest of the chain */ + + while (!BIO_eof(bio)) { + x509 = d2i_X509_bio(bio, NULL); + if (x509 == NULL) { + *err = "d2i_X509_bio() failed in rest of chain"; + sk_X509_pop_free(chain, X509_free); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + if (sk_X509_push(chain, x509) == 0) { + *err = "sk_X509_push() failed in rest of chain"; + sk_X509_pop_free(chain, X509_free); + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + } + + BIO_free(bio); + + return chain; +} + + void ngx_http_lua_ffi_free_cert(void *cdata) { @@ -1209,6 +1284,40 @@ ngx_http_lua_ffi_parse_pem_priv_key(const u_char *pem, size_t pem_len, } +void * +ngx_http_lua_ffi_parse_der_priv_key(const char *data, size_t len, + char **err) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + + if (data == NULL || len == 0) { + *err = "invalid argument"; + ERR_clear_error(); + return NULL; + } + + bio = BIO_new_mem_buf((char *) data, len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NULL; + } + + pkey = d2i_PrivateKey_bio(bio, NULL); + if (pkey == NULL) { + *err = "d2i_PrivateKey_bio() failed"; + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + BIO_free(bio); + + return pkey; +} + + void ngx_http_lua_ffi_free_priv_key(void *cdata) { @@ -1359,8 +1468,8 @@ ngx_http_lua_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store) int -ngx_http_lua_ffi_ssl_verify_client(ngx_http_request_t *r, void *ca_certs, - int depth, char **err) +ngx_http_lua_ffi_ssl_verify_client(ngx_http_request_t *r, void *client_certs, + void *trusted_certs, int depth, char **err) { #ifdef LIBRESSL_VERSION_NUMBER @@ -1372,7 +1481,8 @@ ngx_http_lua_ffi_ssl_verify_client(ngx_http_request_t *r, void *ca_certs, ngx_http_lua_ctx_t *ctx; ngx_ssl_conn_t *ssl_conn; ngx_http_ssl_srv_conf_t *sscf; - STACK_OF(X509) *chain = ca_certs; + STACK_OF(X509) *client_chain = client_certs; + STACK_OF(X509) *trusted_chain = trusted_certs; STACK_OF(X509_NAME) *name_chain = NULL; X509 *x509 = NULL; X509_NAME *subject = NULL; @@ -1426,54 +1536,75 @@ ngx_http_lua_ffi_ssl_verify_client(ngx_http_request_t *r, void *ca_certs, /* set CA chain */ - if (chain != NULL) { + if (client_chain != NULL || trusted_chain != NULL) { + ca_store = X509_STORE_new(); if (ca_store == NULL) { *err = "X509_STORE_new() failed"; return NGX_ERROR; } - /* construct name chain */ + if (client_chain != NULL) { - name_chain = sk_X509_NAME_new_null(); - if (name_chain == NULL) { - *err = "sk_X509_NAME_new_null() failed"; - goto failed; + /* construct name chain */ + name_chain = sk_X509_NAME_new_null(); + if (name_chain == NULL) { + *err = "sk_X509_NAME_new_null() failed"; + goto failed; + } + + for (i = 0; i < sk_X509_num(client_chain); i++) { + x509 = sk_X509_value(client_chain, i); + if (x509 == NULL) { + *err = "sk_X509_value() failed"; + goto failed; + } + + /* add subject to name chain, which will be sent to client */ + subject = X509_NAME_dup(X509_get_subject_name(x509)); + if (subject == NULL) { + *err = "X509_get_subject_name() failed"; + goto failed; + } + + if (!sk_X509_NAME_push(name_chain, subject)) { + *err = "sk_X509_NAME_push() failed"; + X509_NAME_free(subject); + goto failed; + } + + /* add to trusted CA store */ + if (X509_STORE_add_cert(ca_store, x509) == 0) { + *err = "X509_STORE_add_cert() failed"; + goto failed; + } + } + + /* clean subject name list, and set it for send to client */ + SSL_set_client_CA_list(ssl_conn, name_chain); } - for (i = 0; i < sk_X509_num(chain); i++) { - x509 = sk_X509_value(chain, i); - if (x509 == NULL) { - *err = "sk_X509_value() failed"; - goto failed; - } + if (trusted_chain != NULL) { + for (i = 0; i < sk_X509_num(trusted_chain); i++) { + x509 = sk_X509_value(trusted_chain, i); + if (x509 == NULL) { + *err = "sk_X509_value() failed"; + goto failed; + } - /* add subject to name chain, which will be sent to client */ - subject = X509_NAME_dup(X509_get_subject_name(x509)); - if (subject == NULL) { - *err = "X509_get_subject_name() failed"; - goto failed; - } - - if (!sk_X509_NAME_push(name_chain, subject)) { - *err = "sk_X509_NAME_push() failed"; - X509_NAME_free(subject); - goto failed; - } - - /* add to trusted CA store */ - if (X509_STORE_add_cert(ca_store, x509) == 0) { - *err = "X509_STORE_add_cert() failed"; - goto failed; + /* add to trusted CA store */ + if (X509_STORE_add_cert(ca_store, x509) == 0) { + *err = "X509_STORE_add_cert() failed"; + goto failed; + } } } + /* clean ca_store, and store new ca_store */ if (SSL_set0_verify_cert_store(ssl_conn, ca_store) == 0) { *err = "SSL_set0_verify_cert_store() failed"; goto failed; } - - SSL_set_client_CA_list(ssl_conn, name_chain); } return NGX_OK; @@ -1500,4 +1631,27 @@ ngx_http_lua_ffi_get_req_ssl_pointer(ngx_http_request_t *r) } +int +ngx_http_lua_ffi_ssl_client_random(ngx_http_request_t *r, + unsigned char *out, size_t *outlen, char **err) +{ + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + *outlen = SSL_get_client_random(ssl_conn, out, *outlen); + + return NGX_OK; +} + + #endif /* NGX_HTTP_SSL */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_client_helloby.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_client_helloby.c index 03ac430ef..9800f7d41 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_client_helloby.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_client_helloby.c @@ -541,6 +541,10 @@ int ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r, const char **name, size_t *namelen, char **err) { +#ifdef LIBRESSL_VERSION_NUMBER + *err = "LibreSSL does not support by ssl_client_hello_by_lua*"; + return NGX_ERROR; +#else ngx_ssl_conn_t *ssl_conn; #ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB const unsigned char *p; @@ -619,6 +623,7 @@ ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r, *err = "no TLS extension support"; return NGX_ERROR; #endif +#endif /* LIBRESSL_VERSION_NUMBER */ } @@ -626,6 +631,10 @@ int ngx_http_lua_ffi_ssl_get_client_hello_ext(ngx_http_request_t *r, unsigned int type, const unsigned char **out, size_t *outlen, char **err) { +#ifdef LIBRESSL_VERSION_NUMBER + *err = "LibreSSL does not support by ssl_client_hello_by_lua*"; + return NGX_ERROR; +#else ngx_ssl_conn_t *ssl_conn; if (r->connection == NULL || r->connection->ssl == NULL) { @@ -649,7 +658,7 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext(ngx_http_request_t *r, *err = "OpenSSL too old to support this function"; return NGX_ERROR; #endif - +#endif /* LIBRESSL_VERSION_NUMBER */ } @@ -703,7 +712,7 @@ ngx_http_lua_ffi_ssl_set_protocols(ngx_http_request_t *r, } #endif -#ifdef SSL_OP_NO_TLSv1_3 +#if defined(NGX_SSL_TLSv1_3) && defined( SSL_OP_NO_TLSv1_3) SSL_clear_options(ssl_conn, SSL_OP_NO_TLSv1_3); if (!(protocols & NGX_SSL_TLSv1_3)) { SSL_set_options(ssl_conn, SSL_OP_NO_TLSv1_3); diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.c new file mode 100644 index 000000000..ec64c049a --- /dev/null +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.c @@ -0,0 +1,125 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif + + +#include "ddebug.h" + +#if (NGX_HTTP_SSL) + +#include + +#include "ngx_http_lua_cache.h" +#include "ngx_http_lua_initworkerby.h" +#include "ngx_http_lua_util.h" +#include "ngx_http_ssl_module.h" +#include "ngx_http_lua_contentby.h" +#include "ngx_http_lua_ssl_session_fetchby.h" +#include "ngx_http_lua_ssl.h" +#include "ngx_http_lua_directive.h" +#include "ngx_http_lua_ssl_export_keying_material.h" + + +ngx_int_t +ngx_http_lua_ffi_ssl_export_keying_material(ngx_http_request_t *r, + u_char *out, size_t out_size, const char *label, size_t llen, + const u_char *context, size_t ctxlen, int use_ctx, char **err) +{ +#if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x10101000L + *err = "BoringSSL does not support SSL_export_keying_material"; + return NGX_ERROR; +#elif defined(LIBRESSL_VERSION_NUMBER) + *err = "LibreSSL does not support SSL_export_keying_material"; + return NGX_ERROR; +#elif OPENSSL_VERSION_NUMBER < 0x10101000L + *err = "OpenSSL too old"; + return NGX_ERROR; +#else + ngx_connection_t *c; + ngx_ssl_conn_t *ssl_conn; + int rc; + + c = r->connection; + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl connection"; + return NGX_ERROR; + } + + rc = SSL_export_keying_material(ssl_conn, out, out_size, label, llen, + context, ctxlen, use_ctx); + if (rc == 1) { + return NGX_OK; + } + + ngx_ssl_error(NGX_LOG_INFO, c->log, 0, + "SSL_export_keying_material rc: %d, error: %s", + rc, ERR_error_string(ERR_get_error(), NULL)); + + *err = "SSL_export_keying_material() failed"; + + return NGX_ERROR; +#endif +} + + +ngx_int_t +ngx_http_lua_ffi_ssl_export_keying_material_early(ngx_http_request_t *r, + u_char *out, size_t out_size, const char *label, size_t llen, + const u_char *context, size_t ctxlen, char **err) +{ +#if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x10101000L + *err = "BoringSSL does not support SSL_export_keying_material"; + return NGX_ERROR; +#elif defined(LIBRESSL_VERSION_NUMBER) + *err = "LibreSSL does not support SSL_export_keying_material"; + return NGX_ERROR; +#elif OPENSSL_VERSION_NUMBER < 0x10101000L + *err = "OpenSSL too old"; + return NGX_ERROR; +#else + int rc; + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + + c = r->connection; + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl connection"; + return NGX_ERROR; + } + + rc = SSL_export_keying_material_early(ssl_conn, out, out_size, + label, llen, context, ctxlen); + + if (rc == 1) { + return NGX_OK; + } + + ngx_ssl_error(NGX_LOG_INFO, c->log, 0, + "SSL_export_keying_material_early rc: %d, error: %s", + rc, ERR_error_string(ERR_get_error(), NULL)); + + *err = "SSL_export_keying_material_early() failed"; + + return NGX_ERROR; +#endif +} + +#endif /* NGX_HTTP_SSL */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.h b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.h new file mode 100644 index 000000000..7a54bcda3 --- /dev/null +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_export_keying_material.h @@ -0,0 +1,24 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_SSL_EXPORT_KEYING_MATERIAL_H_INCLUDED_ +#define _NGX_HTTP_LUA_SSL_EXPORT_KEYING_MATERIAL_H_INCLUDED_ + +#include "ngx_http_lua_common.h" + +#if (NGX_HTTP_SSL) +ngx_int_t ngx_http_lua_ffi_ssl_export_keying_material(ngx_http_request_t *r, + u_char *out, size_t out_size, const char *label, size_t llen, + const u_char *ctx, size_t ctxlen, int use_ctx, char **err); + +ngx_int_t ngx_http_lua_ffi_ssl_export_keying_material_early( + ngx_http_request_t *r, u_char *out, size_t out_size, const char *label, + size_t llen, const u_char *ctx, size_t ctxlen, char **err); +#endif + +#endif /* _NGX_HTTP_LUA_SSL_EXPORT_KEYING_MATERIAL_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_ocsp.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_ocsp.c index d1805b23d..73e1b9c7f 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_ocsp.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_ssl_ocsp.c @@ -19,8 +19,9 @@ #ifdef NGX_HTTP_LUA_USE_OCSP static int ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn, void *data); -#endif +static long ngx_http_lua_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time); +#endif int ngx_http_lua_ffi_ssl_get_ocsp_responder_from_der_chain( @@ -262,7 +263,7 @@ failed: int ngx_http_lua_ffi_ssl_validate_ocsp_response(const u_char *resp, size_t resp_len, const char *chain_data, size_t chain_len, - u_char *errbuf, size_t *errbuf_size) + u_char *errbuf, size_t *errbuf_size, long *valid) { #ifndef NGX_HTTP_LUA_USE_OCSP @@ -279,7 +280,7 @@ ngx_http_lua_ffi_ssl_validate_ocsp_response(const u_char *resp, OCSP_RESPONSE *ocsp = NULL; OCSP_BASICRESP *basic = NULL; STACK_OF(X509) *chain = NULL; - ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; + ASN1_GENERALIZEDTIME *thisupdate = NULL, *nextupdate = NULL; ocsp = d2i_OCSP_RESPONSE(NULL, &resp, resp_len); if (ocsp == NULL) { @@ -383,6 +384,16 @@ ngx_http_lua_ffi_ssl_validate_ocsp_response(const u_char *resp, goto error; } + if (nextupdate) { + *valid = ngx_http_lua_ssl_stapling_time(nextupdate); + if (*valid == NGX_ERROR) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "invalid nextUpdate time " + "in certificate status") - errbuf; + goto error; + } + } + sk_X509_free(chain); X509_free(cert); X509_free(issuer); @@ -437,6 +448,40 @@ ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { return SSL_TLSEXT_ERR_OK; } + + +static long +ngx_http_lua_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) +{ + BIO *bio; + char *value; + size_t len; + time_t time; + + /* + * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME + * into long. To do this, we use ASN1_GENERALIZEDTIME_print(), + * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g., + * "Feb 3 00:55:52 2015 GMT"), and parse the result. + */ + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + return NGX_ERROR; + } + + /* fake weekday prepended to match C asctime() format */ + + BIO_write(bio, "Tue ", sizeof("Tue ") - 1); + ASN1_GENERALIZEDTIME_print(bio, asn1time); + len = BIO_get_mem_data(bio, &value); + + time = ngx_parse_http_time((u_char *) value, len); + + BIO_free(bio); + + return time; +} #endif diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_subrequest.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_subrequest.c index f4db9aaf6..2ccd271a9 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_subrequest.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_subrequest.c @@ -62,10 +62,10 @@ static ngx_str_t ngx_http_lua_content_length_header_key = static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method, int forward_body, ngx_http_request_body_t *body, unsigned vars_action, - ngx_array_t *extra_vars); + ngx_array_t *extra_vars, ngx_array_t *extra_headers); static int ngx_http_lua_ngx_location_capture(lua_State *L); static int ngx_http_lua_ngx_location_capture_multi(lua_State *L); -static void ngx_http_lua_process_vars_option(ngx_http_request_t *r, +static void ngx_http_lua_process_keyval_option(ngx_http_request_t *r, lua_State *L, int table, ngx_array_t **varsp); static ngx_int_t ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *r, ngx_array_t *extra_vars); @@ -79,7 +79,7 @@ static void ngx_http_lua_cancel_subreq(ngx_http_request_t *r); static ngx_int_t ngx_http_post_request_to_head(ngx_http_request_t *r); static ngx_int_t ngx_http_lua_copy_in_file_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_lua_copy_request_headers(ngx_http_request_t *sr, - ngx_http_request_t *pr, int pr_not_chunked); + ngx_http_request_t *pr, int pr_not_chunked, ngx_array_t *extra_headers); enum { @@ -127,6 +127,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) ngx_http_lua_ctx_t *sr_ctx; ngx_http_lua_ctx_t *ctx; ngx_array_t *extra_vars; + ngx_array_t *extra_headers; ngx_str_t uri; ngx_str_t args; ngx_str_t extra_args; @@ -224,6 +225,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) coctx->pending_subreqs = 0; extra_vars = NULL; + extra_headers = NULL; for (index = 0; index < nsubreqs; index++) { coctx->pending_subreqs++; @@ -263,6 +265,11 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) extra_vars->nelts = 0; } + if (extra_headers != NULL) { + /* flush out existing elements in the array */ + extra_headers->nelts = 0; + } + vars_action = 0; custom_ctx = 0; @@ -318,7 +325,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) switch (lua_type(L, -1)) { case LUA_TTABLE: - ngx_http_lua_process_vars_option(r, L, -1, &extra_vars); + ngx_http_lua_process_keyval_option(r, L, -1, &extra_vars); dd("post process vars top: %d", lua_gettop(L)); break; @@ -335,6 +342,29 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) dd("queries query uri opts: %d", lua_gettop(L)); + /* check the headers option */ + + lua_getfield(L, 4, "headers"); + + switch (lua_type(L, -1)) { + case LUA_TTABLE: + ngx_http_lua_process_keyval_option(r, L, -1, &extra_headers); + + dd("post process vars top: %d", lua_gettop(L)); + break; + + case LUA_TNIL: + /* do nothing */ + break; + + default: + return luaL_error(L, "Bad headers option value"); + } + + lua_pop(L, 1); /* pop the headers */ + + dd("queries query uri opts: %d", lua_gettop(L)); + /* check the share_all_vars option */ lua_getfield(L, 4, "share_all_vars"); @@ -595,7 +625,8 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) ngx_http_set_ctx(sr, sr_ctx, ngx_http_lua_module); rc = ngx_http_lua_adjust_subrequest(sr, method, always_forward_body, - body, vars_action, extra_vars); + body, vars_action, extra_vars, + extra_headers); if (rc != NGX_OK) { ngx_http_lua_cancel_subreq(sr); @@ -631,7 +662,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) static ngx_int_t ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method, int always_forward_body, ngx_http_request_body_t *body, - unsigned vars_action, ngx_array_t *extra_vars) + unsigned vars_action, ngx_array_t *extra_vars, ngx_array_t *extra_headers) { ngx_http_request_t *r; ngx_http_core_main_conf_t *cmcf; @@ -667,7 +698,9 @@ ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method, } } - if (ngx_http_lua_copy_request_headers(sr, r, pr_not_chunked) != NGX_OK) { + if (ngx_http_lua_copy_request_headers(sr, r, pr_not_chunked, extra_headers) + != NGX_OK) + { return NGX_ERROR; } @@ -882,7 +915,7 @@ ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *sr, static void -ngx_http_lua_process_vars_option(ngx_http_request_t *r, lua_State *L, +ngx_http_lua_process_keyval_option(ngx_http_request_t *r, lua_State *L, int table, ngx_array_t **varsp) { ngx_array_t *vars; @@ -1635,10 +1668,11 @@ ngx_http_lua_copy_in_file_request_body(ngx_http_request_t *r) static ngx_int_t ngx_http_lua_copy_request_headers(ngx_http_request_t *sr, - ngx_http_request_t *pr, int pr_not_chunked) + ngx_http_request_t *pr, int pr_not_chunked, ngx_array_t *extra_headers) { ngx_table_elt_t *clh, *header; ngx_list_part_t *part; + ngx_keyval_t *header_keyval; ngx_chain_t *in; ngx_uint_t i; u_char *p; @@ -1742,6 +1776,20 @@ ngx_http_lua_copy_request_headers(ngx_http_request_t *sr, } } + if (extra_headers && extra_headers->nelts > 0) { + + header_keyval = extra_headers->elts; + + for (i = 0; i < extra_headers->nelts; i++, header_keyval++) { + + if (ngx_http_lua_set_input_header(sr, header_keyval->key, + header_keyval->value, 1) == NGX_ERROR) + { + return NGX_ERROR; + } + } + } + dd("after: parent req headers count: %d", (int) pr->headers_in.headers.part.nelts); diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_util.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_util.c index 8fd26561a..f1e0cd08f 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_util.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_util.c @@ -549,6 +549,10 @@ ngx_http_lua_send_header_if_needed(ngx_http_request_t *r, if (!ctx->buffering) { dd("sending headers"); rc = ngx_http_send_header(r); + if (r->filter_finalize) { + ngx_http_set_ctx(r, ctx, ngx_http_lua_module); + } + ctx->header_sent = 1; return rc; } @@ -599,6 +603,12 @@ ngx_http_lua_send_chain_link(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx, if (r->header_only) { ctx->eof = 1; + if (!r->request_body && r == r->main) { + if (ngx_http_discard_request_body(r) != NGX_OK) { + return NGX_ERROR; + } + } + if (ctx->buffering) { return ngx_http_lua_send_http10_headers(r, ctx); } diff --git a/src/deps/src/lua-nginx-module/src/ngx_http_lua_worker_thread.c b/src/deps/src/lua-nginx-module/src/ngx_http_lua_worker_thread.c index 3820d6377..ad747e810 100644 --- a/src/deps/src/lua-nginx-module/src/ngx_http_lua_worker_thread.c +++ b/src/deps/src/lua-nginx-module/src/ngx_http_lua_worker_thread.c @@ -194,11 +194,21 @@ ngx_http_lua_get_task_ctx(lua_State *L, ngx_http_request_t *r) static void ngx_http_lua_free_task_ctx(ngx_http_lua_task_ctx_t *ctx) { + lua_State *vm; + ctx->next = ctxpool->next; ctxpool->next = ctx; /* clean Lua stack */ - lua_settop(ctx->vm, 0); + vm = ctx->vm; + + /* call collectgarbage("collect") */ + lua_settop(vm, 0); + lua_getglobal(vm, "collectgarbage"); + lua_pushstring(vm, "collect"); + lua_pcall(vm, 1, 1, 0); + + lua_settop(vm, 0); } diff --git a/src/deps/src/lua-nginx-module/t/002-content.t b/src/deps/src/lua-nginx-module/t/002-content.t index 54de40ebd..eb9d587f8 100644 --- a/src/deps/src/lua-nginx-module/t/002-content.t +++ b/src/deps/src/lua-nginx-module/t/002-content.t @@ -1098,3 +1098,25 @@ failed to load inlined Lua code: content_by_lua(...45678901234567890123456789012 GET /lua --- response_body_like: 503 Service Temporarily Unavailable --- error_code: 503 + + + +=== TEST 52: send_header trigger filter finalize does not clear the ctx +--- config + location /lua { + content_by_lua_block { + ngx.header["Last-Modified"] = ngx.http_time(ngx.time()) + ngx.send_headers() + local phase = ngx.get_phase() + } + header_filter_by_lua_block { + ngx.header["X-Hello-World"] = "Hello World" + } + } +--- request +GET /lua +--- more_headers +If-Unmodified-Since: Wed, 01 Jan 2020 07:28:00 GMT +--- error_code: 412 +--- no_error_log +unknown phase: 0 diff --git a/src/deps/src/lua-nginx-module/t/014-bugs.t b/src/deps/src/lua-nginx-module/t/014-bugs.t index 1b79aa4c5..d34f42e23 100644 --- a/src/deps/src/lua-nginx-module/t/014-bugs.t +++ b/src/deps/src/lua-nginx-module/t/014-bugs.t @@ -828,7 +828,7 @@ qr/curl: \(28\) Operation timed out after \d+ milliseconds with 0 bytes received rewrite ^/myproxy/(.*) /$1 break; resolver_timeout 3s; #resolver 172.16.0.23; # AWS DNS resolver address is the same in all regions - 172.16.0.23 - resolver 8.8.8.8; + resolver $TEST_NGINX_RESOLVER; proxy_read_timeout 1s; proxy_send_timeout 1s; proxy_connect_timeout 1s; diff --git a/src/deps/src/lua-nginx-module/t/020-subrequest.t b/src/deps/src/lua-nginx-module/t/020-subrequest.t index c731f1e61..37914be06 100644 --- a/src/deps/src/lua-nginx-module/t/020-subrequest.t +++ b/src/deps/src/lua-nginx-module/t/020-subrequest.t @@ -1,6 +1,7 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: use Test::Nginx::Socket::Lua; +use Test::Nginx::Util 'is_tcp_port_used'; #master_on(); #workers(1); @@ -16,6 +17,16 @@ plan tests => repeat_each() * (blocks() * 3 + 23); $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); +# NB: tcp_listen_port needs to be greater than 10000, +# because the test cases expect it to be a 5-digit number +my $tcp_listen_port = 19113; +while (++$tcp_listen_port < 65535) { + if (!is_tcp_port_used $tcp_listen_port) { + last; + } +} +$ENV{TEST_NGINX_TCP_LISTEN_PORT} = $tcp_listen_port; + #no_diff(); no_long_string(); #no_shuffle(); @@ -1383,7 +1394,7 @@ upstream timed out #proxy_read_timeout 100ms; proxy_buffering on; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1396,7 +1407,7 @@ upstream timed out } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.0 200 OK\r\nContent-Length: 1024\r\n\r\nhello world" @@ -1443,7 +1454,7 @@ upstream prematurely closed connection proxy_read_timeout 100ms; proxy_buffering on; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1456,7 +1467,7 @@ upstream prematurely closed connection } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.0 200 OK\r\nContent-Length: 1024\r\n\r\nhello world" @@ -1505,7 +1516,7 @@ upstream timed out #proxy_read_timeout 100ms; proxy_buffering on; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1518,7 +1529,7 @@ upstream timed out } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.0 200 OK\r\n\r\nhello world" @@ -1565,7 +1576,7 @@ truncated: false proxy_read_timeout 100ms; proxy_buffering on; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1578,7 +1589,7 @@ truncated: false } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.0 200 OK\r\n\r\nhello world" @@ -1628,7 +1639,7 @@ upstream timed out #proxy_read_timeout 100ms; proxy_buffering off; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1641,7 +1652,7 @@ upstream timed out } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.0 200 OK\r\n\r\nhello world" @@ -1688,7 +1699,7 @@ truncated: false proxy_read_timeout 500ms; proxy_buffering off; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1701,7 +1712,7 @@ truncated: false } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.0 200 OK\r\n\r\nhello world" @@ -1914,7 +1925,7 @@ a client request body is buffered to a temporary file #proxy_read_timeout 100ms; proxy_http_version 1.1; proxy_buffering on; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1927,7 +1938,7 @@ a client request body is buffered to a temporary file } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nhello world\r" @@ -1977,7 +1988,7 @@ upstream prematurely closed connection #proxy_read_timeout 100ms; proxy_http_version 1.1; proxy_buffering off; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -1990,7 +2001,7 @@ upstream prematurely closed connection } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nhello world\r" @@ -2038,7 +2049,7 @@ upstream prematurely closed connection proxy_read_timeout 100ms; proxy_buffering on; proxy_http_version 1.1; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -2051,7 +2062,7 @@ upstream prematurely closed connection } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nhello world\r" @@ -2100,7 +2111,7 @@ upstream timed out #proxy_read_timeout 100ms; proxy_buffering on; proxy_http_version 1.1; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -2113,7 +2124,7 @@ upstream timed out } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n" @@ -2158,7 +2169,7 @@ truncated: false #proxy_read_timeout 100ms; proxy_buffering off; proxy_http_version 1.1; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -2171,7 +2182,7 @@ truncated: false } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_no_close --- tcp_reply eval "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n" @@ -2217,7 +2228,7 @@ truncated: false #proxy_read_timeout 100ms; proxy_buffering off; - proxy_pass http://127.0.0.1:$TEST_NGINX_RAND_PORT_2; + proxy_pass http://127.0.0.1:$TEST_NGINX_TCP_LISTEN_PORT; } location /main { @@ -2230,7 +2241,7 @@ truncated: false } --- request GET /main ---- tcp_listen: $TEST_NGINX_RAND_PORT_2 +--- tcp_listen: $TEST_NGINX_TCP_LISTEN_PORT --- tcp_query_len: 65 --- tcp_reply eval "HTTP/1.0 200 OK\r\nContent-Length: 1024\r\n\r\nhello world" @@ -3527,3 +3538,83 @@ HTTP/1.1 400 Bad Request [error] --- skip_nginx 3: < 1.21.1 + + + +=== TEST 83: avoid request smuggling of HEAD req +--- config + location /capture { + server_tokens off; + more_clear_headers Date; + + content_by_lua_block { + ngx.say("Hello") + } + } + + location /t { + content_by_lua_block { + local req = [[ +HEAD /capture HTTP/1.1 +Host: test.com +Content-Length: 63 + +GET /capture HTTP/1.1 +Host: test.com +X: GET /bar HTTP/1.0 + +]] + + local sock = ngx.socket.tcp() + sock:settimeout(1000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_SERVER_PORT) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send req: ", err) + return + end + + ngx.say("req bytes: ", bytes) + + local n_resp = 0 + + local reader = sock:receiveuntil("\r\n") + while true do + local line, err = reader() + if line then + ngx.say(line) + if line == "0" then + n_resp = n_resp + 1 + end + + if n_resp >= 2 then + break + end + + else + ngx.say("err: ", err) + break + end + end + + sock:close() + } + } +--- request +GET /t +--- response_body +req bytes: 117 +HTTP/1.1 200 OK +Server: nginx +Content-Type: text/plain +Connection: keep-alive + +err: timeout +--- error_log +lua tcp socket read timed out diff --git a/src/deps/src/lua-nginx-module/t/023-rewrite/request_body.t b/src/deps/src/lua-nginx-module/t/023-rewrite/request_body.t index 32c02e151..b867d3a82 100644 --- a/src/deps/src/lua-nginx-module/t/023-rewrite/request_body.t +++ b/src/deps/src/lua-nginx-module/t/023-rewrite/request_body.t @@ -170,26 +170,3 @@ Expect: 100-Continue http finalize request: 500, "/echo_body?" a:1, c:2 http finalize request: 500, "/echo_body?" a:1, c:0 --- log_level: debug ---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} - - - -=== TEST 9: test HTTP2 reading request body was disabled ---- config - location /echo_body { - lua_need_request_body on; - rewrite_by_lua_block { - ngx.print(ngx.var.request_body or "nil") - } - content_by_lua 'ngx.exit(ngx.OK)'; - } ---- http2 ---- request eval -"POST /echo_body -hello\x00\x01\x02 -world\x03\x04\xff" ---- more_headers -Content-Length: ---- response_body eval -"nil" ---- no_error_log diff --git a/src/deps/src/lua-nginx-module/t/024-access/request_body.t b/src/deps/src/lua-nginx-module/t/024-access/request_body.t index 0aa12c8b5..fa0319527 100644 --- a/src/deps/src/lua-nginx-module/t/024-access/request_body.t +++ b/src/deps/src/lua-nginx-module/t/024-access/request_body.t @@ -170,26 +170,3 @@ Expect: 100-Continue http finalize request: 500, "/echo_body?" a:1, c:2 http finalize request: 500, "/echo_body?" a:1, c:0 --- log_level: debug ---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} - - - -=== TEST 9: test HTTP2 reading request body was disabled ---- config - location /echo_body { - lua_need_request_body on; - access_by_lua_block { - ngx.print(ngx.var.request_body or "nil") - } - content_by_lua 'ngx.exit(ngx.OK)'; - } ---- http2 ---- request eval -"POST /echo_body -hello\x00\x01\x02 -world\x03\x04\xff" ---- more_headers -Content-Length: ---- response_body eval -"nil" ---- no_error_log diff --git a/src/deps/src/lua-nginx-module/t/027-multi-capture.t b/src/deps/src/lua-nginx-module/t/027-multi-capture.t index 929956168..b3cdbaff0 100644 --- a/src/deps/src/lua-nginx-module/t/027-multi-capture.t +++ b/src/deps/src/lua-nginx-module/t/027-multi-capture.t @@ -752,3 +752,75 @@ proxy_cache_path conf/cache levels=1:2 keys_zone=STATIC:10m inactive=10m max_siz GET /foo --- response_body ok + + + +=== TEST 14: capture multi with headers +--- config + location /foo { + content_by_lua_block { + local res1, res2, res3 = ngx.location.capture_multi{ + {"/test", { headers = { ["X-Test-Header"] = "aa"} } }, + {"/test", { headers = { ["X-Test-Header"] = "bb"} } }, + {"/test"}, + } + ngx.say("res1.status = " .. res1.status) + ngx.say("res1.body = " .. res1.body) + ngx.say("res2.status = " .. res2.status) + ngx.say("res2.body = " .. res2.body) + ngx.say("res3.status = " .. res3.status) + ngx.say("res3.body = " .. res3.body) + } + } + + location = /test { + content_by_lua_block { + ngx.print(ngx.var.http_x_test_header) + } + } +--- request + GET /foo +--- response_body +res1.status = 200 +res1.body = aa +res2.status = 200 +res2.body = bb +res3.status = 200 +res3.body = nil + + + +=== TEST 15: capture multi with headers override +--- config + location /foo { + content_by_lua_block { + local res1, res2, res3 = ngx.location.capture_multi{ + {"/test", { headers = { ["X-Test-Header"] = "aa"} } }, + {"/test", { headers = { ["X-Test-Header"] = "bb"} } }, + {"/test"}, + } + ngx.say("res1.status = " .. res1.status) + ngx.say("res1.body = " .. res1.body) + ngx.say("res2.status = " .. res2.status) + ngx.say("res2.body = " .. res2.body) + ngx.say("res3.status = " .. res3.status) + ngx.say("res3.body = " .. res3.body) + } + } + + location = /test { + content_by_lua_block { + ngx.print(ngx.var.http_x_test_header) + } + } +--- request + GET /foo +--- more_headers +X-Test-Header: cc +--- response_body +res1.status = 200 +res1.body = aa +res2.status = 200 +res2.body = bb +res3.status = 200 +res3.body = cc diff --git a/src/deps/src/lua-nginx-module/t/044-req-body.t b/src/deps/src/lua-nginx-module/t/044-req-body.t index f4509e149..d72b1eb63 100644 --- a/src/deps/src/lua-nginx-module/t/044-req-body.t +++ b/src/deps/src/lua-nginx-module/t/044-req-body.t @@ -7,7 +7,7 @@ log_level('warn'); repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 56); +plan tests => repeat_each() * (blocks() * 4 + 58); #no_diff(); no_long_string(); @@ -1774,23 +1774,3 @@ content length: 5 --- no_error_log [error] [alert] ---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} - - - -=== TEST 53: HTTP2 read buffered body was discarded ---- config - location = /test { - content_by_lua_block { - local err = pcall(ngx.req.read_body()) - ngx.say(err) - } - } ---- http2 ---- request -POST /test -hello, world ---- more_headers -Content-Length: ---- error_code: 500 ---- error_log: http2 requests are not supported without content-length header diff --git a/src/deps/src/lua-nginx-module/t/048-match-dfa.t b/src/deps/src/lua-nginx-module/t/048-match-dfa.t index edf3662d4..023231b5c 100644 --- a/src/deps/src/lua-nginx-module/t/048-match-dfa.t +++ b/src/deps/src/lua-nginx-module/t/048-match-dfa.t @@ -207,3 +207,41 @@ exec opts: 0 你 --- no_error_log [error] + + + +=== TEST 9: matched with do +--- config + location /re { + content_by_lua ' + local m = ngx.re.match("hello", "(h)(e)(l)", "jo") + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + ngx.say(m[3]) + else + ngx.say("not matched!") + end + local m = ngx.re.match("horld", "(h)(e)?(l)?", "jo") + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + ngx.say(m[3]) + else + ngx.say("not matched!") + end + '; + } +--- request + GET /re +--- response_body +hel +h +e +l +h +h +false +false diff --git a/src/deps/src/lua-nginx-module/t/062-count.t b/src/deps/src/lua-nginx-module/t/062-count.t index 07605f95b..957590292 100644 --- a/src/deps/src/lua-nginx-module/t/062-count.t +++ b/src/deps/src/lua-nginx-module/t/062-count.t @@ -481,7 +481,7 @@ n = 16 --- request GET /test --- response_body -n = 6 +n = 7 --- no_error_log [error] diff --git a/src/deps/src/lua-nginx-module/t/068-socket-keepalive.t b/src/deps/src/lua-nginx-module/t/068-socket-keepalive.t index 5ca94e4b7..626b44167 100644 --- a/src/deps/src/lua-nginx-module/t/068-socket-keepalive.t +++ b/src/deps/src/lua-nginx-module/t/068-socket-keepalive.t @@ -3029,3 +3029,167 @@ connected: 1, reused: 0 --- error_log lua tcp socket keepalive create connection pool for key "A" lua tcp socket keepalive create connection pool for key "B" + + + +=== TEST 54: wrong first argument for setkeepalive +--- quic_max_idle_timeout: 1.2 +--- http_config eval + "lua_package_path '$::HtmlDir/?.lua;./?.lua;;';" +--- config + server_tokens off; + location /t { + keepalive_timeout 60s; + + set $port $TEST_NGINX_SERVER_PORT; + content_by_lua_block { + local port = ngx.var.port + + local sock = ngx.socket.tcp() + + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: keepalive\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + local reader = sock:receiveuntil("\r\n0\r\n\r\n") + local data, err = reader() + + if not data then + ngx.say("failed to receive response body: ", err) + return + end + + ngx.say("received response of ", #data, " bytes") + + ok, err = sock:setkeepalive() + if not ok then + ngx.say("failed to set reusable: ", err) + end + + ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ok, err = sock:setkeepalive("not a number", "not a number") + if not ok then + ngx.say("failed to set reusable: ", err) + end + } + } + + location /foo { + echo foo; + } + + location /sleep { + echo_sleep 1; + } +--- request +GET /t +--- error_code: +--- response_body +--- error_log eval +qr/\Qbad argument #1 to 'setkeepalive' (number expected, got string)\E/ +--- no_error_log +[crit] +--- timeout: 4 +--- curl_error eval +qr{HTTP/3 stream 0 reset by server} + + + +=== TEST 55: wrong second argument for setkeepalive +--- quic_max_idle_timeout: 1.2 +--- http_config eval + "lua_package_path '$::HtmlDir/?.lua;./?.lua;;';" +--- config + server_tokens off; + location /t { + keepalive_timeout 60s; + + set $port $TEST_NGINX_SERVER_PORT; + content_by_lua_block { + local port = ngx.var.port + + local sock = ngx.socket.tcp() + + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: keepalive\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + local reader = sock:receiveuntil("\r\n0\r\n\r\n") + local data, err = reader() + + if not data then + ngx.say("failed to receive response body: ", err) + return + end + + ngx.say("received response of ", #data, " bytes") + + ok, err = sock:setkeepalive() + if not ok then + ngx.say("failed to set reusable: ", err) + end + + ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ok, err = sock:setkeepalive(10, "not a number") + if not ok then + ngx.say("failed to set reusable: ", err) + end + } + } + + location /foo { + echo foo; + } + + location /sleep { + echo_sleep 1; + } +--- request +GET /t +--- error_code: +--- response_body +--- error_log eval +qr/\Qbad argument #2 to 'setkeepalive' (number expected, got string)\E/ +--- no_error_log +[crit] +--- timeout: 4 +--- curl_error eval +qr{HTTP/3 stream 0 reset by server} diff --git a/src/deps/src/lua-nginx-module/t/082-body-filter-2.t b/src/deps/src/lua-nginx-module/t/082-body-filter-2.t index ffccad28a..3c9b9797d 100644 --- a/src/deps/src/lua-nginx-module/t/082-body-filter-2.t +++ b/src/deps/src/lua-nginx-module/t/082-body-filter-2.t @@ -225,3 +225,47 @@ GET /t [error] [alert] [crit] + + + +=== TEST 4: set resp body nil with ngx.arg[1] first +--- config + location /t { + content_by_lua_block { + ngx.say("Hello World!") + } + + body_filter_by_lua_block { + ngx.arg[1] = "" + ngx.arg[2] = true + } + } +--- request +GET /t +--- response_body +--- no_error_log +[error] +[alert] +[crit] + + + +=== TEST 5: set resp body nil with ngx.arg[2] first +--- config + location /t { + content_by_lua_block { + ngx.say("Hello World!") + } + + body_filter_by_lua_block { + ngx.arg[2] = true + ngx.arg[1] = "" + } + } +--- request +GET /t +--- response_body +--- no_error_log +[error] +[alert] +[crit] diff --git a/src/deps/src/lua-nginx-module/t/087-udp-socket.t b/src/deps/src/lua-nginx-module/t/087-udp-socket.t index ffe6b13e9..d1bc65436 100644 --- a/src/deps/src/lua-nginx-module/t/087-udp-socket.t +++ b/src/deps/src/lua-nginx-module/t/087-udp-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (3 * blocks() + 15); +plan tests => repeat_each() * (3 * blocks() + 16); our $HtmlDir = html_dir; @@ -1222,3 +1222,113 @@ qr/send: fd:\d+ 22 of 22 send: fd:\d+ 16 of 16 send: fd:\d+ 22 of 22/ --- log_level: debug + + + +=== TEST 23: udp bind +--- config + server_tokens off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + #set $port 1234; + + content_by_lua_block { + local socket = ngx.socket + local udp = socket.udp() + + local port = ngx.var.port + udp:settimeout(1000) -- 1 sec + + local ok, err = udp:bind("127.0.0.10") + if not ok then + ngx.say("failed to bind: ", err) + return + end + + local ok, err = udp:setpeername("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected") + + local req = "\0\1\0\0\0\1\0\0flush_all\r\n" + local ok, err = udp:send(req) + if not ok then + ngx.say("failed to send: ", err) + return + end + + local data, err = udp:receive() + if not data then + ngx.say("failed to receive data: ", err) + return + end + ngx.print("received ", #data, " bytes: ", data) + } + } +--- request +GET /t +--- response_body eval +"connected\nreceived 12 bytes: \x{00}\x{01}\x{00}\x{00}\x{00}\x{01}\x{00}\x{00}OK\x{0d}\x{0a}" +--- no_error_log +[error] +--- log_level: debug +--- error_log +lua udp socket receive buffer size: 65536 + + + +=== TEST 24: udp bind failed +--- config + server_tokens off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + #set $port 1234; + + content_by_lua_block { + local socket = ngx.socket + local udp = socket.udp() + + local port = ngx.var.port + udp:settimeout(1000) -- 1 sec + + local ok, err = udp:bind("127.0.0.1000") + if not ok then + ngx.say("failed to bind: ", err) + return + end + + local ok, err = udp:setpeername("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected") + + local req = "\0\1\0\0\0\1\0\0flush_all\r\n" + local ok, err = udp:send(req) + if not ok then + ngx.say("failed to send: ", err) + return + end + + local data, err = udp:receive() + if not data then + ngx.say("failed to receive data: ", err) + return + end + ngx.print("received ", #data, " bytes: ", data) + } + } +--- request +GET /t +--- response_body +failed to bind: bad address +--- no_error_log +[error] +--- log_level: debug diff --git a/src/deps/src/lua-nginx-module/t/129-ssl-socket.t b/src/deps/src/lua-nginx-module/t/129-ssl-socket.t index ccfa19fff..ca8d5a49e 100644 --- a/src/deps/src/lua-nginx-module/t/129-ssl-socket.t +++ b/src/deps/src/lua-nginx-module/t/129-ssl-socket.t @@ -1484,6 +1484,72 @@ SSL reused session === TEST 18: openresty.org: passing SSL verify: keepalive (no reusing the ssl session) +The session returned by SSL_get1_session maybe different. +After function tls_process_new_session_ticket, the session saved in SSL->session +will be replace by a new one. + +ngx_ssl_session_t * +ngx_ssl_get_session(ngx_connection_t *c) +{ +#ifdef TLS1_3_VERSION + if (c->ssl->session) { + SSL_SESSION_up_ref(c->ssl->session); + return c->ssl->session; + } +#endif + + return SSL_get1_session(c->ssl->connection); +} + +SSL_SESSION *SSL_get1_session(SSL *ssl) +/* variant of SSL_get_session: caller really gets something */ +{ + SSL_SESSION *sess; + /* + * Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's non-null + * and when we up the reference count. + */ + CRYPTO_THREAD_read_lock(ssl->lock); + sess = ssl->session; + if (sess) + SSL_SESSION_up_ref(sess); + CRYPTO_THREAD_unlock(ssl->lock); + return sess; +} + +#0 tls_process_new_session_ticket (s=0x7e6ea0, pkt=0x7fffffffc820) at ssl/statem/statem_clnt.c:2650 +#1 0x00007ffff7af50fd in read_state_machine (s=0x7e6ea0) at ssl/statem/statem.c:636 +#2 state_machine (s=0x7e6ea0, server=0) at ssl/statem/statem.c:434 +#3 0x00007ffff7aca6b3 in ssl3_read_bytes (s=, type=23, recvd_type=0x0, buf=0x7fffffffc9d7 "\027\320\355t", len=1, + peek=0, readbytes=0x7fffffffc978) at ssl/record/rec_layer_s3.c:1677 +#4 0x00007ffff7ad2250 in ssl3_read_internal (readbytes=0x7fffffffc978, peek=0, len=1, buf=0x7fffffffc9d7, s=0x7e6ea0) + at ssl/s3_lib.c:4477 +#5 ssl3_read (s=0x7e6ea0, buf=0x7fffffffc9d7, len=1, readbytes=0x7fffffffc978) at ssl/s3_lib.c:4500 +#6 0x00007ffff7ade695 in SSL_read (s=, buf=buf@entry=0x7fffffffc9d7, num=num@entry=1) at ssl/ssl_lib.c:1799 +#7 0x000000000045a965 in ngx_ssl_recv (c=0x72c3b0, buf=0x7fffffffc9d7 "\027\320\355t", size=1) + at src/event/ngx_event_openssl.c:2337 +#8 0x0000000000533b17 in ngx_http_lua_socket_keepalive_close_handler (ev=0x7e2f20) + at /var/code/openresty/lua-nginx-module/src/ngx_http_lua_socket_tcp.c:5753 +#9 0x000000000052cf40 in ngx_http_lua_socket_tcp_setkeepalive (L=0x74edd0) + at /var/code/openresty/lua-nginx-module/src/ngx_http_lua_socket_tcp.c:5602 +#10 0x00007ffff7f0fabe in lj_BC_FUNCC () + from /tmp/undodb.72729.1722915526.2470007.80d50d088e818fd4/debuggee-1-zwqz8svp/symbol-files/opt/luajit-sysm/lib/libluajit-5.1.so.2 +#11 0x000000000051f2b2 in ngx_http_lua_run_thread (L=L@entry=0x767670, r=r@entry=0x7edf80, ctx=ctx@entry=0x750e40, nrets=0) + at /var/code/openresty/lua-nginx-module/src/ngx_http_lua_util.c:1194 +#12 0x0000000000524347 in ngx_http_lua_content_by_chunk (L=0x767670, r=0x7edf80) + at /var/code/openresty/lua-nginx-module/src/ngx_http_lua_contentby.c:124 +#13 0x000000000047c663 in ngx_http_core_content_phase (r=0x7edf80, ph=0x7b4470) at src/http/ngx_http_core_module.c:1271 +#14 0x000000000047b80d in ngx_http_core_run_phases (r=0x7edf80) at src/http/ngx_http_core_module.c:885 +#15 ngx_http_handler (r=r@entry=0x7edf80) at src/http/ngx_http_core_module.c:868 +#16 0x00000000004854ad in ngx_http_process_request (r=r@entry=0x7edf80) at src/http/ngx_http_request.c:2140 +#17 0x00000000004868e8 in ngx_http_process_request_headers (rev=rev@entry=0x7e2f80) at src/http/ngx_http_request.c:1529 +#18 0x0000000000486468 in ngx_http_process_request_line (rev=0x7e2f80) at src/http/ngx_http_request.c:1196 +#19 0x000000000044b338 in ngx_event_process_posted (cycle=cycle@entry=0x721690, posted=0x62f250 ) + at src/event/ngx_event_posted.c:35 +#20 0x000000000044a522 in ngx_process_events_and_timers (cycle=cycle@entry=0x721690) at src/event/ngx_event.c:273 +#21 0x0000000000453819 in ngx_single_process_cycle (cycle=cycle@entry=0x721690) at src/os/unix/ngx_process_cycle.c:323 +#22 0x0000000000429dee in main (argc=argc@entry=5, argv=argv@entry=0x7fffffffd1a8) at src/core/nginx.c:384 --- config server_tokens off; resolver $TEST_NGINX_RESOLVER ipv6=off; @@ -1548,11 +1614,11 @@ set keepalive: 1 nil --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out eval qr/^lua ssl save session: ([0-9A-F]+) -lua ssl save session: \1 -lua ssl save session: \1 -lua ssl free session: \1 -lua ssl free session: \1 -lua ssl free session: \1 +lua ssl save session: ([0-9A-F]+) +lua ssl save session: ([0-9A-F]+) +lua ssl free session: ([0-9A-F]+) +lua ssl free session: ([0-9A-F]+) +lua ssl free session: ([0-9A-F]+) $/ --- error_log diff --git a/src/deps/src/lua-nginx-module/t/138-balancer.t b/src/deps/src/lua-nginx-module/t/138-balancer.t index 8ccdee76c..41be75fcd 100644 --- a/src/deps/src/lua-nginx-module/t/138-balancer.t +++ b/src/deps/src/lua-nginx-module/t/138-balancer.t @@ -12,7 +12,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 9); +plan tests => repeat_each() * (blocks() * 4 + 7); #no_diff(); no_long_string(); @@ -571,7 +571,7 @@ upstream sent more data than specified in "Content-Length" header while reading -=== TEST 18: error in balancer_by_llua_block +=== TEST 18: error in balancer_by_lua_block --- http_config upstream backend { server 0.0.0.1; @@ -591,3 +591,90 @@ upstream sent more data than specified in "Content-Length" header while reading "failed to load inlined Lua code: balancer_by_lua(nginx.conf:27):3: ')' expected (to close '(' at line 2) near ''", --- no_error_log [warn] + + + +=== TEST 19: disable ssl +--- http_config + lua_package_path "$TEST_NGINX_SERVER_ROOT/html/?.lua;;"; + + upstream backend { + server 127.0.0.1:$TEST_NGINX_SERVER_PORT; + balancer_by_lua_block { + local ffi = require "ffi" + local C = ffi.C +ffi.cdef[[ +int +ngx_http_lua_ffi_balancer_set_upstream_tls(ngx_http_request_t *r, int on, char **err); +]] + local errmsg = ffi.new("char *[1]") + local r = require "resty.core.base" .get_request() + if r == nil then + ngx.log(ngx.ERR, "no request found") + return + end + + local rc = C.ngx_http_lua_ffi_balancer_set_upstream_tls(r, 0, errmsg) + if rc < 0 then + ngx.log(ngx.ERR, "failed to disable ssl: ", ffi.string(errmsg[0])) + return + end + } + } +--- config + location = /t { + proxy_pass https://backend/back; + } + + location = /back { + echo ok; + } + +--- request + GET /t +--- response_body +ok +--- no_error_log +[error] +[cirt] + + + +=== TEST 20: recreate_request refresh body buffer when ngx.req.set_body_data is used in balancer phase +--- http_config + lua_package_path "../lua-resty-core/lib/?.lua;;"; + + server { + listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1; + + location / { + content_by_lua_block { + ngx.req.read_body() + local body = ngx.req.get_body_data() + ngx.log(ngx.ERR, "body: ", body) + ngx.say(body) + } + } + } + + upstream foo { + server 127.0.0.1:$TEST_NGINX_RAND_PORT_1 max_fails=0; + + balancer_by_lua_block { + local bal = require "ngx.balancer" + ngx.req.set_body_data("hello world") + assert(bal.recreate_request()) + } + } + +--- config + location = /t { + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_pass http://foo; + } +--- request +GET /t +--- error_code: 200 +--- response_body +hello world diff --git a/src/deps/src/lua-nginx-module/t/140-ssl-c-api.t b/src/deps/src/lua-nginx-module/t/140-ssl-c-api.t index 5b2ae018f..4c81b4f05 100644 --- a/src/deps/src/lua-nginx-module/t/140-ssl-c-api.t +++ b/src/deps/src/lua-nginx-module/t/140-ssl-c-api.t @@ -12,7 +12,7 @@ if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); } else { - plan tests => repeat_each() * (blocks() * 5 + 1); + plan tests => repeat_each() * (blocks() * 5 - 1); } $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -53,6 +53,12 @@ ffi.cdef[[ void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, size_t pem_len, char **err); + void *ngx_http_lua_ffi_parse_der_cert(const char *data, size_t len, + char **err); + + void *ngx_http_lua_ffi_parse_der_priv_key(const char *data, size_t len, + char **err); + int ngx_http_lua_ffi_set_cert(void *r, void *cdata, char **err); @@ -66,7 +72,10 @@ ffi.cdef[[ void ngx_http_lua_ffi_free_priv_key(void *cdata); int ngx_http_lua_ffi_ssl_verify_client(void *r, void *cdata, - int depth, char **err); + void *cdata, int depth, char **err); + + int ngx_http_lua_ffi_ssl_client_random(ngx_http_request_t *r, + unsigned char *out, size_t *outlen, char **err); ]] _EOC_ @@ -844,21 +853,21 @@ lua ssl server name: "test.com" local cert_data = f:read("*all") f:close() - local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) - if not cert then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", + local client_cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not client_cert then + ngx.log(ngx.ERR, "failed to parse PEM client cert: ", ffi.string(errmsg[0])) return end - local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, cert, 1, errmsg) + local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, client_cert, nil, 1, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to verify client: ", ffi.string(errmsg[0])) return end - ffi.C.ngx_http_lua_ffi_free_cert(cert) + ffi.C.ngx_http_lua_ffi_free_cert(client_cert) } ssl_certificate ../../cert/test2.crt; @@ -915,7 +924,7 @@ client certificate subject: emailAddress=agentzh@gmail.com,CN=test.com return end - local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, nil, -1, errmsg) + local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, nil, nil, -1, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to verify client: ", ffi.string(errmsg[0])) @@ -981,21 +990,21 @@ client certificate subject: emailAddress=agentzh@gmail.com,CN=test.com local cert_data = f:read("*all") f:close() - local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) - if not cert then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", + local client_cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not client_cert then + ngx.log(ngx.ERR, "failed to parse PEM client cert: ", ffi.string(errmsg[0])) return end - local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, cert, 1, errmsg) + local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, client_cert, nil, 1, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to verify client: ", ffi.string(errmsg[0])) return end - ffi.C.ngx_http_lua_ffi_free_cert(cert) + ffi.C.ngx_http_lua_ffi_free_cert(client_cert) } ssl_certificate ../../cert/test2.crt; @@ -1323,3 +1332,448 @@ SNI is test.com --- no_error_log [error] [alert] + + + +=== TEST 11: DER cert + private key cdata +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + require "defines" + + local errmsg = ffi.new("char *[1]") + + local r = require "resty.core.base" .get_request() + if r == nil then + ngx.log(ngx.ERR, "no request found") + return + end + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test_der.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local cert = ffi.C.ngx_http_lua_ffi_parse_der_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse DER cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(cert) + + f = assert(io.open("t/cert/test_der.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local pkey = ffi.C.ngx_http_lua_ffi_parse_der_priv_key(pkey_data, #pkey_data, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse DER priv key: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: cdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 12: client random +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + require "defines" + + local errmsg = ffi.new("char *[1]") + + local r = require "resty.core.base" .get_request() + if r == nil then + ngx.log(ngx.ERR, "no request found") + return + end + + -- test client random length + local out = ffi.new("unsigned char[?]", 0) + local sizep = ffi.new("size_t[1]", 0) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_client_random(r, out, sizep, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to get client random length: ", + ffi.string(errmsg[0])) + return + end + + if tonumber(sizep[0]) ~= 32 then + ngx.log(ngx.ERR, "client random length does not equal 32") + return + end + + -- test client random value + out = ffi.new("unsigned char[?]", 50) + sizep = ffi.new("size_t[1]", 50) + + rc = ffi.C.ngx_http_lua_ffi_ssl_client_random(r, out, sizep, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to get client random: ", + ffi.string(errmsg[0])) + return + end + + local init_v = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + if ffi.string(out, sizep[0]) == init_v then + ngx.log(ngx.ERR, "maybe the client random value is incorrect") + return + end + } + + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: cdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 13: verify client, but server don't trust root ca +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name example.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + require "defines" + local ffi = require "ffi" + + local errmsg = ffi.new("char *[1]") + + local r = require "resty.core.base" .get_request() + if r == nil then + ngx.log(ngx.ERR, "no request found") + return + end + + local f = assert(io.open("t/cert/mtls_server.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local client_cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not client_cert then + ngx.log(ngx.ERR, "failed to parse PEM client cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, client_cert, nil, 2, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to verify client: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(client_cert) + } + + ssl_certificate ../../cert/mtls_server.crt; + ssl_certificate_key ../../cert/mtls_server.key; + + location / { + default_type 'text/plain'; + content_by_lua_block { + ngx.say(ngx.var.ssl_client_verify) + } + more_clear_headers Date; + } + } +--- config + location /t { + proxy_pass https://unix:$TEST_NGINX_HTML_DIR/nginx.sock; + proxy_ssl_certificate ../../cert/mtls_client.crt; + proxy_ssl_certificate_key ../../cert/mtls_client.key; + proxy_ssl_session_reuse off; + } + +--- request +GET /t +--- response_body +FAILED:unable to verify the first certificate + +--- no_error_log +[error] +[alert] + + + +=== TEST 14: verify client and server trust root ca +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name example.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + require "defines" + local ffi = require "ffi" + + local errmsg = ffi.new("char *[1]") + + local r = require "resty.core.base" .get_request() + if r == nil then + ngx.log(ngx.ERR, "no request found") + return + end + + local f = assert(io.open("t/cert/mtls_server.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local client_cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not client_cert then + ngx.log(ngx.ERR, "failed to parse PEM client cert: ", + ffi.string(errmsg[0])) + return + end + + local f = assert(io.open("t/cert/mtls_ca.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local trusted_cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not trusted_cert then + ngx.log(ngx.ERR, "failed to parse PEM trusted cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_ssl_verify_client(r, cert, trusted_cert, 2, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to verify client: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(client_cert) + ffi.C.ngx_http_lua_ffi_free_cert(trusted_cert) + } + + ssl_certificate ../../cert/mtls_server.crt; + ssl_certificate_key ../../cert/mtls_server.key; + + location / { + default_type 'text/plain'; + content_by_lua_block { + ngx.say(ngx.var.ssl_client_verify) + } + more_clear_headers Date; + } + } +--- config + location /t { + proxy_pass https://unix:$TEST_NGINX_HTML_DIR/nginx.sock; + proxy_ssl_certificate ../../cert/mtls_client.crt; + proxy_ssl_certificate_key ../../cert/mtls_client.key; + proxy_ssl_session_reuse off; + } + +--- request +GET /t +--- response_body +SUCCESS + +--- no_error_log +[error] +[alert] diff --git a/src/deps/src/lua-nginx-module/t/163-signal.t b/src/deps/src/lua-nginx-module/t/163-signal.t index 15f41e220..0ce8fa261 100644 --- a/src/deps/src/lua-nginx-module/t/163-signal.t +++ b/src/deps/src/lua-nginx-module/t/163-signal.t @@ -5,6 +5,9 @@ our $SkipReason; BEGIN { if ($ENV{TEST_NGINX_USE_HUP}) { $SkipReason = "unavailable under hup test mode"; + + } elsif ($ENV{TEST_NGINX_CHECK_LEAK}) { + $SkipReason = "unavailable under check leak test mode"; } } diff --git a/src/deps/src/lua-nginx-module/t/166-worker-thread.t b/src/deps/src/lua-nginx-module/t/166-worker-thread.t index 925a06094..1cbeec5eb 100644 --- a/src/deps/src/lua-nginx-module/t/166-worker-thread.t +++ b/src/deps/src/lua-nginx-module/t/166-worker-thread.t @@ -1602,3 +1602,74 @@ return {hello=hello} GET /hello --- response_body false , suspicious circular references, table depth exceed max depth: 100 in the argument + + + +=== TEST 50: call run_worker_thread twice +--- main_config + thread_pool testpool threads=1; +--- http_config eval + "lua_package_path '$::HtmlDir/?.lua;./?.lua;;';" +--- config +location /hello { + default_type 'text/plain'; + + content_by_lua_block { + local ok, hello_or_err = ngx.run_worker_thread("testpool", "hello", "hello") + ngx.say(ok, " : ", hello_or_err) + + ok, hello_or_err = ngx.run_worker_thread("testpool", "hello", "hello") + ngx.say(ok, " : ", hello_or_err) + } +} +--- user_files +>>> hello.lua +local function hello() + return "hello" +end +return {hello=hello} +--- request +GET /hello +--- response_body +true : hello +true : hello + + + +=== TEST 51: big object +--- main_config + thread_pool testpool threads=1; +--- http_config eval + "lua_package_path '$::HtmlDir/?.lua;./?.lua;;';" +--- config +location /hello { + default_type 'text/plain'; + + content_by_lua_block { + local ok, hello_or_err = ngx.run_worker_thread("testpool", "hello", "hello") + ngx.say(ok, " : ", #hello_or_err) + + local ok, gcsize_or_err = ngx.run_worker_thread("testpool", "hello", "gcsize") + ngx.say(ok, " : ", gcsize_or_err) + } +} +--- user_files +>>> hello.lua +local function hello() + return string.rep("helloworld", 1000000) +end + +local function gcsize() + return collectgarbage("count") +end + +return { + hello = hello, + gcsize = gcsize +} +--- request +GET /hello +--- response_body eval +qr/\Atrue : 10000000 +true : \d{3,4}\.\d+ +\z/ms diff --git a/src/deps/src/lua-nginx-module/t/188-balancer_keepalive_pool_max_retry.t b/src/deps/src/lua-nginx-module/t/188-balancer_keepalive_pool_max_retry.t new file mode 100644 index 000000000..679ee680f --- /dev/null +++ b/src/deps/src/lua-nginx-module/t/188-balancer_keepalive_pool_max_retry.t @@ -0,0 +1,89 @@ +# vim:set ft= ts=4 sw=4 et: + +use Test::Nginx::Socket::Lua; +use Cwd qw(cwd); + +log_level('info'); +repeat_each(1); + +plan tests => repeat_each() * (blocks() * 6); + +my $pwd = cwd(); + +no_long_string(); + +check_accum_error_log(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- http_config + lua_shared_dict request_counter 1m; + upstream my_upstream { + server 127.0.0.1; + balancer_by_lua_block { + local balancer = require "ngx.balancer" + + if not ngx.ctx.tries then + ngx.ctx.tries = 0 + end + + ngx.ctx.tries = ngx.ctx.tries + 1 + ngx.log(ngx.INFO, "tries ", ngx.ctx.tries) + + if ngx.ctx.tries == 1 then + balancer.set_more_tries(5) + end + + local host = "127.0.0.1" + local port = $TEST_NGINX_RAND_PORT_1; + + local ok, err = balancer.set_current_peer(host, port) + if not ok then + ngx.log(ngx.ERR, "failed to set the current peer: ", err) + return ngx.exit(500) + end + + balancer.set_timeouts(60000, 60000, 60000) + + local ok, err = balancer.enable_keepalive(60, 100) + if not ok then + ngx.log(ngx.ERR, "failed to enable keepalive: ", err) + return ngx.exit(500) + end + } + } + + server { + listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1; + location /hello { + content_by_lua_block{ + local request_counter = ngx.shared.request_counter + local first_request = request_counter:get("first_request") + if first_request == nil then + request_counter:set("first_request", "yes") + ngx.print("hello") + else + ngx.exit(ngx.HTTP_CLOSE) + end + } + } + } +--- config + location = /t { + proxy_pass http://my_upstream; + proxy_set_header Connection "keep-alive"; + + rewrite_by_lua_block { + ngx.req.set_uri("/hello") + } + } +--- pipelined_requests eval +["GET /t HTTP/1.1" , "GET /t HTTP/1.1"] +--- response_body eval +["hello", qr/502/] +--- error_code eval +[200, 502] +--- no_error_log eval +qr/tries 7/ diff --git a/src/deps/src/lua-nginx-module/t/cert/test_der.crt b/src/deps/src/lua-nginx-module/t/cert/test_der.crt new file mode 100644 index 000000000..273b98638 Binary files /dev/null and b/src/deps/src/lua-nginx-module/t/cert/test_der.crt differ diff --git a/src/deps/src/lua-nginx-module/t/cert/test_der.key b/src/deps/src/lua-nginx-module/t/cert/test_der.key new file mode 100644 index 000000000..14e9fa582 Binary files /dev/null and b/src/deps/src/lua-nginx-module/t/cert/test_der.key differ diff --git a/src/deps/src/lua-nginx-module/util/build.sh b/src/deps/src/lua-nginx-module/util/build.sh index 41896f2c7..fdf5c4d53 100644 --- a/src/deps/src/lua-nginx-module/util/build.sh +++ b/src/deps/src/lua-nginx-module/util/build.sh @@ -25,13 +25,13 @@ force=$2 add_fake_shm_module="--add-module=$root/t/data/fake-shm-module" add_http3_module=--with-http_v3_module -answer=`$root/util/ver-ge "$NGINX_VERSION" 1.25.1` +answer=`$root/util/ver-ge "$version" 1.25.1` if [ "$OPENSSL_VER" = "1.1.0l" ] || [ "$answer" = "N" ]; then add_http3_module="" fi disable_pcre2=--without-pcre2 -answer=`$root/util/ver-ge "$NGINX_VERSION" 1.25.1` +answer=`$root/util/ver-ge "$version" 1.25.1` if [ "$answer" = "N" ] || [ "$USE_PCRE2" = "Y" ]; then disable_pcre2="" fi