From 4339b17ec20dcb277c948931a37b702a84185d6b Mon Sep 17 00:00:00 2001 From: lijunlong Date: Sun, 8 Nov 2026 16:14:28 +0800 Subject: [PATCH 1/2] feature: add ngx.ssl.get_req_ssl_ctx(). Expose the downstream session SSL_CTX pointer through the HTTP and stream FFI exports. Preserve Nginx session_ctx semantics after SNI selection and return a borrowed void pointer with the existing ngx.ssl error convention. Only export the Lua getter when its C symbol is available so older binaries can still load ngx.ssl and callers can select a fallback. Document ownership and availability, and cover request errors, TLS phases, repeated reads, SNI, and missing-symbol compatibility. Validation: 60 new and 856 existing SSL assertions pass on Nginx 1.31.8 with OpenSSL 3.5.9. A real older binary without the symbol still loads ngx.ssl. Luacheck and git diff --check pass. --- lib/ngx/ssl.lua | 41 ++++++++ lib/ngx/ssl.md | 26 ++++++ t/ssl-ctx.t | 227 +++++++++++++++++++++++++++++++++++++++++++++ t/stream/ssl-ctx.t | 193 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 487 insertions(+) create mode 100644 t/ssl-ctx.t create mode 100644 t/stream/ssl-ctx.t diff --git a/lib/ngx/ssl.lua b/lib/ngx/ssl.lua index 64ecd9908..accd5583d 100644 --- a/lib/ngx/ssl.lua +++ b/lib/ngx/ssl.lua @@ -49,6 +49,7 @@ local ngx_lua_ffi_ssl_session_master_key local ngx_lua_ffi_ssl_export_keying_material local ngx_lua_ffi_ssl_export_keying_material_early local ngx_lua_ffi_get_req_ssl_pointer +local ngx_lua_ffi_get_req_ssl_ctx local ngx_lua_ffi_get_upstream_ssl_pointer local ngx_lua_ffi_req_shared_ssl_ciphers @@ -108,6 +109,9 @@ if subsystem == 'http' then void *ngx_http_lua_ffi_get_req_ssl_pointer(ngx_http_request_t *r, char **err); + void *ngx_http_lua_ffi_get_req_ssl_ctx(ngx_http_request_t *r, + char **err); + void *ngx_http_lua_ffi_get_upstream_ssl_pointer( ngx_http_request_t *r, char **err); @@ -186,6 +190,13 @@ if subsystem == 'http' then ngx_lua_ffi_ssl_export_keying_material_early = C.ngx_http_lua_ffi_ssl_export_keying_material_early ngx_lua_ffi_get_req_ssl_pointer = C.ngx_http_lua_ffi_get_req_ssl_pointer + if pcall(function () + return C.ngx_http_lua_ffi_get_req_ssl_ctx + end) + then + ngx_lua_ffi_get_req_ssl_ctx = C.ngx_http_lua_ffi_get_req_ssl_ctx + end + ngx_lua_ffi_get_upstream_ssl_pointer = C.ngx_http_lua_ffi_get_upstream_ssl_pointer ngx_lua_ffi_req_shared_ssl_ciphers = @@ -239,6 +250,9 @@ elseif subsystem == 'stream' then void *ngx_stream_lua_ffi_get_req_ssl_pointer(ngx_stream_lua_request_t *r, char **err); + void *ngx_stream_lua_ffi_get_req_ssl_ctx(ngx_stream_lua_request_t *r, + char **err); + void *ngx_stream_lua_ffi_get_upstream_ssl_pointer( ngx_stream_lua_request_t *r, char **err); @@ -285,6 +299,13 @@ elseif subsystem == 'stream' then ngx_lua_ffi_ssl_verify_client = C.ngx_stream_lua_ffi_ssl_verify_client ngx_lua_ffi_ssl_client_random = C.ngx_stream_lua_ffi_ssl_client_random ngx_lua_ffi_get_req_ssl_pointer = C.ngx_stream_lua_ffi_get_req_ssl_pointer + if pcall(function () + return C.ngx_stream_lua_ffi_get_req_ssl_ctx + end) + then + ngx_lua_ffi_get_req_ssl_ctx = C.ngx_stream_lua_ffi_get_req_ssl_ctx + end + ngx_lua_ffi_get_upstream_ssl_pointer = C.ngx_stream_lua_ffi_get_upstream_ssl_pointer ngx_lua_ffi_req_shared_ssl_ciphers = @@ -705,6 +726,26 @@ function _M.get_req_ssl_pointer() end +local function get_req_ssl_ctx() + local r = get_request() + if not r then + error("no request found") + end + + local ctx = ngx_lua_ffi_get_req_ssl_ctx(r, errmsg) + if ctx == nil then + return nil, ffi_str(errmsg[0]) + end + + return ctx +end + + +if ngx_lua_ffi_get_req_ssl_ctx then + _M.get_req_ssl_ctx = get_req_ssl_ctx +end + + function _M.get_upstream_ssl_pointer() local r = get_request() if not r then diff --git a/lib/ngx/ssl.md b/lib/ngx/ssl.md index 9b5ca4b4e..d7c0a5e20 100644 --- a/lib/ngx/ssl.md +++ b/lib/ngx/ssl.md @@ -37,6 +37,7 @@ Table of Contents * [get_session_master_key](#get_session_master_key) * [get_shared_ssl_ciphers](#get_shared_ssl_ciphers) * [get_req_ssl_pointer](#get_req_ssl_pointer) + * [get_req_ssl_ctx](#get_req_ssl_ctx) * [get_upstream_ssl_pointer](#get_upstream_ssl_pointer) * [Community](#community) * [English Mailing List](#english-mailing-list) @@ -761,6 +762,31 @@ This function was first added in version `0.1.16`. [Back to TOC](#table-of-contents) +get_req_ssl_ctx +--------------- +**syntax:** *ctx_ptr, err = ssl.get_req_ssl_ctx()* + +**context:** *any context with a downstream TLS connection* + +Retrieves the OpenSSL `SSL_CTX*` stored in Nginx's downstream `session_ctx`, +in both HTTP and stream subsystems. This is the original session context, +which can differ from `SSL_get_SSL_CTX()` after SNI selects another server. + +Returns a `void *` FFI pointer on success, or `nil` and an error string when +SSL state or the session context is unavailable. Raises `no request found` +when called without a request. + +The pointer is borrowed from Nginx. Do not free it or attach a garbage +collector to it. If retaining it beyond the connection lifetime, obtain +and release a separate reference using the appropriate OpenSSL APIs. + +This function is only exported when the running lua-nginx-module or +stream-lua-nginx-module provides the corresponding `get_req_ssl_ctx` FFI +symbol. On older binaries, `ssl.get_req_ssl_ctx` is `nil`; the other +`ngx.ssl` APIs remain available. + +[Back to TOC](#table-of-contents) + get_upstream_ssl_pointer ------------ **syntax:** *ssl_ptr, err = ssl.get_upstream_ssl_pointer()* diff --git a/t/ssl-ctx.t b/t/ssl-ctx.t new file mode 100644 index 000000000..4a9a3fec0 --- /dev/null +++ b/t/ssl-ctx.t @@ -0,0 +1,227 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(2); +plan tests => repeat_each() * blocks() * 3; + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); +no_long_string(); +log_level 'info'; + +add_block_preprocessor(sub { + my $block = shift; + my $config = $block->http_config || ''; + $config .= <<'_EOC_'; +lua_package_path "$prefix/html/?.lua;./lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; +_EOC_ + $block->set_value("http_config", $config); + $block->set_value("user_files", <<'_EOC_'); +>>> ssl_ctx.lua +local ffi = require "ffi" +local ssl = require "ngx.ssl" + +ffi.cdef[[ + typedef struct ssl_ctx_st SSL_CTX; + SSL_CTX *SSL_get_SSL_CTX(const void *ssl); + int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +]] + +local C = ffi.C +local _M = {} + +function _M.depths() + local ctx, err = ssl.get_req_ssl_ctx() + assert(ctx ~= nil, err) + assert(ffi.istype("void *", ctx)) + assert(ctx == ssl.get_req_ssl_ctx()) + + local conn = assert(ssl.get_req_ssl_pointer()) + return C.SSL_CTX_get_verify_depth(ffi.cast("SSL_CTX *", ctx)), + C.SSL_CTX_get_verify_depth(C.SSL_get_SSL_CTX(conn)) +end + +return _M +_EOC_ +}); + +run_tests(); + +__DATA__ + +=== TEST 1: API reports a missing request +--- http_config + init_by_lua_block { + local ssl = require "ngx.ssl" + local ok, err = pcall(ssl.get_req_ssl_ctx) + _G.no_request_ok = ok + _G.no_request_err = err + } +--- config + location /t { + content_by_lua_block { + ngx.say(no_request_ok, ": ", no_request_err:sub(-16)) + } + } +--- request +GET /t +--- response_body +false: no request found +--- no_error_log +[error] + + +=== TEST 2: plain connection returns an error +--- config + location /t { + content_by_lua_block { + local ctx, err = require("ngx.ssl").get_req_ssl_ctx() + ngx.say(ctx == nil, ": ", err) + } + } +--- request +GET /t +--- response_body +true: bad request +--- no_error_log +[error] + + +=== TEST 3: TLS context is readable during certificate and content phases +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-3.sock ssl; + server_name default.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 3; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 3) + } + + location / { + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } + } +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/ctx-3.sock")) + assert(sock:sslhandshake(nil, "default.test", false)) + assert(sock:send("GET / HTTP/1.0\r\nHost: default.test\r\n\r\n")) + local data = assert(sock:receive("*a")) + local _, header_end = data:find("\r\n\r\n", 1, true) + assert(header_end) + ngx.print(data:sub(header_end + 1)) + assert(sock:close()) + } + } +--- request +GET /t +--- response_body +3:3 +--- no_error_log +[error] + + +=== TEST 4: SNI preserves the original session context +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-4.sock ssl; + server_name default.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 3; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 3) + } + + location / { + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } + } + + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-4.sock ssl; + server_name selected.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 7; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 7) + } + + location / { + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } + } +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/ctx-4.sock")) + assert(sock:sslhandshake(nil, "selected.test", false)) + assert(sock:send("GET / HTTP/1.0\r\nHost: selected.test\r\n\r\n")) + local data = assert(sock:receive("*a")) + local _, header_end = data:find("\r\n\r\n", 1, true) + assert(header_end) + ngx.print(data:sub(header_end + 1)) + assert(sock:close()) + } + } +--- request +GET /t +--- response_body +3:7 +--- no_error_log +[error] + + +=== TEST 5: ngx.ssl loads without the optional C symbol +--- config + location /t { + content_by_lua_block { + local ffi = require "ffi" + package.loaded.ffi = setmetatable({ + C = setmetatable({}, { + __index = function(_, name) + if name == "ngx_http_lua_ffi_get_req_ssl_ctx" then + error("unavailable C symbol") + end + return ffi.C[name] + end, + }), + }, { __index = ffi }) + package.loaded["ngx.ssl"] = nil + local ssl = require "ngx.ssl" + ngx.say(ssl.get_req_ssl_ctx == nil) + local conn, err = ssl.get_req_ssl_pointer() + ngx.say(conn == nil, ": ", err) + } + } +--- request +GET /t +--- response_body +true +true: bad request +--- no_error_log +[error] diff --git a/t/stream/ssl-ctx.t b/t/stream/ssl-ctx.t new file mode 100644 index 000000000..a6920adeb --- /dev/null +++ b/t/stream/ssl-ctx.t @@ -0,0 +1,193 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua::Stream; + +repeat_each(2); +plan tests => repeat_each() * blocks() * 3; + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); +no_long_string(); +log_level 'info'; + +add_block_preprocessor(sub { + my $block = shift; + my $config = $block->stream_config || ''; + $config .= <<'_EOC_'; +lua_package_path "$prefix/html/?.lua;./lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; +_EOC_ + $block->set_value("stream_config", $config); + $block->set_value("user_files", <<'_EOC_'); +>>> ssl_ctx.lua +local ffi = require "ffi" +local ssl = require "ngx.ssl" + +ffi.cdef[[ + typedef struct ssl_ctx_st SSL_CTX; + SSL_CTX *SSL_get_SSL_CTX(const void *ssl); + int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +]] + +local C = ffi.C +local _M = {} + +function _M.depths() + local ctx, err = ssl.get_req_ssl_ctx() + assert(ctx ~= nil, err) + assert(ffi.istype("void *", ctx)) + assert(ctx == ssl.get_req_ssl_ctx()) + + local conn = assert(ssl.get_req_ssl_pointer()) + return C.SSL_CTX_get_verify_depth(ffi.cast("SSL_CTX *", ctx)), + C.SSL_CTX_get_verify_depth(C.SSL_get_SSL_CTX(conn)) +end + +return _M +_EOC_ +}); + +run_tests(); + +__DATA__ + +=== TEST 1: API reports a missing request +--- stream_config + init_by_lua_block { + local ssl = require "ngx.ssl" + local ok, err = pcall(ssl.get_req_ssl_ctx) + _G.no_request_ok = ok + _G.no_request_err = err + } +--- stream_server_config + content_by_lua_block { + ngx.say(no_request_ok, ": ", no_request_err:sub(-16)) + } +--- stream_response +false: no request found +--- no_error_log +[error] + + +=== TEST 2: plain connection returns an error +--- stream_server_config + content_by_lua_block { + local ctx, err = require("ngx.ssl").get_req_ssl_ctx() + ngx.say(ctx == nil, ": ", err) + } +--- stream_response +true: bad request +--- no_error_log +[error] + + +=== TEST 3: TLS context is readable during certificate and content phases +--- stream_config + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-3.sock ssl; + server_name default.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 3; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 3) + } + + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } +--- stream_server_config + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/ctx-3.sock")) + assert(sock:sslhandshake(nil, "default.test", false)) + ngx.print(assert(sock:receive("*a"))) + assert(sock:close()) + } +--- stream_response +3:3 +--- no_error_log +[error] + + +=== TEST 4: SNI preserves the original session context +--- stream_config + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-4.sock ssl; + server_name default.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 3; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 3) + } + + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } + + server { + listen unix:$TEST_NGINX_HTML_DIR/ctx-4.sock ssl; + server_name selected.test; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_verify_depth 7; + + ssl_certificate_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + assert(session_depth == 3) + assert(active_depth == 7) + } + + content_by_lua_block { + local session_depth, active_depth = require("ssl_ctx").depths() + ngx.say(session_depth, ":", active_depth) + } + } +--- stream_server_config + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/ctx-4.sock")) + assert(sock:sslhandshake(nil, "selected.test", false)) + ngx.print(assert(sock:receive("*a"))) + assert(sock:close()) + } +--- stream_response +3:7 +--- no_error_log +[error] + + +=== TEST 5: ngx.ssl loads without the optional C symbol +--- stream_server_config + content_by_lua_block { + local ffi = require "ffi" + package.loaded.ffi = setmetatable({ + C = setmetatable({}, { + __index = function(_, name) + if name == "ngx_stream_lua_ffi_get_req_ssl_ctx" then + error("unavailable C symbol") + end + return ffi.C[name] + end, + }), + }, { __index = ffi }) + package.loaded["ngx.ssl"] = nil + local ssl = require "ngx.ssl" + ngx.say(ssl.get_req_ssl_ctx == nil) + local conn, err = ssl.get_req_ssl_pointer() + ngx.say(conn == nil, ": ", err) + } +--- stream_response +true +true: bad request +--- no_error_log +[error] From 3f3b2f91c7a7232a92e54a918430b0a31daf80c7 Mon Sep 17 00:00:00 2001 From: lijunlong Date: Sun, 8 Nov 2026 16:23:04 +0800 Subject: [PATCH 2/2] change: bind the request SSL_CTX FFI exports directly. Require the HTTP and stream C getters when loading ngx.ssl and export the Lua getter unconditionally. Remove the missing-symbol compatibility tests and document the corresponding module requirement. Validation: the request SSL_CTX and existing SSL suites pass for HTTP and stream, along with the lua-resty-openssl SSL suite. Luacheck and git diff --check pass. --- lib/ngx/ssl.lua | 20 +++----------------- lib/ngx/ssl.md | 6 ++---- t/ssl-ctx.t | 31 ------------------------------- t/stream/ssl-ctx.t | 27 --------------------------- 4 files changed, 5 insertions(+), 79 deletions(-) diff --git a/lib/ngx/ssl.lua b/lib/ngx/ssl.lua index accd5583d..82221cf13 100644 --- a/lib/ngx/ssl.lua +++ b/lib/ngx/ssl.lua @@ -190,13 +190,7 @@ if subsystem == 'http' then ngx_lua_ffi_ssl_export_keying_material_early = C.ngx_http_lua_ffi_ssl_export_keying_material_early ngx_lua_ffi_get_req_ssl_pointer = C.ngx_http_lua_ffi_get_req_ssl_pointer - if pcall(function () - return C.ngx_http_lua_ffi_get_req_ssl_ctx - end) - then - ngx_lua_ffi_get_req_ssl_ctx = C.ngx_http_lua_ffi_get_req_ssl_ctx - end - + ngx_lua_ffi_get_req_ssl_ctx = C.ngx_http_lua_ffi_get_req_ssl_ctx ngx_lua_ffi_get_upstream_ssl_pointer = C.ngx_http_lua_ffi_get_upstream_ssl_pointer ngx_lua_ffi_req_shared_ssl_ciphers = @@ -299,13 +293,7 @@ elseif subsystem == 'stream' then ngx_lua_ffi_ssl_verify_client = C.ngx_stream_lua_ffi_ssl_verify_client ngx_lua_ffi_ssl_client_random = C.ngx_stream_lua_ffi_ssl_client_random ngx_lua_ffi_get_req_ssl_pointer = C.ngx_stream_lua_ffi_get_req_ssl_pointer - if pcall(function () - return C.ngx_stream_lua_ffi_get_req_ssl_ctx - end) - then - ngx_lua_ffi_get_req_ssl_ctx = C.ngx_stream_lua_ffi_get_req_ssl_ctx - end - + ngx_lua_ffi_get_req_ssl_ctx = C.ngx_stream_lua_ffi_get_req_ssl_ctx ngx_lua_ffi_get_upstream_ssl_pointer = C.ngx_stream_lua_ffi_get_upstream_ssl_pointer ngx_lua_ffi_req_shared_ssl_ciphers = @@ -741,9 +729,7 @@ local function get_req_ssl_ctx() end -if ngx_lua_ffi_get_req_ssl_ctx then - _M.get_req_ssl_ctx = get_req_ssl_ctx -end +_M.get_req_ssl_ctx = get_req_ssl_ctx function _M.get_upstream_ssl_pointer() diff --git a/lib/ngx/ssl.md b/lib/ngx/ssl.md index d7c0a5e20..70a419670 100644 --- a/lib/ngx/ssl.md +++ b/lib/ngx/ssl.md @@ -780,10 +780,8 @@ The pointer is borrowed from Nginx. Do not free it or attach a garbage collector to it. If retaining it beyond the connection lifetime, obtain and release a separate reference using the appropriate OpenSSL APIs. -This function is only exported when the running lua-nginx-module or -stream-lua-nginx-module provides the corresponding `get_req_ssl_ctx` FFI -symbol. On older binaries, `ssl.get_req_ssl_ctx` is `nil`; the other -`ngx.ssl` APIs remain available. +This function requires lua-nginx-module or stream-lua-nginx-module with +the corresponding `get_req_ssl_ctx` FFI export. [Back to TOC](#table-of-contents) diff --git a/t/ssl-ctx.t b/t/ssl-ctx.t index 4a9a3fec0..fb619fe9c 100644 --- a/t/ssl-ctx.t +++ b/t/ssl-ctx.t @@ -194,34 +194,3 @@ GET /t 3:7 --- no_error_log [error] - - -=== TEST 5: ngx.ssl loads without the optional C symbol ---- config - location /t { - content_by_lua_block { - local ffi = require "ffi" - package.loaded.ffi = setmetatable({ - C = setmetatable({}, { - __index = function(_, name) - if name == "ngx_http_lua_ffi_get_req_ssl_ctx" then - error("unavailable C symbol") - end - return ffi.C[name] - end, - }), - }, { __index = ffi }) - package.loaded["ngx.ssl"] = nil - local ssl = require "ngx.ssl" - ngx.say(ssl.get_req_ssl_ctx == nil) - local conn, err = ssl.get_req_ssl_pointer() - ngx.say(conn == nil, ": ", err) - } - } ---- request -GET /t ---- response_body -true -true: bad request ---- no_error_log -[error] diff --git a/t/stream/ssl-ctx.t b/t/stream/ssl-ctx.t index a6920adeb..28719123d 100644 --- a/t/stream/ssl-ctx.t +++ b/t/stream/ssl-ctx.t @@ -164,30 +164,3 @@ true: bad request 3:7 --- no_error_log [error] - - -=== TEST 5: ngx.ssl loads without the optional C symbol ---- stream_server_config - content_by_lua_block { - local ffi = require "ffi" - package.loaded.ffi = setmetatable({ - C = setmetatable({}, { - __index = function(_, name) - if name == "ngx_stream_lua_ffi_get_req_ssl_ctx" then - error("unavailable C symbol") - end - return ffi.C[name] - end, - }), - }, { __index = ffi }) - package.loaded["ngx.ssl"] = nil - local ssl = require "ngx.ssl" - ngx.say(ssl.get_req_ssl_ctx == nil) - local conn, err = ssl.get_req_ssl_pointer() - ngx.say(conn == nil, ": ", err) - } ---- stream_response -true -true: bad request ---- no_error_log -[error]