diff --git a/.travis.yml b/.travis.yml index e583826a6..8a66ff2cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ env: - TEST_NGINX_RANDOMIZE=1 - LUACHECK_VER=0.21.1 matrix: - - NGINX_VERSION=1.27.0 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f USE_PCRE2=Y + - NGINX_VERSION=1.27.1 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f USE_PCRE2=Y - NGINX_VERSION=1.25.3 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f services: diff --git a/README.markdown b/README.markdown index df2ba4bd1..65a6df161 100644 --- a/README.markdown +++ b/README.markdown @@ -169,6 +169,7 @@ API Implemented * [ngx.encode_base64](https://github.com/openresty/lua-nginx-module#ngxencode_base64) * [ngx.decode_base64](https://github.com/openresty/lua-nginx-module#ngxdecode_base64) +* [ngx.decode_base64mime](https://github.com/openresty/lua-nginx-module#ngxdecode_base64mime) [Back to TOC](#table-of-contents) diff --git a/dist.ini b/dist.ini index 1231145e8..f4a40ffc0 100644 --- a/dist.ini +++ b/dist.ini @@ -7,4 +7,4 @@ lib_dir=lib doc_dir=lib repo_link=https://github.com/openresty/lua-resty-core main_module=lib/resty/core/base.lua -requires = luajit >= 2.1.0, nginx >= 1.13.6, ngx_http_lua = 0.10.13, openresty/lua-resty-lrucache >= 0.08 +requires = luajit >= 2.1.0, nginx >= 1.27.1, ngx_http_lua = 0.10.28, openresty/lua-resty-lrucache >= 0.08 diff --git a/lib/ngx/resp.lua b/lib/ngx/resp.lua index b02847fc9..28d1ed4aa 100644 --- a/lib/ngx/resp.lua +++ b/lib/ngx/resp.lua @@ -1,10 +1,20 @@ -- Copyright (C) Yichun Zhang. All rights reserved. +local ffi = require "ffi" +local C = ffi.C + local base = require "resty.core.base" base.allows_subsystem('http') +local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT local core_response = require "resty.core.response" local set_resp_header = core_response.set_resp_header +local get_request = base.get_request + +ffi.cdef[[ + int ngx_http_lua_ffi_set_resp_status_and_reason(ngx_http_request_t *r, + int status, const char *reason, size_t reason_len); +]] local _M = { version = base.version } @@ -15,4 +25,22 @@ function _M.add_header(key, value) end +function _M.set_status(status, reason) + local r = get_request() + + if not r then + error("no request found") + end + + if type(status) ~= 'number' then + status = tonumber(status) + end + + local rc = C.ngx_http_lua_ffi_set_resp_status_and_reason(r, status, + reason, #reason) + if rc == FFI_BAD_CONTEXT then + error("API disabled in the current context", 2) + end +end + return _M diff --git a/lib/ngx/resp.md b/lib/ngx/resp.md index 5ad8e249d..01f8c4729 100644 --- a/lib/ngx/resp.md +++ b/lib/ngx/resp.md @@ -12,6 +12,7 @@ Table of Contents * [Description](#description) * [Methods](#methods) * [add_header](#add_header) + * [set_status](#set_status) * [Community](#community) * [English Mailing List](#english-mailing-list) * [Chinese Mailing List](#chinese-mailing-list) @@ -35,6 +36,10 @@ ngx_resp.add_header("Foo", "bar") ngx_resp.add_header("Foo", "baz") --> there will be two new headers in HTTP response: --> Foo: bar and Foo: baz + + +ngx_resp.set(531, "user defined error") +--> the response line will be: 531 user defiend error ``` [Back to TOC](#table-of-contents) @@ -73,6 +78,15 @@ instead of appending it. [Back to TOC](#table-of-contents) +set_status +---------- +**syntax:** *ngx_resp.status(status, reason?)* + +Unlike `ngx.status` which only sets the status, this function sets the response +status with an optional reason. The `reason` should be a string. + +[Back to TOC](#table-of-contents) + Community ========= diff --git a/lib/resty/core/base.lua b/lib/resty/core/base.lua index 84e1affee..801350b57 100644 --- a/lib/resty/core/base.lua +++ b/lib/resty/core/base.lua @@ -19,22 +19,22 @@ local FREE_LIST_REF = 0 if subsystem == 'http' then if not ngx.config or not ngx.config.ngx_lua_version - or ngx.config.ngx_lua_version ~= 10027 + or ngx.config.ngx_lua_version ~= 10028 then - error("ngx_http_lua_module 0.10.27 required") + error("ngx_http_lua_module 0.10.28 required") end elseif subsystem == 'stream' then if not ngx.config or not ngx.config.ngx_lua_version - or ngx.config.ngx_lua_version ~= 15 + or ngx.config.ngx_lua_version ~= 16 then - error("ngx_stream_lua_module 0.0.15 required") + error("ngx_stream_lua_module 0.0.16 required") end else - error("ngx_http_lua_module 0.10.27 or " - .. "ngx_stream_lua_module 0.0.15 required") + error("ngx_http_lua_module 0.10.28 or " + .. "ngx_stream_lua_module 0.0.16 required") end @@ -141,7 +141,7 @@ local c_buf_type = ffi.typeof("char[?]") local _M = new_tab(0, 18) -_M.version = "0.1.30" +_M.version = "0.1.31" _M.new_tab = new_tab _M.clear_tab = clear_tab diff --git a/lib/resty/core/base64.lua b/lib/resty/core/base64.lua index 8a0e463b4..7f8e5388d 100644 --- a/lib/resty/core/base64.lua +++ b/lib/resty/core/base64.lua @@ -30,6 +30,10 @@ if subsystem == "http" then int ngx_http_lua_ffi_decode_base64(const unsigned char *src, size_t len, unsigned char *dst, size_t *dlen); + + int ngx_http_lua_ffi_decode_base64mime(const unsigned char *src, + size_t len, unsigned char *dst, + size_t *dlen); ]] ngx_lua_ffi_encode_base64 = C.ngx_http_lua_ffi_encode_base64 @@ -51,6 +55,7 @@ elseif subsystem == "stream" then end + local function base64_encoded_length(len, no_padding) return no_padding and floor((len * 8 + 5) / 6) or floor((len + 2) / 3) * 4 @@ -110,6 +115,22 @@ ngx.decode_base64 = function (s) end +ngx.decode_base64mime = function (s) + if type(s) ~= 'string' then + error("string argument only", 2) + end + local slen = #s + local dlen = base64_decoded_length(slen) + local dst = get_string_buf(dlen) + local pdlen = get_size_ptr() + local ok = C.ngx_http_lua_ffi_decode_base64mime(s, slen, dst, pdlen) + if ok == 0 then + return nil + end + return ffi_string(dst, pdlen[0]) +end + + return { version = base.version } diff --git a/t/cert/chain/chain.pem b/t/cert/chain/chain.pem index 21b704f2f..54dca309f 100644 --- a/t/cert/chain/chain.pem +++ b/t/cert/chain/chain.pem @@ -1,46 +1,3 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 4100 (0x1004) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=US, ST=California, O=OpenResty, CN=Signing-CA-2 - Validity - Not Before: Sep 20 05:27:46 2014 GMT - Not After : Aug 27 05:27:46 2114 GMT - Subject: C=US, ST=California, O=OpenResty, CN=test.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) - Modulus: - 00:d8:53:ac:ac:5c:3f:f9:80:a8:96:4b:b0:58:db: - 5a:86:de:ca:30:02:d9:19:c8:f6:14:c5:40:c9:41: - eb:bb:7a:d1:e1:f9:96:3b:54:d5:e8:bf:ac:50:5a: - 49:11:da:99:60:44:e0:25:68:40:36:7c:f6:ce:b4: - 9c:b9:58:d6:ea:e7:44:98:63:eb:a2:72:f8:e9:69: - b4:4a:4d:68:86:41:ca:67:58:61:e6:70:e8:08:fe: - ad:c2:75:59:24:0e:f0:2f:1a:70:83:8c:a3:77:64: - e8:4d:d5:c5:28:62:a9:53:d1:a1:22:f5:36:43:a7: - 46:00:aa:97:54:72:d4:72:47 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 1F:DB:C0:D9:3C:4B:77:A8:9A:AC:33:1F:7B:70:C4:CF:BA:C8:07:DD - X509v3 Authority Key Identifier: - keyid:39:77:77:A3:4E:92:8B:E2:25:20:72:64:35:0A:7A:87:A8:58:A9:F8 - - Signature Algorithm: sha1WithRSAEncryption - 1e:cd:83:66:b1:db:ea:5c:37:7e:bc:31:44:52:72:03:ae:9b: - 44:20:2c:ad:00:20:a5:dc:cf:9d:c8:c8:8f:df:cf:24:26:9c: - 43:83:f4:d2:ff:eb:d9:e4:7d:25:cf:1f:b8:aa:63:58:03:b9: - da:52:42:f8:fe:2e:71:cc:8f:de:26:34:cd:da:5c:7a:3b:64: - 07:18:27:a1:61:b6:58:32:96:10:97:f2:7f:00:c4:44:43:b7: - 9d:e2:31:69:4f:c2:95:c5:a3:32:d1:c0:00:c6:ef:58:b9:0f: - e6:08:3a:0d:c9:c0:14:f7:26:8c:43:13:55:1b:93:71:72:c7: - ad:2f -----BEGIN CERTIFICATE----- MIICijCCAfOgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAoMCU9wZW5SZXN0eTEVMBMGA1UE @@ -57,47 +14,6 @@ g2ax2+pcN368MURScgOum0QgLK0AIKXcz53IyI/fzyQmnEOD9NL/69nkfSXPH7iq Y1gDudpSQvj+LnHMj94mNM3aXHo7ZAcYJ6FhtlgylhCX8n8AxERDt53iMWlPwpXF ozLRwADG71i5D+YIOg3JwBT3JoxDE1Ubk3Fyx60v -----END CERTIFICATE----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 4098 (0x1002) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=US, ST=California, L=San Francisco, O=OpenResty, CN=Root CA - Validity - Not Before: Sep 20 05:09:05 2014 GMT - Not After : Aug 27 05:09:05 2114 GMT - Subject: C=US, ST=California, O=OpenResty, CN=Signing-CA-1 - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) - Modulus: - 00:b9:9a:3d:b6:31:dd:b6:8a:f1:9f:61:25:79:70: - f6:ea:4b:6a:0f:0c:72:ea:45:fc:4d:51:cf:f5:71: - 88:94:9c:f9:04:40:99:fd:2d:17:15:3a:de:5f:70: - 4a:06:79:13:fb:81:49:ad:da:59:44:12:81:74:9d: - d8:19:3e:4e:e8:c7:00:ee:f9:96:81:7a:bf:09:e6: - 88:b0:e3:b2:e8:ca:e3:72:23:e4:86:83:41:ca:b3: - 49:c0:f5:76:8a:d7:b5:fc:a3:12:1b:2b:0b:b4:57: - 10:24:97:40:be:cb:17:e7:c5:de:93:1b:59:94:ff: - 34:3f:cd:4d:14:76:09:0e:f3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 12:57:8E:2C:9B:CA:C9:8D:F8:88:B1:4D:EE:A6:6D:F3:99:C3:AF:E1 - X509v3 Authority Key Identifier: - keyid:56:65:C9:8B:65:55:27:2E:AB:14:F0:26:46:BD:BB:9E:A1:2B:41:58 - - X509v3 Basic Constraints: - CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1e:fb:6f:3e:12:bd:45:11:59:52:d5:60:ff:7c:73:9e:32:ce: - 76:fa:0b:b6:4a:58:68:db:92:a4:a0:d2:63:24:27:9c:6a:c5: - 6c:fa:84:d4:b5:80:93:b0:79:8f:33:c6:06:99:49:81:99:f4: - 52:ba:bd:ff:6e:f5:69:3f:65:e0:59:51:ce:16:66:2f:39:b5: - 31:ff:18:2a:a4:8e:14:77:7b:a2:2c:54:4b:f0:a5:2c:83:12: - c4:d5:1c:4a:5f:7b:31:26:ed:63:ba:d5:83:e2:b5:1d:c3:f3: - 34:a0:ba:dd:ee:87:ee:70:71:ae:1b:c5:97:9b:08:a6:9c:ad: - c0:c2 -----BEGIN CERTIFICATE----- MIICdjCCAd+gAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEjAQ @@ -114,47 +30,6 @@ Slho25KkoNJjJCecasVs+oTUtYCTsHmPM8YGmUmBmfRSur3/bvVpP2XgWVHOFmYv ObUx/xgqpI4Ud3uiLFRL8KUsgxLE1RxKX3sxJu1jutWD4rUdw/M0oLrd7ofucHGu G8WXmwimnK3Awg== -----END CERTIFICATE----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 4099 (0x1003) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=US, ST=California, O=OpenResty, CN=Signing-CA-1 - Validity - Not Before: Sep 20 05:25:04 2014 GMT - Not After : Aug 27 05:25:04 2114 GMT - Subject: C=US, ST=California, O=OpenResty, CN=Signing-CA-2 - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) - Modulus: - 00:a4:d0:ae:16:a8:8f:9d:2c:ee:12:f5:0c:5e:29: - 65:9b:cc:9b:67:6f:40:24:d7:44:ff:d4:de:8d:d4: - 36:1c:e1:37:2b:df:ff:69:35:6d:0b:4f:ae:9a:16: - e7:a9:c6:24:d3:8e:a4:c3:2f:25:d8:f3:66:73:8e: - 84:8e:9c:a6:c7:f9:ce:8c:b7:9d:60:26:85:4c:8f: - f4:43:17:af:9d:94:1a:f5:21:7b:1c:2b:9c:ee:fe: - 4a:ca:6d:c7:cf:ee:2a:02:28:1f:6e:13:94:85:3f: - 50:a3:03:18:bd:6c:f9:b5:9d:37:b9:27:61:29:75: - d3:39:77:5e:83:41:aa:8c:21 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 39:77:77:A3:4E:92:8B:E2:25:20:72:64:35:0A:7A:87:A8:58:A9:F8 - X509v3 Authority Key Identifier: - keyid:12:57:8E:2C:9B:CA:C9:8D:F8:88:B1:4D:EE:A6:6D:F3:99:C3:AF:E1 - - X509v3 Basic Constraints: - CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 3b:4b:b6:31:51:72:9a:ef:42:60:5e:98:60:71:d7:26:4a:46: - f1:0e:1f:08:be:e6:1b:5f:e2:fd:28:54:8d:b1:c5:09:6f:04: - cb:69:dc:39:5e:67:e0:91:9f:10:94:bc:35:90:4a:65:fe:58: - bd:e9:9d:18:f0:b2:c4:2c:6e:05:00:a4:63:59:6a:85:cf:0e: - 28:3a:ad:34:1c:1e:8c:08:cf:ac:79:18:e6:2b:16:49:9c:0b: - 09:66:50:29:53:78:04:9e:3d:27:40:c4:0c:72:d6:8c:d6:b1: - 9c:f5:f2:f8:8c:9c:0b:0d:e1:4b:9b:ec:c9:65:0c:1e:fe:27: - 07:96 -----BEGIN CERTIFICATE----- MIICYzCCAcygAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAoMCU9wZW5SZXN0eTEVMBMGA1UE diff --git a/t/decode-base64.t b/t/decode-base64.t index 974246c60..14931d3c5 100644 --- a/t/decode-base64.t +++ b/t/decode-base64.t @@ -223,3 +223,147 @@ decode_base64url returned: nil, invalid input --- no_error_log [error] -- NYI: + + + +=== TEST 9: decode_base64mime decode with newlines ('\n') inserted after every 76 characters +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime("T3BlblJlc3R5IGlzIGEgZnVsbC1mbGVkZ2VkIHdlYiBwbGF0Zm9ybSB0aGF0IGludGVncmF0ZXMg\ndGhlIHN0YW5kYXJkIE5naW54IGNvcmUsIEx1YUpJVCwgbWFueSBjYXJlZnVsbHkgd3JpdHRlbiBM\ndWEgbGlicmFyaWVzLCBsb3RzIG9mIGhpZ2ggcXVhbGl0eSAzcmQtcGFydHkgTmdpbnggbW9kdWxl\ncywgYW5kIG1vc3Qgb2YgdGhlaXIgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLiBJdCBpcyBkZXNpZ25l\nZCB0byBoZWxwIGRldmVsb3BlcnMgZWFzaWx5IGJ1aWxkIHNjYWxhYmxlIHdlYiBhcHBsaWNhdGlv\nbnMsIHdlYiBzZXJ2aWNlcywgYW5kIGR5bmFtaWMgd2ViIGdhdGV3YXlzLg==\n") + end + ngx.say(s) + } + } +--- request +GET /base64mime +--- response_body +OpenResty is a full-fledged web platform that integrates the standard Nginx core, LuaJIT, many carefully written Lua libraries, lots of high quality 3rd-party Nginx modules, and most of their external dependencies. It is designed to help developers easily build scalable web applications, web services, and dynamic web gateways. +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: + + + +=== TEST 10: decode_base64mime decode with random newlines ('\n') inserted +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime("T\n3BlblJ\nlc3R5IGlzIGEgZnVsbC1mbGVkZ2VkIHdlYiBwb\nGF0Zm9ybSB0aGF0IGludGVncmF0ZXMg\ndGhlIHN0YW5kYXJkIE5naW54IGNvcmUsIEx1YUpJVCwgbWFueSBjYXJlZnVsbHkgd3JpdHRlbiBM\ndWEgbGlicmFyaWVz\nLCBsb3RzIG9mIGhpZ2ggcXVhbGl0eSAzcmQtcGFydHkgTmdpbnggbW9kdWxl\ncywgYW5kIG1vc3Qgb2YgdGhlaXIgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLiBJdCBpcyBkZXNpZ25l\nZCB0byBoZWxwIGRldmVsb3BlcnMgZWFzaWx5IGJ1aWxkIHNjYWxhYmxlIHdlYiBhcHBsaWNhdGlv\nbnMsIHdlYiBzZXJ2aWNlc\nywgYW5kIGR5bmFtaWMgd2ViIGdhdGV3YXlzLg==\n") + end + ngx.say(s) + } + } +--- request +GET /base64mime +--- response_body +OpenResty is a full-fledged web platform that integrates the standard Nginx core, LuaJIT, many carefully written Lua libraries, lots of high quality 3rd-party Nginx modules, and most of their external dependencies. It is designed to help developers easily build scalable web applications, web services, and dynamic web gateways. +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: + + + +=== TEST 11: decode_base64mime decode with characters outside alphabet +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime("!T3B#lblJl@c3R5IG\rlzIGEgZnVs\nbC1mbGVkZ2Vk&IHdlYiBwbG'F0Zm9ybSB0aGF0[IGludGVncmF0ZXMg\ndGhlIHN0YW]5kYXJkIE5naW54IGNvcmUsIEx1-YUpJVCwg_bWFueSBjYXJlZnVsbHkgd3JpdHRlbiBM\ndWEgbGlicmFyaWVzLCBsb3R$zIG9mIGhpZ2%ggcXVhbGl0eSAzcmQ^tcGFydHkgTm&dpbnggbW9kdWxl\ncywgYW5kIG1vc3Qgb2YgdGhlaXIgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLiBJdCBpcyBkZXNpZ25l\nZCB0byBoZWxwIGRldmVsb3BlcnMgZWFzaWx5IGJ1aWxkIHNjYWxhYmxlIHdlYiBhcHBsaWNhdGlv\nbnMsIHdlYiBzZXJ2aWNlcywgYW5kIGR5bmFtaWMgd2ViIGdhdGV3YXlzLg==\n") + end + ngx.say(s) + } + } +--- request +GET /base64mime +--- response_body +OpenResty is a full-fledged web platform that integrates the standard Nginx core, LuaJIT, many carefully written Lua libraries, lots of high quality 3rd-party Nginx modules, and most of their external dependencies. It is designed to help developers easily build scalable web applications, web services, and dynamic web gateways. +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: + + + +=== TEST 12: decode_base64mime decode not well formed string +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime('zaaLg==') + end + ngx.say(s) + } + } +--- request +GET /base64mime +--- response_body +nil +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: + + + +=== TEST 13: decode_base64mime decode empty string +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime('') + end + ngx.say(s .. 'empty') + } + } +--- request +GET /base64mime +--- response_body +empty +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: + + + +=== TEST 14: decode_base64mime decode outside the base encoding alphabet string +--- http_config eval: $::HttpConfig +--- config + location = /base64mime { + content_by_lua_block { + local s + for i = 1, 100 do + s = ngx.decode_base64mime('^&$') + end + ngx.say(s .. 'empty') + } + } +--- request +GET /base64mime +--- response_body +empty +--- error_log eval +qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):3 loop\]/ +--- no_error_log +[error] + -- NYI: