Remove unused test files and configurations for lua-nginx-module

This commit is contained in:
Théophile Diot 2025-01-16 10:22:58 +01:00
parent 4f5d1919c3
commit 116a8b5b26
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
259 changed files with 0 additions and 130534 deletions

View file

@ -1,2 +0,0 @@
servroot

View file

@ -1,81 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(1);
plan tests => repeat_each() * (blocks() * 3);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
our $http_config = <<'_EOC_';
# lua-resty-string is required for lua-resty-mysql
lua_package_path "../lua-resty-rsa/lib/?.lua;../lua-resty-mysql/lib/?.lua;../lua-resty-string/lib/?.lua;;";
_EOC_
no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: conv_uid - drop table
--- http_config eval: $::http_config
--- config
location = /init {
content_by_lua_block {
local mysql = require "resty.mysql"
local db = assert(mysql:new())
local ok, err, errcode, sqlstate = db:connect{
host = "127.0.0.1",
port = $TEST_NGINX_MYSQL_PORT,
database = "ngx_test",
user = "ngx_test",
password = "ngx_test",
charset = "utf8",
}
local queries = {
"DROP TABLE IF EXISTS conv_uid",
"CREATE TABLE conv_uid(id serial primary key, new_uid integer, old_uid integer)",
"INSERT INTO conv_uid(old_uid,new_uid) VALUES(32,56),(35,78)",
}
for _, query in ipairs(queries) do
local ok, err = db:query(query)
if not ok then
ngx.say("failed to run mysql query \"", query, "\": ", err)
return
end
end
ngx.say("done!")
}
}
--- request
GET /init
--- response_body
done!
--- timeout: 10
--- no_error_log
[error]
=== TEST 2: flush data from memcached
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /flush
--- error_code: 200
--- response_body eval
"OK\r
"
--- timeout: 10
--- no_error_log
[error]

View file

@ -1,33 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => blocks() * repeat_each() * 2;
run_tests();
__DATA__
=== TEST 1: sanity (integer)
--- config
location /lua {
echo 2;
}
--- request
GET /lua
--- response_body
2
=== TEST 2: sanity (string)
--- config
location /lua {
echo "helloworld";
}
--- request
GET /lua
--- response_body
helloworld

View file

@ -1,812 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 3 + 5);
#log_level("warn");
no_long_string();
run_tests();
__DATA__
=== TEST 1: simple set (integer)
--- config
location /lua {
set_by_lua $res "return 1+1";
echo $res;
}
--- request
GET /lua
--- response_body
2
--- no_error_log
[error]
=== TEST 2: simple set (string)
--- config
location /lua {
set_by_lua $res "return 'hello' .. 'world'";
echo $res;
}
--- request
GET /lua
--- response_body
helloworld
--- no_error_log
[error]
=== TEST 3: internal only
--- config
location /lua {
set_by_lua $res "local function fib(n) if n > 2 then return fib(n-1)+fib(n-2) else return 1 end end return fib(10)";
echo $res;
}
--- request
GET /lua
--- response_body
55
--- no_error_log
[error]
=== TEST 4: inlined script with arguments
--- config
location /lua {
set_by_lua $res "return ngx.arg[1] + ngx.arg[2]" $arg_a $arg_b;
echo $res;
}
--- request
GET /lua?a=1&b=2
--- response_body
3
--- no_error_log
[error]
=== TEST 5: fib by arg
--- config
location /fib {
set_by_lua $res "local function fib(n) if n > 2 then return fib(n-1)+fib(n-2) else return 1 end end return fib(tonumber(ngx.arg[1]))" $arg_n;
echo $res;
}
--- request
GET /fib?n=10
--- response_body
55
--- no_error_log
[error]
=== TEST 6: adder
--- config
location = /adder {
set_by_lua $res
"local a = tonumber(ngx.arg[1])
local b = tonumber(ngx.arg[2])
return a + b" $arg_a $arg_b;
echo $res;
}
--- request
GET /adder?a=25&b=75
--- response_body
100
--- no_error_log
[error]
=== TEST 7: read nginx variables directly from within Lua
--- config
location = /set-both {
set $b 32;
set_by_lua $a "return tonumber(ngx.var.b) + 1";
echo "a = $a";
}
--- request
GET /set-both
--- response_body
a = 33
--- no_error_log
[error]
=== TEST 8: set nginx variables directly from within Lua
--- config
location = /set-both {
set $b "";
set_by_lua $a "ngx.var.b = 32; return 7";
echo "a = $a";
echo "b = $b";
}
--- request
GET /set-both
--- response_body
a = 7
b = 32
--- no_error_log
[error]
=== TEST 9: set non-existent nginx variables
--- config
location = /set-both {
#set $b "";
set_by_lua $a "ngx.var.b = 32; return 7";
echo "a = $a";
}
--- request
GET /set-both
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
variable "b" not found for writing; maybe it is a built-in variable that is not changeable or you forgot to use "set $b '';" in the config file to define it first
=== TEST 10: set quote sql str
--- config
location = /set {
set $a "";
set_by_lua $a "return ngx.quote_sql_str(ngx.var.a)";
echo $a;
}
--- request
GET /set
--- response_body
''
--- no_error_log
[error]
=== TEST 11: set md5
--- config
location = /md5 {
set_by_lua $a 'return ngx.md5("hello")';
echo $a;
}
--- request
GET /md5
--- response_body
5d41402abc4b2a76b9719d911017c592
--- no_error_log
[error]
=== TEST 12: no ngx.print
--- config
location /lua {
set_by_lua $res "ngx.print(32) return 1";
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 13: no ngx.say
--- config
location /lua {
set_by_lua $res "ngx.say(32) return 1";
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 14: no ngx.flush
--- config
location /lua {
set_by_lua $res "ngx.flush()";
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 15: no ngx.eof
--- config
location /lua {
set_by_lua $res "ngx.eof()";
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 16: no ngx.send_headers
--- config
location /lua {
set_by_lua $res "ngx.send_headers()";
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 17: no ngx.location.capture
--- config
location /lua {
set_by_lua $res 'ngx.location.capture("/sub")';
echo $res;
}
location /sub {
echo sub;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 18: no ngx.location.capture_multi
--- config
location /lua {
set_by_lua $res 'ngx.location.capture_multi{{"/sub"}}';
echo $res;
}
location /sub {
echo sub;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 19: no ngx.exit
--- config
location /lua {
set_by_lua $res 'ngx.exit(0)';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 20: no ngx.redirect
--- config
location /lua {
set_by_lua $res 'ngx.redirect("/blah")';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 21: no ngx.exec
--- config
location /lua {
set_by_lua $res 'ngx.exec("/blah")';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 22: no ngx.req.set_uri(uri, true)
--- config
location /lua {
set_by_lua $res 'ngx.req.set_uri("/blah", true)';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 23: ngx.req.set_uri(uri) exists
--- config
location /lua {
set_by_lua $res 'ngx.req.set_uri("/blah") return 1';
echo $uri;
}
--- request
GET /lua
--- response_body
/blah
--- no_error_log
[error]
=== TEST 24: no ngx.req.read_body()
--- config
location /lua {
set_by_lua $res 'ngx.req.read_body()';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/(?:API disabled in the context of set_by_lua\*|http3 requests are not supported without content-length header)/ms
=== TEST 25: no ngx.req.socket()
--- config
location /lua {
set_by_lua $res 'return ngx.req.socket()';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
my $err_log;
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
$err_log = "http v3 not supported yet";
} else {
$err_log = "API disabled in the context of set_by_lua*";
}
$err_log;
=== TEST 26: no ngx.socket.tcp()
--- config
location /lua {
set_by_lua $res 'return ngx.socket.tcp()';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 27: no ngx.socket.connect()
--- config
location /lua {
set_by_lua $res 'return ngx.socket.connect("127.0.0.1", 80)';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
API disabled in the context of set_by_lua*
=== TEST 28: set $limit_rate (variables with set_handler)
--- config
location /lua {
set $limit_rate 1000;
rewrite_by_lua '
ngx.var.limit_rate = 180;
';
echo "limit rate = $limit_rate";
}
--- request
GET /lua
--- response_body
limit rate = 180
--- no_error_log
[error]
=== TEST 29: set $args and read $query_string
--- config
location /lua {
set $args 'hello';
rewrite_by_lua '
ngx.var.args = "world";
';
echo $query_string;
}
--- request
GET /lua
--- response_body
world
--- no_error_log
[error]
=== TEST 30: set $arg_xxx
--- config
location /lua {
rewrite_by_lua '
ngx.var.arg_foo = "world";
';
echo $arg_foo;
}
--- request
GET /lua?foo=3
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
variable "arg_foo" not found for writing; maybe it is a built-in variable that is not changeable or you forgot to use "set $arg_foo '';" in the config file to define it first
=== TEST 31: symbol $ in lua code of set_by_lua
--- config
location /lua {
set_by_lua $res 'return "$unknown"';
echo $res;
}
--- request
GET /lua
--- response_body
$unknown
--- no_error_log
[error]
=== TEST 32: symbol $ in lua code of set_by_lua_file
--- config
location /lua {
set_by_lua_file $res html/a.lua;
echo $res;
}
--- user_files
>>> a.lua
return "$unknown"
--- request
GET /lua
--- response_body
$unknown
--- no_error_log
[error]
=== TEST 33: external script files with arguments
--- config
location /lua {
set_by_lua_file $res html/a.lua $arg_a $arg_b;
echo $res;
}
--- user_files
>>> a.lua
return ngx.arg[1] + ngx.arg[2]
--- request
GET /lua?a=5&b=2
--- response_body
7
--- no_error_log
[error]
=== TEST 34: variables in set_by_lua_file's file path
--- config
location /lua {
set $path "html/a.lua";
set_by_lua_file $res $path $arg_a $arg_b;
echo $res;
}
--- user_files
>>> a.lua
return ngx.arg[1] + ngx.arg[2]
--- request
GET /lua?a=5&b=2
--- response_body
7
--- no_error_log
[error]
=== TEST 35: lua error (string)
--- config
location /lua {
set_by_lua $res 'error("Bad")';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to run set_by_lua*: set_by_lua(nginx.conf:40):1: Bad
=== TEST 36: lua error (nil)
--- config
location /lua {
set_by_lua $res 'error(nil)';
echo $res;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
failed to run set_by_lua*: unknown reason
=== TEST 37: globals are shared in all requests.
--- config
location /lua {
set_by_lua_block $res {
if not foo then
foo = 1
else
ngx.log(ngx.INFO, "old foo: ", foo)
foo = foo + 1
end
return foo
}
echo $res;
}
--- request
GET /lua
--- response_body_like chomp
\A[12]
\z
--- no_error_log
[error]
--- grep_error_log eval: qr/(old foo: \d+|writing a global Lua variable \('\w+'\))/
--- grep_error_log_out eval
["writing a global Lua variable \('foo'\)\n", "old foo: 1\n"]
=== TEST 38: user modules using ngx.arg
--- http_config
lua_package_path "$prefix/html/?.lua;;";
--- config
location /lua {
set_by_lua $res 'local foo = require "foo" return foo.go()' $arg_a $arg_b;
echo $res;
}
--- user_files
>>> foo.lua
module("foo", package.seeall)
function go()
return ngx.arg[1] + ngx.arg[2]
end
--- request
GET /lua?a=1&b=2
--- response_body
3
--- no_error_log
[error]
=== TEST 39: server scope (inline)
--- config
location /lua {
set $a "[$res]";
echo $a;
}
set_by_lua $res "return 1+1";
--- request
GET /lua
--- response_body
[2]
--- no_error_log
[error]
=== TEST 40: server if scope (inline)
--- config
location /lua {
set $a "[$res]";
echo $a;
}
if ($arg_name = "jim") {
set_by_lua $res "return 1+1";
}
--- request
GET /lua?name=jim
--- response_body
[2]
--- no_error_log
[error]
=== TEST 41: location if scope (inline)
--- config
location /lua {
if ($arg_name = "jim") {
set_by_lua $res "return 1+1";
set $a "[$res]";
echo $a;
}
}
--- request
GET /lua?name=jim
--- response_body
[2]
--- no_error_log
[error]
=== TEST 42: server scope (file)
--- config
location /lua {
set $a "[$res]";
echo $a;
}
set_by_lua_file $res html/a.lua;
--- user_files
>>> a.lua
return 1+1
--- request
GET /lua
--- response_body
[2]
--- no_error_log
[error]
=== TEST 43: server if scope (file)
--- config
location /lua {
set $a "[$res]";
echo $a;
}
if ($arg_name = "jim") {
set_by_lua_file $res html/a.lua;
}
--- request
GET /lua?name=jim
--- user_files
>>> a.lua
return 1+1
--- response_body
[2]
--- no_error_log
[error]
=== TEST 44: location if scope (file)
--- config
location /lua {
if ($arg_name = "jim") {
set_by_lua_file $res html/a.lua;
set $a "[$res]";
echo $a;
}
}
--- user_files
>>> a.lua
return 1+1
--- request
GET /lua?name=jim
--- response_body
[2]
--- no_error_log
[error]
=== TEST 45: backtrace
--- config
location /t {
set_by_lua $a '
local bar
local foo
function foo()
bar()
end
function bar()
error("something bad happened")
end
foo()
';
echo ok;
}
--- request
GET /t
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
something bad happened
stack traceback:
in function 'error'
in function 'bar'
in function 'foo'
=== TEST 46: Lua file does not exist
--- config
location /lua {
set_by_lua_file $a html/test2.lua;
}
--- user_files
>>> test.lua
v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/failed to load external Lua file ".*?test2\.lua": cannot open .*? No such file or directory/

File diff suppressed because it is too large Load diff

View file

@ -1,128 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(1);
plan tests => blocks() * repeat_each() * 2;
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
no_long_string();
run_tests();
__DATA__
=== TEST 1: syntax error in lua code chunk
--- config
location /lua {
set_by_lua $res "local a
a = a+;
return a";
echo $res;
}
--- request
GET /lua
--- error_code: 500
--- response_body_like: 500 Internal Server Error
=== TEST 2: syntax error in lua file
--- config
location /lua {
set_by_lua_file $res 'html/test.lua';
echo $res;
}
--- user_files
>>> test.lua
local a
a = 3 +;
return a
--- request
GET /lua
--- error_code: 500
--- response_body_like: 500 Internal Server Error
=== TEST 3: syntax error in lua file (from Guang Feng)
--- config
location /lua {
set $res '[{"a":32},{"b":64}]';
#set $res '[{"friend_userid":1750146},{"friend_userid":1750150},{"friend_userid":1750153},{"friend_userid":1750166},{"friend_userid":1750181},{"friend_userid":1750186},{"friend_userid":1750195},{"friend_userid":1750232}]';
set_by_lua_file $list 'html/test.lua' $res;
#set_by_lua_file $list 'html/feed.lua' $res;
echo $list;
}
--- user_files
>>> test.lua
-- local j = require('json')
local p = ngx.arg[1]
return p
>>> feed.lua
local s = require("json")
local function explode(d,p)
local t, ll
t={}
ll=0
if(#p == 1) then return p end
while true do
l=string.find(p,d,ll+1,true)
if l~=nil then
table.insert(t, string.sub(p,ll,l-1))
ll=l+1
else
table.insert(t, string.sub(p,ll))
break
end
end
return t
end
local a = explode(',', string.sub(ngx.arg[1], 2, -1))
local x = {}
for i,v in ipairs(a) do table.insert(x,s.decode(v).friend_userid) end
return table.concat(x,',')
--- request
GET /lua
--- response_body
[{"a":32},{"b":64}]
=== TEST 4: 500 in subrequest
--- config
location /main {
content_by_lua '
local res = ngx.location.capture("/err")
ngx.say(res.status);
';
}
location /err {
return 500;
}
--- request
GET /main
--- response_body
500
=== TEST 5: drizzle_pass 500 in subrequest
--- config
location /main {
content_by_lua '
local res = ngx.location.capture("/err")
ngx.say(res.status);
';
}
location /err {
set $back 'blah-blah';
drizzle_pass $back;
}
--- request
GET /main
--- response_body
500

View file

@ -1,211 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#log_level('warn');
#master_on();
#repeat_each(120);
repeat_each(2);
plan tests => blocks() * repeat_each() * 2;
our $HtmlDir = html_dir;
#warn $html_dir;
#$ENV{LUA_PATH} = "$html_dir/?.lua";
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;./?.lua;;';"
--- config
location /main {
echo_location /load;
echo_location /check;
echo_location /check;
}
location /load {
content_by_lua '
package.loaded.foo = nil;
collectgarbage()
local foo = require "foo";
foo.hi()
';
}
location /check {
content_by_lua '
local foo = package.loaded.foo
if foo then
ngx.say("found")
foo.hi()
else
ngx.say("not found")
end
';
}
--- request
GET /main
--- user_files
>>> foo.lua
module(..., package.seeall);
ngx.say("loading");
function hi ()
ngx.say("hello, foo")
end;
--- response_body
loading
hello, foo
found
hello, foo
found
hello, foo
=== TEST 2: sanity
--- http_config eval
"lua_package_cpath '$::HtmlDir/?.so';"
--- config
location /main {
content_by_lua '
ngx.print(package.cpath);
';
}
--- request
GET /main
--- user_files
--- response_body_like: ^[^;]+/servroot(_\d+)?/html/\?\.so$
=== TEST 3: expand default path (after)
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;;';"
--- config
location /main {
content_by_lua '
ngx.print(package.path);
';
}
--- request
GET /main
--- response_body_like: ^[^;]+/servroot(_\d+)?/html/\?\.lua;(.+\.lua)?;*$
=== TEST 4: expand default cpath (after)
--- http_config eval
"lua_package_cpath '$::HtmlDir/?.so;;';"
--- config
location /main {
content_by_lua '
ngx.print(package.cpath);
';
}
--- request
GET /main
--- response_body_like: ^[^;]+/servroot(_\d+)?/html/\?\.so;(.+\.so)?;*$
=== TEST 5: expand default path (before)
--- http_config eval
"lua_package_path ';;$::HtmlDir/?.lua';"
--- config
location /main {
content_by_lua '
ngx.print(package.path);
';
}
--- request
GET /main
--- response_body_like: ^(.+\.lua)?;*?[^;]+/servroot(_\d+)?/html/\?\.lua$
=== TEST 6: expand default cpath (before)
--- http_config eval
"lua_package_cpath ';;$::HtmlDir/?.so';"
--- config
location /main {
content_by_lua '
ngx.print(package.cpath);
';
}
--- request
GET /main
--- response_body_like: ^(.+\.so)?;*?[^;]+/servroot(_\d+)?/html/\?\.so$
=== TEST 7: require "ngx" (content_by_lua)
--- config
location /ngx {
content_by_lua '
local ngx = require "ngx"
ngx.say("hello, world")
';
}
--- request
GET /ngx
--- response_body
hello, world
=== TEST 8: require "ngx" (set_by_lua)
--- config
location /ngx {
set_by_lua $res '
local ngx = require "ngx"
return ngx.escape_uri(" ")
';
echo $res;
}
--- request
GET /ngx
--- response_body
%20
=== TEST 9: require "ndk" (content_by_lua)
--- config
location /ndk {
content_by_lua '
local ndk = require "ndk"
local res = ndk.set_var.set_escape_uri(" ")
ngx.say(res)
';
}
--- request
GET /ndk
--- response_body
%20
=== TEST 10: require "ndk" (set_by_lua)
--- config
location /ndk {
set_by_lua $res '
local ndk = require "ndk"
return ndk.set_var.set_escape_uri(" ")
';
echo $res;
}
--- request
GET /ndk
--- response_body
%20

View file

@ -1,828 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#repeat_each(20000);
#repeat_each(200);
repeat_each(2);
#master_on();
#workers(1);
#log_level('debug');
#log_level('warn');
#worker_connections(1024);
plan tests => repeat_each() * (blocks() * 3 + 2);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
our $LuaCpath = $ENV{LUA_CPATH} ||
'/usr/local/openresty-debug/lualib/?.so;/usr/local/openresty/lualib/?.so;;';
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
no_long_string();
run_tests();
__DATA__
=== TEST 1: throw 403
--- config
location /lua {
content_by_lua "ngx.exit(403);ngx.say('hi')";
}
--- request
GET /lua
--- error_code: 403
--- response_body_like: 403 Forbidden
--- no_error_log
[error]
=== TEST 2: throw 404
--- config
location /lua {
content_by_lua "ngx.exit(404);ngx.say('hi');";
}
--- request
GET /lua
--- error_code: 404
--- response_body_like: 404 Not Found
--- no_error_log
[error]
=== TEST 3: throw 404 after sending the header and partial body
--- config
location /lua {
content_by_lua "ngx.say('hi');ngx.exit(404);ngx.say(', you')";
}
--- request
GET /lua
--- error_log
attempt to set status 404 via ngx.exit after sending out the response status 200
--- no_error_log
[alert]
--- response_body
hi
=== TEST 4: working with ngx_auth_request (succeeded)
--- config
location /auth {
content_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
}
location /api {
set $user $arg_user;
auth_request /auth;
echo "Logged in";
}
--- request
GET /api?user=agentzh
--- error_code: 200
--- response_body
Logged in
--- no_error_log
[error]
=== TEST 5: working with ngx_auth_request (failed)
--- config
location /auth {
content_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
}
location /api {
set $user $arg_user;
auth_request /auth;
echo "Logged in";
}
--- request
GET /api?user=agentz
--- error_code: 403
--- response_body_like: 403 Forbidden
--- no_error_log
[error]
=== TEST 6: working with ngx_auth_request (simplest form, w/o ngx_memc)
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
content_by_lua_file 'html/foo.lua';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
-- print('just have run sr: ' .. res.body)
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- no_error_log
[error]
=== TEST 7: working with ngx_auth_request (simplest form)
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
content_by_lua_file 'html/foo.lua';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- no_error_log
[error]
=== TEST 8: working with ngx_auth_request
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream memc_b {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream_list memc_cluster memc_a memc_b;
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass $backend;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
content_by_lua_file 'html/foo.lua';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- no_error_log
[error]
--- timeout: 5
=== TEST 9: working with ngx_auth_request
--- http_config
upstream backend {
drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
keepalive 300;
}
#upstream_list memc_cluster memc_a memc_b;
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
#set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass memc_a;
}
location /conv-mysql {
internal;
set $key "conv-uri-$query_string";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
set_quote_sql_str $seo_uri $query_string;
drizzle_query "select url from my_url_map where seo_url=$seo_uri";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
content_by_lua_file 'html/foo.lua';
}
location /baz {
set $my_uri $uri;
auth_request /conv-uid;
echo_exec /jump $my_uri;
}
location /jump {
internal;
rewrite ^ $query_string? redirect;
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local seo_uri = ngx.var.my_uri
-- print('about to run sr')
local res = ngx.location.capture('/conv-mysql?' .. seo_uri)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].url) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.my_uri = res[1].url;
-- print('done')
--- request
GET /baz
--- response_body_like: 302
--- error_code: 302
--- response_headers
Location: http://localhost:$ServerPort/foo/bar
--- SKIP
=== TEST 10: throw 0
--- config
location /lua {
content_by_lua "ngx.say('Hi'); ngx.eof(); ngx.exit(0);ngx.say('world')";
}
--- request
GET /lua
--- error_code: 200
--- response_body
Hi
--- no_error_log
[error]
=== TEST 11: pcall safe
--- config
location /lua {
content_by_lua '
local function f ()
ngx.say("hello")
ngx.exit(200)
end
pcall(f)
ngx.say("world")
';
}
--- request
GET /lua
--- error_code: 200
--- response_body
hello
--- no_error_log
[error]
=== TEST 12: 501 Method Not Implemented
--- config
location /lua {
content_by_lua '
ngx.exit(501)
';
}
--- request
GET /lua
--- error_code: 501
--- response_body_like: 501 (?:Method )?Not Implemented
--- no_error_log
[error]
=== TEST 13: 501 Method Not Implemented
--- config
location /lua {
content_by_lua '
ngx.exit(ngx.HTTP_METHOD_NOT_IMPLEMENTED)
';
}
--- request
GET /lua
--- error_code: 501
--- response_body_like: 501 (?:Method )?Not Implemented
--- no_error_log
[error]
=== TEST 14: throw 403 after sending out headers with 200
--- config
location /lua {
rewrite_by_lua '
ngx.send_headers()
ngx.say("Hello World")
ngx.exit(403)
';
}
--- request
GET /lua
--- response_body
Hello World
--- error_log
attempt to set status 403 via ngx.exit after sending out the response status 200
--- no_error_log
[alert]
=== TEST 15: throw 403 after sending out headers with 403
--- config
location /lua {
rewrite_by_lua '
ngx.status = 403
ngx.send_headers()
ngx.say("Hello World")
ngx.exit(403)
';
}
--- request
GET /lua
--- response_body
Hello World
--- error_code: 403
--- no_error_log
[error]
[alert]
=== TEST 16: throw 403 after sending out headers with 403 (HTTP 1.0 buffering)
--- config
location /t {
rewrite_by_lua '
ngx.status = 403
ngx.say("Hello World")
ngx.exit(403)
';
}
--- request
GET /t HTTP/1.0
--- response_body
Hello World
--- error_code: 403
--- no_error_log
[error]
[alert]
=== TEST 17: throw 444 after sending out responses (HTTP 1.0)
--- config
location /lua {
content_by_lua "
ngx.say('ok');
return ngx.exit(444)
";
}
--- request
GET /lua HTTP/1.0
--- ignore_response
--- log_level: debug
--- no_error_log
lua sending HTTP 1.0 response headers
[error]
=== TEST 18: throw 499 after sending out responses (HTTP 1.0)
--- config
location /lua {
content_by_lua "
ngx.say('ok');
return ngx.exit(499)
";
}
--- request
GET /lua HTTP/1.0
--- ignore_response
--- log_level: debug
--- no_error_log
lua sending HTTP 1.0 response headers
[error]
=== TEST 19: throw 408 after sending out responses (HTTP 1.0)
--- config
location /lua {
content_by_lua "
ngx.say('ok');
return ngx.exit(408)
";
}
--- request
GET /lua HTTP/1.0
--- ignore_response
--- log_level: debug
--- no_error_log
lua sending HTTP 1.0 response headers
[error]
=== TEST 20: exit(201) with custom response body
--- config
location = /t {
content_by_lua "
ngx.status = 201
ngx.say('ok');
return ngx.exit(201)
";
}
--- request
GET /t
--- ignore_response
--- log_level: debug
--- no_error_log
lua sending HTTP 1.0 response headers
[error]
[alert]
=== TEST 21: exit 403 in header filter
--- config
location = /t {
content_by_lua "ngx.say('hi');";
header_filter_by_lua '
return ngx.exit(403)
';
}
--- request
GET /t
--- error_code: 403
--- response_body_like: 403 Forbidden
--- no_error_log
[error]
=== TEST 22: exit 201 in header filter
--- config
lingering_close always;
location = /t {
content_by_lua "ngx.say('hi');";
header_filter_by_lua '
return ngx.exit(201)
';
}
--- request
GET /t
--- error_code: 201
--- response_body
--- no_error_log
[error]
=== TEST 23: exit both in header filter and content handler
--- config
location = /t {
content_by_lua "ngx.status = 201 ngx.say('hi') ngx.exit(201)";
header_filter_by_lua '
return ngx.exit(201)
';
}
--- request
GET /t
--- error_code: 201
--- stap2
/*
F(ngx_http_send_header) {
printf("=== %d\n", $r->headers_out->status)
print_ubacktrace()
}
*/
F(ngx_http_lua_header_filter_inline) {
printf("=== %d\n", $r->headers_out->status)
print_ubacktrace()
}
F(ngx_http_lua_header_filter_by_chunk).return {
if ($return == -1) {
printf("====== header filter by chunk\n")
print_ubacktrace()
}
}
--- stap_out
--- response_body
--- no_error_log
[error]
[alert]
=== TEST 24: exit 444 in header filter
--- config
location = /t {
content_by_lua "ngx.say('hello world');";
header_filter_by_lua '
return ngx.exit(444)
';
}
--- request
GET /t
--- error_code: 444
--- response_body
--- no_error_log
[error]
=== TEST 25: 501 Method Not Implemented
--- config
location /lua {
content_by_lua '
ngx.exit(ngx.HTTP_NOT_IMPLEMENTED)
';
}
--- request
GET /lua
--- error_code: 501
--- response_body_like: 501 (?:Method )?Not Implemented
--- no_error_log
[error]
=== TEST 26: accepts NGX_OK
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.OK)
}
}
--- request
GET /t
--- response_body
--- no_error_log
[error]
=== TEST 27: accepts NGX_ERROR
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.ERROR)
}
}
--- request
GET /t
--- error_code:
--- response_body
--- no_error_log
[error]
--- curl_error
curl: (95) HTTP/3 stream 0 reset by server
=== TEST 28: accepts NGX_DECLINED
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.DECLINED)
}
}
--- request
GET /t
--- error_code:
--- response_body
--- no_error_log
[error]
--- curl_error
curl: (95) HTTP/3 stream 0 reset by server
=== TEST 29: refuses NGX_AGAIN
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.AGAIN)
}
}
--- request
GET /t
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log eval
qr/\[error\] .*? bad argument to 'ngx.exit': does not accept NGX_AGAIN or NGX_DONE/
=== TEST 30: refuses NGX_DONE
--- config
location = /t {
content_by_lua_block {
ngx.exit(ngx.DONE)
}
}
--- request
GET /t
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log eval
qr/\[error\] .*? bad argument to 'ngx.exit': does not accept NGX_AGAIN or NGX_DONE/

View file

@ -1,330 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 4);
no_long_string();
run_tests();
__DATA__
=== TEST 1: escape uri in set_by_lua
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri('a 你')";
echo $res;
}
--- request
GET /escape
--- response_body
a%20%E4%BD%A0
=== TEST 2: unescape uri in set_by_lua
--- config
location /unescape {
set_by_lua $res "return ngx.unescape_uri('a%20%e4%bd%a0')";
echo $res;
}
--- request
GET /unescape
--- response_body
a 你
=== TEST 3: escape uri in content_by_lua
--- config
location /escape {
content_by_lua "ngx.say(ngx.escape_uri('a 你'))";
}
--- request
GET /escape
--- response_body
a%20%E4%BD%A0
=== TEST 4: unescape uri in content_by_lua
--- config
location /unescape {
content_by_lua "ngx.say(ngx.unescape_uri('a%20%e4%bd%a0'))";
}
--- request
GET /unescape
--- response_body
a 你
=== TEST 5: escape uri in set_by_lua
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri('a+b')";
echo $res;
}
--- request
GET /escape
--- response_body
a%2Bb
=== TEST 6: escape uri in set_by_lua
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri('\"a/b={}:<>;&[]\\\\^')";
echo $res;
}
--- request
GET /escape
--- response_body
%22a%2Fb%3D%7B%7D%3A%3C%3E%3B%26%5B%5D%5C%5E
=== TEST 7: escape uri in set_by_lua
--- config
location /escape {
echo hello;
header_filter_by_lua '
ngx.header.baz = ngx.escape_uri(" ")
';
}
--- request
GET /escape
--- response_headers
baz: %20
--- response_body
hello
=== TEST 8: escape a string that cannot be escaped
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri('abc')";
echo $res;
}
--- request
GET /escape
--- response_body
abc
=== TEST 9: escape an empty string that cannot be escaped
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri('')";
echo $res;
}
--- request
GET /escape
--- response_body eval: "\n"
=== TEST 10: escape nil
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri(nil)";
echo "[$res]";
}
--- request
GET /escape
--- response_body
[]
=== TEST 11: escape numbers
--- config
location /escape {
set_by_lua $res "return ngx.escape_uri(32)";
echo "[$res]";
}
--- request
GET /escape
--- response_body
[32]
=== TEST 12: unescape nil
--- config
location = /t {
set_by_lua $res "return ngx.unescape_uri(nil)";
echo "[$res]";
}
--- request
GET /t
--- response_body
[]
=== TEST 13: unescape numbers
--- config
location = /t {
set_by_lua $res "return ngx.unescape_uri(32)";
echo "[$res]";
}
--- request
GET /t
--- response_body
[32]
=== TEST 14: reserved chars
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("-_.!~*'()"))
ngx.say(ngx.escape_uri(",$@|`"))
}
}
--- request
GET /lua
--- response_body
-_.!~*'()
%2C%24%40%7C%60
--- no_error_log
[error]
=== TEST 15: escape type argument
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("https://www.google.com", 0))
ngx.say(ngx.escape_uri("https://www.google.com/query?q=test", 0))
ngx.say(ngx.escape_uri("https://www.google.com/query?\r\nq=test", 0))
ngx.say(ngx.escape_uri("-_.~!*'();:@&=+$,/?#", 0))
ngx.say(ngx.escape_uri("<>[]{}\\\" ", 0))
}
}
--- request
GET /lua
--- response_body
https://www.google.com
https://www.google.com/query%3Fq=test
https://www.google.com/query%3F%0D%0Aq=test
-_.~!*'();:@&=+$,/%3F%23
<>[]{}\"%20
--- no_error_log
[error]
=== TEST 16: escape type argument
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 0))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 1))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 2))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 3))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 4))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 5))
ngx.say(ngx.escape_uri("https://www.google.com/?t=abc@ :", 6))
}
}
--- request
GET /lua
--- response_body
https://www.google.com/%3Ft=abc@%20:
https://www.google.com/%3Ft=abc@%20:
https%3A%2F%2Fwww.google.com%2F%3Ft%3Dabc%40%20%3A
https://www.google.com/?t=abc@%20:
https://www.google.com/?t=abc@%20:
https://www.google.com/?t=abc@%20:
https://www.google.com/?t=abc@%20:
--- no_error_log
[error]
=== TEST 17: escape type out of range
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("https://www.google.com", -1))
}
}
--- request
GET /lua
--- error_code: 500
--- error_log eval
qr/\[error\] \d+#\d+: \*\d+ lua entry thread aborted: runtime error: "type" \-1 out of range/
=== TEST 18: escape type out of range
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("https://www.google.com", 10))
}
}
--- request
GET /lua
--- error_code: 500
--- error_log eval
qr/\[error\] \d+#\d+: \*\d+ lua entry thread aborted: runtime error: "type" 10 out of range/
=== TEST 19: escape type not integer
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.escape_uri("https://www.google.com", true))
}
}
--- request
GET /lua
--- error_code: 500
--- error_log eval
qr/\[error\] \d+#\d+: \*\d+ lua entry thread aborted: runtime error: "type" is not a number/
=== TEST 20: invalid unescape sequences
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.unescape_uri("%ua%%20%au"))
}
}
--- request
GET /lua
--- response_body
%ua% %au
=== TEST 21: invalid unescape sequences where remain length less than 2
--- config
location /lua {
content_by_lua_block {
ngx.say(ngx.unescape_uri("%a")) -- first character is good
ngx.say(ngx.unescape_uri("%u")) -- first character is bad
ngx.say(ngx.unescape_uri("%"))
ngx.say(ngx.unescape_uri("good%20job%"))
}
}
--- request
GET /lua
--- response_body
%a
%u
%
good job%

View file

@ -1,102 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: set md5 hello
--- config
location = /md5 {
content_by_lua 'ngx.say(ngx.md5("hello"))';
}
--- request
GET /md5
--- response_body
5d41402abc4b2a76b9719d911017c592
=== TEST 2: nil string to ngx.md5
--- config
location = /md5 {
content_by_lua 'ngx.say(ngx.md5(nil))';
}
--- request
GET /md5
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 3: null string to ngx.md5
--- config
location /md5 {
content_by_lua 'ngx.say(ngx.md5(""))';
}
--- request
GET /md5
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 4: use ngx.md5 in set_by_lua
--- config
location = /md5 {
set_by_lua $a 'return ngx.md5("hello")';
echo $a;
}
--- request
GET /md5
--- response_body
5d41402abc4b2a76b9719d911017c592
=== TEST 5: use ngx.md5 in set_by_lua (nil)
--- config
location = /md5 {
set_by_lua $a 'return ngx.md5(nil)';
echo $a;
}
--- request
GET /md5
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 6: use ngx.md5 in set_by_lua (null string)
--- config
location /md5 {
set_by_lua $a 'return ngx.md5("")';
echo $a;
}
--- request
GET /md5
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 7: md5(number)
--- config
location = /md5 {
content_by_lua 'ngx.say(ngx.md5(45))';
}
--- request
GET /md5
--- response_body
6c8349cc7260ae62e3b1396831a8398f

View file

@ -1,38 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: use ngx.today in content_by_lua
--- config
location = /today {
content_by_lua 'ngx.say(ngx.today())';
}
--- request
GET /today
--- response_body_like: ^\d{4}-\d{2}-\d{2}$
=== TEST 2: use ngx.today in set_by_lua
--- config
location = /today {
set_by_lua $a 'return ngx.today()';
echo $a;
}
--- request
GET /today
--- response_body_like: ^\d{4}-\d{2}-\d{2}$

View file

@ -1,570 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('debug'); # to ensure any log-level can be outputted
repeat_each(2);
plan tests => repeat_each() * (blocks() * 3 + 4);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: test log-level STDERR
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.STDERR, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 2: test log-level EMERG
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.EMERG, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[emerg\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 3: test log-level ALERT
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.ALERT, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[alert\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 4: test log-level CRIT
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.CRIT, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[crit\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 5: test log-level ERR
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.ERR, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 6: test log-level WARN
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.WARN, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[warn\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 7: test log-level NOTICE
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.NOTICE, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[notice\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 8: test log-level INFO
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.INFO, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[info\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 9: test log-level DEBUG
--- config
location /log {
content_by_lua '
ngx.say("before log")
ngx.log(ngx.DEBUG, "hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[debug\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 10: regression test print()
--- config
location /log {
content_by_lua '
ngx.say("before log")
print("hello, log", 1234, 3.14159)
ngx.say("after log")
';
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[notice\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: hello, log12343.14159/
=== TEST 11: print(nil)
--- config
location /log {
content_by_lua '
print()
print(nil)
print("nil: ", nil)
ngx.say("hi");
';
}
--- request
GET /log
--- response_body
hi
--- error_log eval
[
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):2: ,/,
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):3: nil,/,
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):4: nil: nil,/,
]
=== TEST 12: ngx.log in set_by_lua
--- config
location /log {
set_by_lua $a '
ngx.log(ngx.ERR, "HELLO")
return 32;
';
echo $a;
}
--- request
GET /log
--- response_body
32
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] set_by_lua\(nginx.conf:43\):2: HELLO,/
=== TEST 13: test booleans and nil
--- config
location /log {
set_by_lua $a '
ngx.log(ngx.ERR, true, false, nil)
return 32;
';
echo $a;
}
--- request
GET /log
--- response_body
32
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] set_by_lua\(nginx.conf:43\):2: truefalsenil,/
=== TEST 14: test table with metamethod
--- config
location /log {
content_by_lua_block {
ngx.say("before log")
local t = setmetatable({v = "value"}, {
__tostring = function(self)
return "tostring "..self.v
end
})
ngx.log(ngx.ERR, t)
ngx.say("after log")
}
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring value,/
=== TEST 15: test table without metamethod
--- config
location /log {
content_by_lua_block {
ngx.log(ngx.ERR, {})
ngx.say("done")
}
}
--- request
GET /log
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
bad argument #1 to 'log' (expected table to have __tostring metamethod)
=== TEST 16: test tables mixed with other types
--- config
location /log {
content_by_lua_block {
ngx.say("before log")
local t = setmetatable({v = "value"}, {
__tostring = function(self)
return "tostring: "..self.v
end
})
ngx.log(ngx.ERR, t, " hello ", t)
ngx.say("after log")
}
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring: value hello tostring: value,/
=== TEST 17: test print with tables
--- config
location /log {
content_by_lua_block {
ngx.say("before log")
local t = setmetatable({v = "value"}, {
__tostring = function(self)
return "tostring: "..self.v
end
})
print(t, " hello ", t)
ngx.say("after log")
}
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[notice\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring: value hello tostring: value,/
=== TEST 18: print() in header filter
--- config
location /log {
header_filter_by_lua '
print("hello world")
ngx.header.foo = 32
';
echo hi;
}
--- request
GET /log
--- response_headers
foo: 32
--- error_log eval
qr/\[notice\] .*? \[lua\] header_filter_by_lua\(nginx.conf:43\):2: hello world/
--- response_body
hi
=== TEST 19: ngx.log in header filter
--- config
location /log {
header_filter_by_lua '
ngx.log(ngx.ERR, "howdy, lua!")
ngx.header.foo = 32
';
echo hi;
}
--- request
GET /log
--- response_headers
foo: 32
--- response_body
hi
--- error_log eval
qr/\[error\] .*? \[lua\] header_filter_by_lua\(nginx.conf:43\):2: howdy, lua!/
=== TEST 20: ngx.log big data
--- config
location /log {
content_by_lua '
ngx.log(ngx.ERR, "a" .. string.rep("h", 1970) .. "b")
ngx.say("hi")
';
}
--- request
GET /log
--- response_headers
--- error_log eval
[qr/ah{1970}b/]
=== TEST 21: ngx.log in Lua function calls & inlined lua
--- config
location /log {
content_by_lua '
local foo
local bar
function foo()
bar()
end
function bar()
ngx.log(ngx.ERR, "hello, log", 1234, 3.14159)
end
foo()
ngx.say("done")
';
}
--- request
GET /log
--- response_body
done
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):9: bar\(\): hello, log12343.14159/
=== TEST 22: ngx.log in Lua function tail-calls & inlined lua
--- config
location /log {
content_by_lua '
local foo
local bar
function foo()
return bar(5)
end
function bar(n)
if n < 1 then
ngx.log(ngx.ERR, "hello, log", 1234, 3.14159)
return n
end
return bar(n - 1)
end
foo()
ngx.say("done")
';
}
--- request
GET /log
--- response_body
done
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):10:(?: foo\(\):)? hello, log12343.14159/
=== TEST 23: ngx.log in Lua files
--- config
location /log {
content_by_lua_file 'html/test.lua';
}
--- user_files
>>> test.lua
local foo
local bar
function foo()
bar()
end
function bar()
ngx.log(ngx.ERR, "hello, log", 1234, 3.14159)
end
foo()
ngx.say("done")
--- request
GET /log
--- response_body
done
--- error_log eval
qr/\[error\] \S+: \S+ \[lua\] test.lua:8: bar\(\): hello, log12343.14159/
=== TEST 24: ngx.log with bad levels (ngx.ERROR, -1)
--- config
location /log {
content_by_lua '
ngx.log(ngx.ERROR, "hello lua")
ngx.say("done")
';
}
--- request
GET /log
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
bad log level: -1
=== TEST 25: ngx.log with bad levels (9)
--- config
location /log {
content_by_lua '
ngx.log(9, "hello lua")
ngx.say("done")
';
}
--- request
GET /log
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
bad log level: 9
=== TEST 26: \0 in the log message
--- config
location = /t {
content_by_lua '
ngx.log(ngx.WARN, "hello\\0world")
ngx.say("ok")
';
}
--- request
GET /t
--- response_body
ok
--- no_error_log
[error]
--- error_log eval
"2: hello\0world, client: "
=== TEST 27: test log-level STDERR
Note: maximum number of digits after the decimal-point character is 13
--- config
location /log {
content_by_lua_block {
ngx.say("before log")
ngx.log(ngx.STDERR, 3.14159265357939723846)
ngx.say("after log")
}
}
--- request
GET /log
--- response_body
before log
after log
--- error_log eval
qr/\[\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):3: 3.1415926535794/

View file

@ -1,291 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('debug'); # to ensure any log-level can be outputted
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: test reading request body
--- config
location /echo_body {
lua_need_request_body on;
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 2: test not reading request body
--- config
location /echo_body {
lua_need_request_body off;
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 3: test default setting (not reading request body)
--- config
location /echo_body {
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 4: test main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 5: test server conf
--- config
lua_need_request_body on;
location /echo_body {
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 6: test override main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
lua_need_request_body off;
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 7: test override server conf
--- config
lua_need_request_body on;
location /echo_body {
lua_need_request_body off;
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 8: test override server conf
--- config
location /proxy {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /hi {
echo_request_body;
}
location /echo_body {
lua_need_request_body off;
content_by_lua '
ngx.say(ngx.var.request_body or "nil")
local res = ngx.location.capture(
"/proxy",
{ method = ngx.HTTP_POST,
body = ngx.var.request_body })
ngx.say(res.status)
';
}
--- request eval
"POST /echo_body
"
--- response_body
nil
200
=== TEST 9: empty POST body
--- config
location /proxy {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /hi {
echo_request_body;
}
location /echo_body {
lua_need_request_body on;
content_by_lua '
ngx.say(ngx.var.request_body or "nil")
local res = ngx.location.capture(
"/proxy",
{ method = ngx.HTTP_POST,
body = ngx.var.request_body })
ngx.say(res.status)
';
}
--- request eval
"POST /echo_body
"
--- response_body
nil
200
=== TEST 10: on disk request body
--- config
location /proxy {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /hi {
echo_request_body;
}
location /echo_body {
lua_need_request_body on;
client_max_body_size 100k;
client_body_buffer_size 1;
sendfile on;
content_by_lua '
local res = ngx.location.capture(
"/proxy",
{ method = ngx.HTTP_POST,
body = ngx.var.request_body })
ngx.print(res.body)
';
}
--- request eval
"POST /echo_body
" . ('a' x 1024)
--- response_body chomp
=== TEST 11: no modify main request content-length
--- config
location /foo {
content_by_lua '
ngx.location.capture("/other", {body = "hello"})
ngx.say(ngx.req.get_headers()["Content-Length"] or "nil")
';
}
location /other {
echo hi;
}
--- request
POST /foo
hi
--- response_body
2
=== TEST 12: Expect: 100-Continue
--- config
location /echo_body {
lua_need_request_body on;
content_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
}
--- request
POST /echo_body
hello world
--- more_headers
Expect: 100-Continue
--- ignore_response
--- no_error_log
[error]
[alert]
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 13: test reading the first n bytes of request body
--- config
location /echo_body {
lua_need_request_body on;
content_by_lua_block {
local data = ngx.req.get_body_data(1)
ngx.say(data)
}
}
--- request
POST /echo_body
hello
--- response_body
h
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}

View file

@ -1,170 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
#md5_bin_bin is hard to test, so convert it to hex mode
__DATA__
=== TEST 1: set md5_bin hello ????xxoo
--- config
location = /md5_bin {
content_by_lua 'local a = string.gsub(ngx.md5_bin("hello"), ".", function (c)
return string.format("%02x", string.byte(c))
end); ngx.say(a)';
}
--- request
GET /md5_bin
--- response_body
5d41402abc4b2a76b9719d911017c592
=== TEST 2: set md5_bin hello ????xxoo
--- config
location = /md5_bin {
content_by_lua 'ngx.say(string.len(ngx.md5_bin("hello")))';
}
--- request
GET /md5_bin
--- response_body
16
=== TEST 3: set md5_bin hello
--- config
location = /md5_bin {
content_by_lua '
local s = ngx.md5_bin("hello")
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
ngx.say(s)
';
}
--- request
GET /md5_bin
--- response_body
5d41402abc4b2a76b9719d911017c592
=== TEST 4: nil string to ngx.md5_bin
--- config
location = /md5_bin {
content_by_lua '
local s = ngx.md5_bin(nil)
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
ngx.say(s)
';
}
--- request
GET /md5_bin
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 5: null string to ngx.md5_bin
--- config
location /md5_bin {
content_by_lua '
local s = ngx.md5_bin("")
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
ngx.say(s)
';
}
--- request
GET /md5_bin
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 6: use ngx.md5_bin in set_by_lua
--- config
location = /md5_bin {
set_by_lua $a 'return string.gsub(ngx.md5_bin("hello"), ".", function (c)
return string.format("%02x", string.byte(c))
end)';
echo $a;
}
--- request
GET /md5_bin
--- response_body
5d41402abc4b2a76b9719d911017c592
=== TEST 7: use ngx.md5_bin in set_by_lua (nil)
--- config
location = /md5_bin {
set_by_lua $a '
local s = ngx.md5_bin(nil)
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
return s
';
echo $a;
}
--- request
GET /md5_bin
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 8: use ngx.md5_bin in set_by_lua (null string)
--- config
location /md5_bin {
set_by_lua $a '
local s = ngx.md5_bin("")
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
return s
';
echo $a;
}
--- request
GET /md5_bin
--- response_body
d41d8cd98f00b204e9800998ecf8427e
=== TEST 9: md5_bin(number)
--- config
location = /t {
content_by_lua '
local s = ngx.md5_bin(45)
s = string.gsub(s, ".", function (c)
return string.format("%02x", string.byte(c))
end)
ngx.say(s)
';
}
--- request
GET /t
--- response_body
6c8349cc7260ae62e3b1396831a8398f

View file

@ -1,118 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: use ngx.localtime in content_by_lua
--- config
location = /now {
content_by_lua 'ngx.say(ngx.localtime())';
}
--- request
GET /now
--- response_body_like: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$
=== TEST 2: use ngx.localtime in set_by_lua
--- config
location = /now {
set_by_lua $a 'return ngx.localtime()';
echo $a;
}
--- request
GET /now
--- response_body_like: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$
=== TEST 3: use ngx.time in set_by_lua
--- config
location = /time {
set_by_lua $a 'return ngx.time()';
echo $a;
}
--- request
GET /time
--- response_body_like: ^\d{10,}$
=== TEST 4: use ngx.time in content_by_lua
--- config
location = /time {
content_by_lua 'ngx.say(ngx.time())';
}
--- request
GET /time
--- response_body_like: ^\d{10,}$
=== TEST 5: use ngx.time in content_by_lua
--- config
location = /time {
content_by_lua '
ngx.say(ngx.time())
ngx.say(ngx.localtime())
ngx.say(ngx.utctime())
ngx.say(ngx.cookie_time(ngx.time()))
';
}
--- request
GET /time
--- response_body_like chomp
^\d{10,}
\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}
\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}
\w+, .*? GMT$
=== TEST 6: use ngx.now in set_by_lua
--- config
location = /time {
set_by_lua $a 'return ngx.now()';
echo $a;
}
--- request
GET /time
--- response_body_like: ^\d{10,}(\.\d{1,3})?$
=== TEST 7: use ngx.now in content_by_lua
--- config
location = /time {
content_by_lua 'ngx.say(ngx.now())';
}
--- request
GET /time
--- response_body_like: ^\d{10,}(\.\d{1,3})?$
=== TEST 8: use ngx.update_time & ngx.now in content_by_lua
--- config
location = /time {
content_by_lua '
ngx.update_time()
ngx.say(ngx.now())
';
}
--- request
GET /time
--- response_body_like: ^\d{10,}(\.\d{1,3})?$

View file

@ -1,245 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 4);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: base64 encode hello
--- config
location = /encode_base64 {
content_by_lua 'ngx.say(ngx.encode_base64("hello"))';
}
--- request
GET /encode_base64
--- response_body
aGVsbG8=
=== TEST 2: nil string to ngx.encode_base64
--- config
location = /encode_base64 {
content_by_lua 'ngx.say("left" .. ngx.encode_base64(nil) .. "right")';
}
--- request
GET /encode_base64
--- response_body
leftright
=== TEST 3: null string to ngx.encode_base64
--- config
location = /encode_base64 {
content_by_lua 'ngx.say("left" .. ngx.encode_base64("") .. "right")';
}
--- request
GET /encode_base64
--- response_body
leftright
=== TEST 4: use ngx.encode_base64 in set_by_lua
--- config
location = /encode_base64 {
set_by_lua $a 'return ngx.encode_base64("hello")';
echo $a;
}
--- request
GET /encode_base64
--- response_body
aGVsbG8=
=== TEST 5: use ngx.encode_base64 in set_by_lua (nil)
--- config
location = /encode_base64 {
set_by_lua $a 'return "left" .. ngx.encode_base64(nil) .. "right"';
echo $a;
}
--- request
GET /encode_base64
--- response_body
leftright
=== TEST 6: use ngx.encode_base64 in set_by_lua (null string)
--- config
location /encode_base64 {
set_by_lua $a 'return "left" .. ngx.encode_base64("") .. "right"';
echo $a;
}
--- request
GET /encode_base64
--- response_body
leftright
=== TEST 7: base64 encode hello
--- config
location = /decode_base64 {
content_by_lua 'ngx.say(ngx.decode_base64("aGVsbG8="))';
}
--- request
GET /decode_base64
--- response_body
hello
=== TEST 8: null string to ngx.decode_base64
--- config
location = /decode_base64 {
content_by_lua 'ngx.say("left" .. ngx.decode_base64("") .. "right")';
}
--- request
GET /decode_base64
--- response_body
leftright
=== TEST 9: use ngx.decode_base64 in set_by_lua
--- config
location = /decode_base64 {
set_by_lua $a 'return ngx.decode_base64("aGVsbG8=")';
echo $a;
}
--- request
GET /decode_base64
--- response_body
hello
=== TEST 10: use ngx.decode_base64 in set_by_lua (nil)
--- config
location = /decode_base64 {
set_by_lua $a 'return "left" .. ngx.decode_base64(nil) .. "right"';
echo $a;
}
--- request
GET /decode_base64
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
string argument only
=== TEST 11: use ngx.decode_base64 in set_by_lua (null string)
--- config
location /decode_base64 {
set_by_lua $a 'return "left" .. ngx.decode_base64("") .. "right"';
echo $a;
}
--- request
GET /decode_base64
--- response_body
leftright
=== TEST 12: base64 encode number
--- config
location = /t {
content_by_lua 'ngx.say(ngx.encode_base64(32))';
}
--- request
GET /t
--- response_body
MzI=
=== TEST 13: base64 decode number
--- config
location = /t {
content_by_lua 'ngx.say(ngx.decode_base64(32))';
}
--- request
GET /t
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
string argument only
=== TEST 14: base64 decode error
--- config
location = /t {
content_by_lua 'ngx.say(ngx.decode_base64("^*~"))';
}
--- request
GET /t
--- response_body
nil
--- no_error_log
[error]
=== TEST 15: base64 encode without padding (explicit true to no_padding)
--- config
location = /t {
content_by_lua 'ngx.say(ngx.encode_base64("hello", true))';
}
--- request
GET /t
--- response_body
aGVsbG8
=== TEST 16: base64 encode short string
--- config
location = /t {
content_by_lua 'ngx.say(ngx.encode_base64("w"))';
}
--- request
GET /t
--- response_body
dw==
=== TEST 17: base64 encode short string with padding (explicit false to no_padding)
--- config
location = /t {
content_by_lua 'ngx.say(ngx.encode_base64("w", false))';
}
--- request
GET /t
--- response_body
dw==
=== TEST 18: base64 encode with wrong 2nd parameter
--- config
location = /t {
content_by_lua 'ngx.say(ngx.encode_base64("w", 0))';
}
--- request
GET /t
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
qr/bad argument \#2 to 'encode_base64' \(boolean expected, got number\)|\[error\] .*? bad no_padding: boolean expected, got number/

File diff suppressed because one or more lines are too long

View file

@ -1,295 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
#repeat_each(120);
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 9);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: no key found
--- config
location /nil {
content_by_lua '
ngx.say(ngx.blah_blah == nil and "nil" or "not nil")
';
}
--- request
GET /nil
--- response_body
nil
=== TEST 2: .status found
--- config
location /nil {
content_by_lua '
ngx.say(ngx.status == nil and "nil" or "not nil")
';
}
--- request
GET /nil
--- response_body
not nil
=== TEST 3: default to 0
--- config
location /nil {
content_by_lua '
ngx.say(ngx.status);
';
}
--- request
GET /nil
--- response_body
0
=== TEST 4: default to 0
--- config
location /nil {
content_by_lua '
ngx.say("blah");
ngx.say(ngx.status);
';
}
--- request
GET /nil
--- response_body
blah
200
=== TEST 5: set 201
--- config
location /201 {
content_by_lua '
ngx.status = 201;
ngx.say("created");
';
}
--- request
GET /201
--- response_body
created
--- error_code: 201
=== TEST 6: set "201"
--- config
location /201 {
content_by_lua '
ngx.status = "201";
ngx.say("created");
';
}
--- request
GET /201
--- response_body
created
--- error_code: 201
=== TEST 7: set "201.7"
--- config
location /201 {
content_by_lua '
ngx.status = "201.7";
ngx.say("created");
';
}
--- request
GET /201
--- response_body
created
--- error_code: 201
=== TEST 8: set "abc"
--- config
location /201 {
content_by_lua '
ngx.status = "abc";
ngx.say("created");
';
}
--- request
GET /201
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 9: set blah
--- config
location /201 {
content_by_lua '
ngx.blah = 201;
ngx.say("created");
';
}
--- request
GET /201
--- response_body
created
--- no_error_log
[error]
=== TEST 10: set ngx.status before headers are sent
--- config
location /t {
content_by_lua '
ngx.say("ok")
ngx.status = 201
';
}
--- request
GET /t
--- response_body
ok
--- error_code: 200
--- error_log eval
qr/\[error\] .*? attempt to set ngx\.status after sending out response headers/
=== TEST 11: http 1.0 and ngx.status
--- config
location /nil {
content_by_lua '
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("invalid request")
ngx.exit(ngx.HTTP_OK)
';
}
--- request
GET /nil HTTP/1.0
--- response_body
invalid request
--- error_code: 401
--- no_error_log
[error]
=== TEST 12: github issue #221: cannot modify ngx.status for responses from ngx_proxy
--- config
location = /t {
proxy_pass http://127.0.0.1:$server_port/;
header_filter_by_lua '
if ngx.status == 206 then
ngx.status = ngx.HTTP_OK
end
';
}
--- request
GET /t
--- more_headers
Range: bytes=0-4
--- response_body chop
<html
--- error_code: 200
--- no_error_log
[error]
=== TEST 13: 101 response has a complete status line
--- config
location /t {
content_by_lua '
ngx.status = 101
ngx.send_headers()
';
}
--- request
GET /t
--- raw_response_headers_like: ^HTTP/1.1 101 Switching Protocols\r\n
--- error_code: 101
--- no_error_log
[error]
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
--- no_http2
=== TEST 14: reading error status code
--- config
location = /t {
content_by_lua 'ngx.say("status = ", ngx.status)';
}
--- raw_request eval
"GET /t\r\n"
--- http09
--- response_body
status = 9
=== TEST 15: err status
--- config
location /nil {
content_by_lua '
ngx.exit(502)
';
body_filter_by_lua '
if ngx.arg[2] then
ngx.log(ngx.WARN, "ngx.status = ", ngx.status)
end
';
}
--- request
GET /nil
--- response_body_like: 502 Bad Gateway
--- error_code: 502
--- error_log
ngx.status = 502
--- no_error_log
[error]
=== TEST 16: ngx.status assignment should clear r->err_status
--- config
location = /t {
return 502;
header_filter_by_lua_block {
if ngx.status == 502 then
ngx.status = 654
ngx.log(ngx.WARN, "ngx.status: ", ngx.status)
end
}
}
--- request
GET /t
--- response_body_like: Bad Gateway
--- error_log
ngx.status: 654
--- no_error_log
[error]
--- error_code: 654

File diff suppressed because it is too large Load diff

View file

@ -1,596 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 8);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
#no_shuffle();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /read {
content_by_lua '
ngx.exec("/hi");
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body
Hello
=== TEST 2: empty uri arg
--- config
location /read {
content_by_lua '
ngx.exec("");
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 3: no arg
--- config
location /read {
content_by_lua '
ngx.exec();
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: too many args
--- config
location /read {
content_by_lua '
ngx.exec(1, 2, 3, 4);
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 5: null uri
--- config
location /read {
content_by_lua '
ngx.exec(nil)
ngx.say("Hi")
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: user args
--- config
location /read {
content_by_lua '
ngx.exec("/hi", "Yichun Zhang")
ngx.say("Hi")
';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello Yichun Zhang
=== TEST 7: args in uri
--- config
location /read {
content_by_lua '
ngx.exec("/hi?agentzh")
ngx.say("Hi")
';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello agentzh
=== TEST 8: args in uri and user args
--- config
location /read {
content_by_lua '
ngx.exec("/hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello a=Yichun&b=Zhang
=== TEST 9: args in uri and user args
--- config
location /read {
content_by_lua '
ngx.exec("@hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
}
location @hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello
=== TEST 10: exec after location capture (simple echo)
--- config
location /test {
content_by_lua_file 'html/test.lua';
}
location /a {
echo "hello";
}
location /b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('/b')
--- request
GET /test
--- response_body
hello
=== TEST 11: exec after location capture (memc)
--- config
location /test {
content_by_lua_file 'html/test.lua';
}
location /a {
set $memc_key 'hello world';
set $memc_value 'hello hello hello world world world';
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /b {
set $memc_key 'hello world';
set $memc_cmd get;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('/b')
--- request
GET /test
--- response_body: hello hello hello world world world
=== TEST 12: exec after named location capture (simple echo)
--- config
location /test {
content_by_lua_file 'html/test.lua';
}
location /a {
echo "hello";
}
location @b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('@b')
--- request
GET /test
--- response_body
hello
=== TEST 13: exec after named location capture (memc)
--- config
location /test {
content_by_lua_file 'html/test.lua';
}
location /a {
set $memc_key 'hello world';
set $memc_value 'hello hello hello world world world';
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location @b {
set $memc_key 'hello world';
set $memc_cmd get;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('@b')
--- request
GET /test
--- response_body: hello hello hello world world world
=== TEST 14: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (content)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
#echo hello;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
content_by_lua '
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 15: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (content + named location)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
#echo hello;
}
location @p {
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
content_by_lua '
ngx.exec("@p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 16: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (content + post subrequest)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
#echo hello;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location blah {
echo blah;
}
location /lua {
content_by_lua '
ngx.location.capture("/blah")
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 17: pcall safe
--- config
location /lua {
content_by_lua '
local function f ()
ngx.exec("/hi")
end
pcall(f)
ngx.say("hello")
';
}
location /hi {
echo hi;
}
--- request
GET /lua
--- error_code: 200
--- response_body
hi
=== TEST 18: lua table as "args" parameter
--- config
location /lua {
content_by_lua '
local args = { foo = 3, bar = 4 }
ngx.exec("/hi", args)
';
}
location /hi {
echo "foo = $arg_foo";
echo "bar = $arg_bar";
}
--- request
GET /lua
--- error_code: 200
--- response_body
foo = 3
bar = 4
=== TEST 19: jump to internal locations requires ctx cleared
--- config
location @proxy {
rewrite_by_lua return;
echo hello;
}
location /main {
content_by_lua '
ngx.exec("@proxy")
';
}
--- request
GET /main
--- response_body
hello
=== TEST 20: exec + rewrite + named locations
--- config
location @proxy {
rewrite_by_lua return;
echo hello;
}
location /main {
rewrite_by_lua '
ngx.exec("@proxy")
';
}
--- request
GET /main
--- response_body
hello
=== TEST 21: exec(named location) in subrequests
--- config
location /entry {
echo_location /foo;
echo_location /foo2;
}
location /foo {
content_by_lua '
ngx.exec("@bar")
';
}
location /foo2 {
content_by_lua '
ngx.exec("@bar")
';
}
location @bar {
proxy_pass http://127.0.0.1:$server_port/bar;
}
location /bar {
echo hello;
}
--- request
GET /entry
--- response_body
hello
hello
=== TEST 22: exec(normal location) in subrequests
--- config
location /entry {
echo_location /foo;
echo_location /foo2;
}
location /foo {
content_by_lua '
ngx.exec("/baz")
';
}
location /foo2 {
content_by_lua '
ngx.exec("/baz")
';
}
location /baz {
proxy_pass http://127.0.0.1:$server_port/bar;
}
location /bar {
echo hello;
}
--- request
GET /entry
--- response_body
hello
hello
=== TEST 23: content_by_lua + ngx.exec + subrequest capture
--- config
location /main {
rewrite_by_lua '
local res = ngx.location.capture("/test_loc");
ngx.print("hello, ", res.body)
';
content_by_lua return;
}
location /test_loc {
content_by_lua '
ngx.exec("@proxy")
';
}
location @proxy {
#echo proxy;
proxy_pass http://127.0.0.1:$server_port/foo;
}
location /foo {
#echo_status 201;
echo bah;
}
--- request
GET /main
--- response_body
hello, bah
=== TEST 24: jump to an internal location
--- config
location /t {
content_by_lua '
return ngx.exec("/proxy", ngx.var.args)
';
}
location /proxy {
internal;
proxy_pass http://127.0.0.1:$server_port/dummy;
}
location = /dummy {
echo -n dummy;
}
--- pipelined_requests eval
["GET /t", "GET /t?foo"]
--- response_body eval
["dummy", "dummy"]
--- no_error_log
[error]
=== TEST 25: pipelined requests
--- config
location /t {
content_by_lua_block {
ngx.exec("@foo")
}
}
location @foo {
return 200;
}
--- pipelined_requests eval
["GET /t", "GET /t"]
--- error_code eval
[200, 200]
--- response_body eval
["", ""]
--- no_error_log
[error]

View file

@ -1,173 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 4);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /read {
content_by_lua '
local s = ndk.set_var.set_escape_uri(" :")
local r = ndk.set_var.set_unescape_uri("a%20b")
ngx.say(s)
ngx.say(r)
';
}
--- request
GET /read
--- response_body
%20%3A
a b
=== TEST 2: directive not found
--- config
location /read {
content_by_lua '
local s = ndk.set_var.set_escape_uri_blah_blah(" :")
ngx.say(s)
';
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 3: directive not found
--- config
location /read {
content_by_lua '
local s = ndk.set_var.content_by_lua(" :")
ngx.say(s)
';
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: directive not found
--- config
location /read {
header_filter_by_lua '
ngx.header.Foo = ndk.set_var.set_escape_uri(" %")
';
echo hi;
}
--- request
GET /read
--- response_headers
Foo: %20%25
--- response_body
hi
=== TEST 5: bug: ndk.set_var not initialize ngx_http_variable_value_t variable properly
--- config
location /luaset {
content_by_lua "
local version = '2011.10.13+0000'
local e_version = ndk.set_var.set_encode_base32(version)
local s_version= ndk.set_var.set_quote_sql_str(version)
ngx.say(e_version)
ngx.say(s_version)
";
}
--- request
GET /luaset
--- response_body
68o32c9e64o2sc9j5co30c1g
'2011.10.13+0000'
=== TEST 6: set_by_lua
--- config
location /read {
set_by_lua $r '
return ndk.set_var.set_unescape_uri("a%20b")
';
echo $r;
}
--- request
GET /read
--- response_body
a b
=== TEST 7: header_filter_by_lua
--- config
location /read {
set $foo '';
content_by_lua '
ngx.send_headers()
ngx.say(ngx.var.foo)
';
header_filter_by_lua '
ngx.var.foo = ndk.set_var.set_unescape_uri("a%20b")
';
}
--- request
GET /read
--- response_body
a b
=== TEST 8: log_by_lua
--- config
location /read {
echo ok;
log_by_lua '
local foo = ndk.set_var.set_unescape_uri("a%20b")
ngx.log(ngx.WARN, "foo = ", foo)
';
}
--- request
GET /read
--- response_body
ok
--- wait: 0.1
--- error_log
foo = a b
=== TEST 9: ngx.timer.*
--- config
location /read {
echo ok;
log_by_lua '
ngx.timer.at(0, function ()
local foo = ndk.set_var.set_unescape_uri("a%20b")
ngx.log(ngx.WARN, "foo = ", foo)
end)
';
}
--- request
GET /read
--- response_body
ok
--- wait: 0.1
--- error_log
foo = a b
--- no_error_log
[error]

View file

@ -1,46 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => blocks() * repeat_each() * 2;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /read {
content_by_lua '
ngx.say(ngx.OK)
ngx.say(ngx.AGAIN)
ngx.say(ngx.DONE)
ngx.say(ngx.ERROR)
';
}
--- request
GET /read
--- response_body
0
-2
-4
-1
=== TEST 2: http constants
--- config
location /read {
content_by_lua '
ngx.say(ngx.HTTP_GATEWAY_TIMEOUT)
';
}
--- request
GET /read
--- response_body
504

File diff suppressed because it is too large Load diff

View file

@ -1,45 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: cookie_time
--- config
location /lua {
content_by_lua '
ngx.say(ngx.cookie_time(1290079655))
';
}
--- request
GET /lua
--- response_body
Thu, 18-Nov-10 11:27:35 GMT
=== TEST 2: cookie_time in set_by_lua
--- config
location /lua {
set_by_lua $a '
return ngx.cookie_time(1290079655)
';
echo $a;
}
--- request
GET /lua
--- response_body
Thu, 18-Nov-10 11:27:35 GMT

View file

@ -1,428 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 3 + 9);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: default 302
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo");
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 2: explicit 302
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo", ngx.HTTP_MOVED_TEMPORARILY);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 3: explicit 301
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo", ngx.HTTP_MOVED_PERMANENTLY);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo
--- response_body_like: 301 Moved Permanently
--- error_code: 301
=== TEST 4: bad rc
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo", 404);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log
only ngx.HTTP_MOVED_TEMPORARILY, ngx.HTTP_MOVED_PERMANENTLY, ngx.HTTP_PERMANENT_REDIRECT, ngx.HTTP_SEE_OTHER, and ngx.HTTP_TEMPORARY_REDIRECT are allowed
=== TEST 5: no args
--- config
location /read {
content_by_lua '
ngx.redirect()
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: relative uri
--- config
location /echo {
echo hello, world;
}
location /proxy {
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/echo;
}
location /read {
content_by_lua '
ngx.location.capture("/proxy")
ngx.redirect("/echo")
ngx.say("hi")
';
}
--- request
GET /read
--- raw_response_headers_like eval
my $headers;
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
$headers = "location: /echo\r\n"
} else {
$headers = "Location: /echo\r\n"
}
$headers;
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 7: default 302 (with uri args)
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?bar=3");
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo?bar=3
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 8: location.capture + ngx.redirect
--- config
location /echo {
echo hello, world;
}
location /proxy {
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/echo;
}
location /read {
content_by_lua '
ngx.location.capture("/proxy")
ngx.location.capture("/proxy")
ngx.redirect("/echo")
ngx.exit(403)
';
}
--- pipelined_requests eval
["GET /read/1", "GET /read/2"]
--- error_code eval
[302, 302]
--- response_body eval
[qr/302 Found/, qr/302 Found/]
=== TEST 9: explicit 307
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo", ngx.HTTP_TEMPORARY_REDIRECT);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo
--- response_body_like: 307 Temporary Redirect
--- error_code: 307
=== TEST 10: explicit 307 with args
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?a=b&c=d", ngx.HTTP_TEMPORARY_REDIRECT);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- response_body_like: 307 Temporary Redirect
--- error_code: 307
=== TEST 11: explicit 307
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?a=b&c=d", 307);
ngx.say("hi")
';
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- response_body_like: 307 Temporary Redirect
--- error_code: 307
=== TEST 12: explicit 303
--- config
location /read {
content_by_lua_block {
ngx.redirect("http://agentzh.org/foo", ngx.HTTP_SEE_OTHER);
ngx.say("hi")
}
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo
--- response_body_like: 303 See Other
--- error_code: 303
=== TEST 13: explicit 303 with args
--- config
location /read {
content_by_lua_block {
ngx.redirect("http://agentzh.org/foo?a=b&c=d", ngx.HTTP_SEE_OTHER);
ngx.say("hi")
}
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- response_body_like: 303 See Other
--- error_code: 303
=== TEST 14: explicit 303
--- config
location /read {
content_by_lua_block {
ngx.redirect("http://agentzh.org/foo?a=b&c=d", 303);
ngx.say("hi")
}
}
--- request
GET /read
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- response_body_like: 303 See Other
--- error_code: 303
=== TEST 15: explicit 308 with args
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?a=b&c=d", ngx.HTTP_PERMANENT_REDIRECT);
ngx.say("hi")
';
}
--- request
GET /read
--- response_body_like: 308 Permanent Redirect
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- error_code: 308
=== TEST 16: explicit 308
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?a=b&c=d", 308);
ngx.say("hi")
';
}
--- request
GET /read
--- response_body_like: 308 Permanent Redirect
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- error_code: 308
=== TEST 17: explicit 308 with args
--- config
location /read {
content_by_lua '
ngx.redirect("http://agentzh.org/foo?a=b&c=d", 308);
ngx.say("hi")
';
}
--- request
GET /read
--- response_body_like: 308 Permanent Redirect
--- response_headers
Location: http://agentzh.org/foo?a=b&c=d
--- error_code: 308
=== TEST 18: unsafe uri (with '\r')
--- config
location = /t {
content_by_lua_block {
ngx.redirect("http://agentzh.org/foo\rfoo:bar\nbar:foo");
ngx.say("hi")
}
}
--- request
GET /t
--- error_code: 500
--- response_headers
Location:
foo:
bar:
--- error_log
unsafe byte "0x0d" in redirect uri "http://agentzh.org/foo\x0Dfoo:bar\x0Abar:foo"
=== TEST 19: unsafe uri (with '\n')
--- config
location = /t {
content_by_lua_block {
ngx.redirect("http://agentzh.org/foo\nfoo:bar\rbar:foo");
ngx.say("hi")
}
}
--- request
GET /t
--- error_code: 500
--- response_headers
Location:
foo:
bar:
--- error_log
unsafe byte "0x0a" in redirect uri "http://agentzh.org/foo\x0Afoo:bar\x0Dbar:foo"
=== TEST 20: unsafe uri (with prefix '\n')
--- config
location = /t {
content_by_lua_block {
ngx.redirect("\nfoo:http://agentzh.org/foo");
ngx.say("hi")
}
}
--- request
GET /t
--- error_code: 500
--- response_headers
Location:
foo:
--- error_log
unsafe byte "0x0a" in redirect uri "\x0Afoo:http://agentzh.org/foo"
=== TEST 21: unsafe uri (with prefix '\r')
--- config
location = /t {
content_by_lua_block {
ngx.redirect("\rfoo:http://agentzh.org/foo");
ngx.say("hi")
}
}
--- request
GET /t
--- error_code: 500
--- response_headers
Location:
foo:
--- error_log
unsafe byte "0x0d" in redirect uri "\x0Dfoo:http://agentzh.org/foo"
=== TEST 22: unsafe uri logging escapes '"' and '\' characters
--- config
location = /t {
content_by_lua_block {
ngx.redirect("\rhttp\\://\"agentzh.org\"/foo");
ngx.say("hi")
}
}
--- request
GET /t
--- error_code: 500
--- response_headers
Location:
foo:
--- error_log
unsafe byte "0x0d" in redirect uri "\x0Dhttp\x5C://\x22agentzh.org\x22/foo"

View file

@ -1,856 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = <<_EOC_;
$t::StapThread::GCScript
F(ngx_http_lua_check_broken_connection) {
println("lua check broken conn")
}
F(ngx_http_lua_request_cleanup) {
println("lua req cleanup")
}
_EOC_
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
plan(skip_all => "HTTP3 does not support client abort");
} elsif (defined $ENV{TEST_NGINX_USE_HTTP2}) {
plan(skip_all => "HTTP2 does not support client abort");
} else {
plan tests => repeat_each() * (blocks() * 3 - 1);
}
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 0.1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 2: sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 3: sleep + ignore
--- config
location /t {
lua_check_client_abort off;
rewrite_by_lua '
ngx.sleep(1)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
=== TEST 4: subrequest + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location /sub {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 5: subrequest + ignore
--- config
location /t {
lua_check_client_abort off;
rewrite_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location /sub {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: fail
lua req cleanup
delete thread 1
--- wait: 1.1
--- timeout: 0.2
--- abort
--- ignore_response
--- error_log
bad things happen
=== TEST 6: subrequest + stop (proxy, ignore client abort)
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location = /sub {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.2:12345/;
}
location = /sleep {
lua_check_client_abort on;
rewrite_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 7: subrequest + stop (proxy, check client abort)
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location = /sub {
proxy_ignore_client_abort off;
proxy_pass http://127.0.0.2:12345/;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 8: need body on + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
lua_need_request_body on;
rewrite_by_lua '
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 9: ngx.req.read_body + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.req.read_body()
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 10: ngx.req.socket + receive() + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
sock:receive()
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 11: ngx.req.socket + receive(N) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
sock:receive(5)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 0.1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 12: ngx.req.socket + receive(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
sock:receive(2)
ngx.sleep(1)
';
content_by_lua return;
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out_like
^(?:lua check broken conn
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup|lua check broken conn
lua req cleanup
delete thread 1)$
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
=== TEST 13: ngx.req.socket + m * receive(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
sock:receive(2)
sock:receive(2)
sock:receive(1)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 14: ngx.req.socket + receiveuntil + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
local it = sock:receiveuntil("\\n")
it()
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 15: ngx.req.socket + receiveuntil + it(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
local it = sock:receiveuntil("\\n")
it(2)
it(3)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 16: cosocket + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.req.discard_body()
local sock, err = ngx.socket.tcp()
if not sock then
ngx.log(ngx.ERR, "failed to get socket: ", err)
return
end
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
if not ok then
ngx.log(ngx.ERR, "failed to connect: ", err)
return
end
local bytes, err = sock:send("blpop nonexist 2\\r\\n")
if not bytes then
ngx.log(ngx.ERR, "failed to send query: ", err)
return
end
-- ngx.log(ngx.ERR, "about to receive")
local res, err = sock:receive()
if not res then
ngx.log(ngx.ERR, "failed to receive query: ", err)
return
end
ngx.log(ngx.ERR, "res: ", res)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 17: ngx.req.socket + receive n < content-length + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
error("bad")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 100\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
failed to receive: client aborted
=== TEST 18: ngx.req.socket + receive n == content-length + stop
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
ngx.sleep(1)
error("bad")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 5\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 19: ngx.req.socket + receive n == content-length + ignore
--- config
location /t {
rewrite_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
ngx.say("done")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 5\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- shutdown: 1
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 20: ngx.req.read_body + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.req.read_body()
';
content_by_lua return;
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- shutdown: 1
--- wait: 0.1
--- ignore_response
--- no_error_log
[error]
=== TEST 21: exec to lua + ignore
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.exec("/t2")
';
}
location = /t2 {
lua_check_client_abort off;
content_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 22: exec to proxy + ignore
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.exec("/t2")
';
}
location = /t2 {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.1:$server_port/sleep;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 23: exec (named location) to proxy + ignore
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
ngx.exec("@t2")
';
}
location @t2 {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.1:$server_port/sleep;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]

View file

@ -1,400 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2 + 4);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /read {
rewrite_by_lua '
ngx.exec("/hi");
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body
Hello
=== TEST 2: empty uri arg
--- config
location /read {
rewrite_by_lua '
ngx.exec("");
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 3: no arg
--- config
location /read {
rewrite_by_lua '
ngx.exec();
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: too many args
--- config
location /read {
rewrite_by_lua '
ngx.exec(1, 2, 3, 4);
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 5: null uri
--- config
location /read {
rewrite_by_lua '
ngx.exec(nil)
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: user args
--- config
location /read {
rewrite_by_lua '
ngx.exec("/hi", "Yichun Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello Yichun Zhang
=== TEST 7: args in uri
--- config
location /read {
rewrite_by_lua '
ngx.exec("/hi?agentzh")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello agentzh
=== TEST 8: args in uri and user args
--- config
location /read {
rewrite_by_lua '
ngx.exec("/hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello a=Yichun&b=Zhang
=== TEST 9: args in uri and user args
--- config
location /read {
rewrite_by_lua '
ngx.exec("@hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location @hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello
=== TEST 10: exec after location capture
--- config
location /test {
rewrite_by_lua_file 'html/test.lua';
echo world;
}
location /a {
echo "hello";
}
location /b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('/b')
--- request
GET /test
--- response_body
hello
=== TEST 11: exec after (named) location capture
--- config
location /test {
rewrite_by_lua_file 'html/test.lua';
}
location /a {
echo "hello";
}
location @b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('@b')
--- request
GET /test
--- response_body
hello
=== TEST 12: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (rewrite)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
rewrite_by_lua '
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 13: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (rewrite + named location)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location @p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
rewrite_by_lua '
ngx.exec("@p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 14: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (rewrite + post subrequest)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /blah {
echo blah;
}
location /lua {
rewrite_by_lua '
ngx.location.capture("/blah")
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 15: rewrite_by_lua + ngx.exec + subrequest capture
--- config
location /main {
rewrite_by_lua '
local res = ngx.location.capture("/test_loc");
ngx.print("hello, ", res.body)
';
content_by_lua return;
}
location /test_loc {
rewrite_by_lua '
ngx.exec("@proxy")
';
}
location @proxy {
#echo proxy;
proxy_pass http://127.0.0.1:$server_port/foo;
}
location /foo {
echo bah;
}
--- request
GET /main
--- response_body
hello, bah
=== TEST 16: rewrite_by_lua_file + ngx.exec + subrequest capture
--- config
location /main {
rewrite_by_lua '
local res = ngx.location.capture("/test_loc");
ngx.print("hello, ", res.body)
';
content_by_lua return;
}
location /test_loc {
rewrite_by_lua_file html/jump.lua;
}
location @proxy {
#echo proxy;
proxy_pass http://127.0.0.1:$server_port/foo;
}
location /foo {
echo bah;
}
--- user_files
>>> jump.lua
ngx.exec("@proxy")
--- request
GET /main
--- response_body
hello, bah
=== TEST 17: pipelined requests
--- config
location /t {
rewrite_by_lua_block {
ngx.exec("@foo")
}
}
location @foo {
return 200;
}
--- pipelined_requests eval
["GET /t", "GET /t"]
--- error_code eval
[200, 200]
--- response_body eval
["", ""]
--- no_error_log
[error]

View file

@ -1,600 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#repeat_each(20000);
repeat_each(2);
#master_on();
#workers(1);
#log_level('debug');
#log_level('warn');
#worker_connections(1024);
plan tests => repeat_each() * (blocks() * 2 + 4);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
our $LuaCpath = $ENV{LUA_CPATH} ||
'/usr/local/openresty-debug/lualib/?.so;/usr/local/openresty/lualib/?.so;;';
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
no_long_string();
#no_shuffle();
run_tests();
__DATA__
=== TEST 1: throw 403
--- config
location /lua {
rewrite_by_lua "ngx.exit(403);ngx.say('hi')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 403
--- response_body_like: 403 Forbidden
=== TEST 2: throw 404
--- config
location /lua {
rewrite_by_lua "ngx.exit(404);ngx.say('hi');";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 404
--- response_body_like: 404 Not Found
=== TEST 3: throw 404 after sending the header and partial body
--- config
location /lua {
rewrite_by_lua "ngx.say('hi');ngx.exit(404);ngx.say(', you')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_log
attempt to set status 404 via ngx.exit after sending out the response status 200
--- response_body
hi
=== TEST 4: working with ngx_auth_request (succeeded)
--- config
location /auth {
rewrite_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $user $arg_user;
auth_request /auth;
echo "Logged in";
}
--- request
GET /api?user=agentzh
--- error_code: 200
--- response_body
Logged in
=== TEST 5: working with ngx_auth_request (failed)
--- config
location /auth {
rewrite_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $user $arg_user;
auth_request /auth;
echo "Logged in";
}
--- request
GET /api?user=agentz
--- error_code: 403
--- response_body_like: 403 Forbidden
=== TEST 6: working with ngx_auth_request (simplest form, w/o ngx_memc)
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
rewrite_by_lua_file 'html/foo.lua';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
-- ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 7: working with ngx_auth_request (simplest form)
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
rewrite_by_lua_file 'html/foo.lua';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 8: working with ngx_auth_request
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream memc_b {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream_list memc_cluster memc_a memc_b;
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass $backend;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
rewrite_by_lua_file 'html/foo.lua';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $uid $arg_uid;
auth_request /conv-uid;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- no_error_log
[error]
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 9: working with ngx_auth_request
--- http_config
upstream backend {
drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
keepalive 300;
}
#upstream_list memc_cluster memc_a memc_b;
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
#set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass memc_a;
}
location /conv-mysql {
internal;
set $key "conv-uri-$query_string";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
set_quote_sql_str $seo_uri $query_string;
drizzle_query "select url from my_url_map where seo_url=$seo_uri";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
rewrite_by_lua_file 'html/foo.lua';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /baz {
set $my_uri $uri;
auth_request /conv-uid;
echo_exec /jump $my_uri;
}
location /jump {
internal;
rewrite ^ $query_string? redirect;
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local seo_uri = ngx.var.my_uri
-- print('about to run sr')
local res = ngx.location.capture('/conv-mysql?' .. seo_uri)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].url) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.my_uri = res[1].url;
-- print('done')
--- request
GET /baz
--- response_body_like: 302
--- error_code: 302
--- response_headers
Location: http://localhost:$ServerPort/foo/bar
--- SKIP
=== TEST 10: throw 0
--- config
location /lua {
rewrite_by_lua "ngx.say('Hi'); ngx.eof(); ngx.exit(0);ngx.say('world')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 200
--- response_body
Hi
=== TEST 11: throw ngx.OK does *not* skip other rewrite phase handlers
--- config
location /lua {
rewrite_by_lua "ngx.exit(ngx.OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
hello
=== TEST 12: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by inlined code)
--- config
location /lua {
rewrite_by_lua "ngx.exit(ngx.HTTP_OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
=== TEST 13: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by inlined code + partial output)
--- config
location /lua {
rewrite_by_lua "ngx.say('hiya') ngx.exit(ngx.HTTP_OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
hiya
=== TEST 14: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by file)
--- config
location /lua {
rewrite_by_lua_file html/foo.lua;
set $foo hello;
echo $foo;
}
--- user_files
>>> foo.lua
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua
--- response_body
=== TEST 15: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by file + partial output)
--- config
location /lua {
rewrite_by_lua_file html/foo.lua;
set $foo hello;
echo $foo;
}
--- user_files
>>> foo.lua
ngx.say("morning")
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua
--- response_body
morning
=== TEST 16: error page with custom body
--- config
error_page 410 @err;
location @err {
echo blah blah;
}
location /foo {
rewrite_by_lua '
ngx.status = ngx.HTTP_GONE
ngx.say("This is our own content")
-- to cause quit the whole request rather than the current phase handler
ngx.exit(ngx.HTTP_OK)
';
echo Hello;
}
--- request
GET /foo
--- response_body
This is our own content
--- error_code: 410
=== TEST 17: exit with 204 (HTTP 1.1)
--- config
location = /t {
rewrite_by_lua '
ngx.exit(204)
';
proxy_pass http://127.0.0.1:$server_port/blah;
}
location = /blah {
echo blah;
}
--- request
GET /t
--- more_headers2
--- stap2
F(ngx_http_send_header) {
printf("send header\n")
print_ubacktrace()
}
--- response_body
--- error_code: 204
--- no_error_log
[error]
=== TEST 18: exit with 204 (HTTP 1.0)
--- config
location = /t {
rewrite_by_lua '
ngx.exit(204)
';
proxy_pass http://127.0.0.1:$server_port/blah;
}
location = /blah {
echo blah;
}
--- request
GET /t HTTP/1.0
--- more_headers2
--- stap2
F(ngx_http_send_header) {
printf("send header\n")
print_ubacktrace()
}
--- response_body
--- error_code: 204
--- no_error_log
[error]

View file

@ -1,169 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2 + 3);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: rewrite I/O with content I/O
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
rewrite_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
print("rewrite GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
print("rewrite PUT: " .. res.status);
res = ngx.location.capture("/memc");
print("rewrite cached: " .. res.body);
';
content_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
ngx.say("content GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.say("content PUT: " .. res.status);
res = ngx.location.capture("/memc");
ngx.say("content cached: " .. res.body);
';
}
--- request
GET /lua
--- response_body
content GET: 404
content PUT: 201
content cached: hello
--- grep_error_log eval: qr/rewrite .+?(?= while )/
--- grep_error_log_out
rewrite GET: 404
rewrite PUT: 201
rewrite cached: hello
--- log_level: info
--- no_error_log
[error]
[alert]
=== TEST 2: share data via nginx variables
--- config
location /foo {
set $foo '';
rewrite_by_lua '
ngx.var.foo = 32
';
content_by_lua '
ngx.say(tonumber(ngx.var.foo) * 2)
';
}
--- request
GET /foo
--- response_body
64
=== TEST 3: share the request body (need request body explicitly off)
--- config
location /echo_body {
lua_need_request_body off;
set $res '';
rewrite_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body
nil
nil
=== TEST 4: share the request body (need request body off by default)
--- config
location /echo_body {
#lua_need_request_body off;
set $res '';
rewrite_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body
nil
nil
=== TEST 5: share the request body (need request body on)
--- config
location /echo_body {
lua_need_request_body on;
set $res '';
rewrite_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff
hello\x00\x01\x02
world\x03\x04\xff
"

View file

@ -1,394 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(10);
plan tests => blocks() * repeat_each() * 2;
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /foo {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
=== TEST 2: 4 concurrent requests
--- config
location /foo {
rewrite_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
content_by_lua return;
}
location ~ '^/([a-d])$' {
echo -n $1;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
res3.status = 200
res3.body = c
res4.status = 200
res4.body = d
=== TEST 3: capture multi in series
--- config
location /foo {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("2 res1.status = " .. res1.status)
ngx.say("2 res1.body = " .. res1.body)
ngx.say("2 res2.status = " .. res2.status)
ngx.say("2 res2.body = " .. res2.body)
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
2 res1.status = 200
2 res1.body = a
2 res2.status = 200
2 res2.body = b
=== TEST 4: capture multi in subrequest
--- config
location /foo {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location /main {
rewrite_by_lua '
local res = ngx.location.capture("/foo?n=1")
ngx.say("top res.status = " .. res.status)
ngx.say("top res.body = [" .. res.body .. "]")
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /main
--- response_body
top res.status = 200
top res.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
=== TEST 5: capture multi in parallel
--- config
location ~ '^/(foo|bar)$' {
set $tag $1;
rewrite_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location /main {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("top res1.status = " .. res1.status)
ngx.say("top res1.body = [" .. res1.body .. "]")
ngx.say("top res2.status = " .. res2.status)
ngx.say("top res2.body = [" .. res2.body .. "]")
';
content_by_lua return;
}
location ~ '^/([abcd])$' {
echo -n $1;
}
--- request
GET /main
--- response_body
top res1.status = 200
top res1.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
top res2.status = 200
top res2.body = [2 res1.status = 200
2 res1.body = c
2 res2.status = 200
2 res2.body = d
]
=== TEST 6: memc sanity
--- config
location /foo {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
content_by_lua return;
}
location ~ '^/[ab]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
"
=== TEST 7: memc muti + multi
--- config
location /main {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = [" .. res1.body .. "]")
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = [" .. res2.body .. "]")
';
content_by_lua return;
}
location ~ '^/(foo|bar)$' {
set $tag $1;
rewrite_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
print("args: " .. ngx.var.args)
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location ~ '^/[abcd]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /main
--- response_body eval
"res1.status = 200
res1.body = [1 res1.status = 201
1 res1.body = STORED\r
1 res2.status = 201
1 res2.body = STORED\r
]
res2.status = 200
res2.body = [2 res1.status = 201
2 res1.body = STORED\r
2 res2.status = 201
2 res2.body = STORED\r
]
"
=== TEST 8: memc 4 concurrent requests
--- config
location /foo {
rewrite_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
content_by_lua return;
}
location ~ '^/[a-d]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
res3.status = 201
res3.body = STORED\r
res4.status = 201
res4.body = STORED\r
"

View file

@ -1,662 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = <<_EOC_;
$t::StapThread::GCScript
F(ngx_http_lua_check_broken_connection) {
println("lua check broken conn")
}
F(ngx_http_lua_request_cleanup) {
println("lua req cleanup")
}
_EOC_
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
plan(skip_all => "HTTP3 does not support on_abort");
} elsif (defined $ENV{TEST_NGINX_USE_HTTP2}) {
plan(skip_all => "HTTP2 does not support on_abort");
} else {
plan tests => repeat_each() * (blocks() * 4 + 15);
}
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: ignore the client abort event in the user callback
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
terminate 1: ok
delete thread 2
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
--- timeout: 0.2
--- abort
--- wait: 0.7
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 2: abort in the user callback
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(444)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- wait: 0.1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
=== TEST 3: ngx.exit(499) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(499)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 4: ngx.exit(408) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(408)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- wait: 0.1
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 5: ngx.exit(-1) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(-1)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 6: ngx.exit(0) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(0)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
ngx.log(ngx.ERR, "main handler done")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 0.7;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out_like eval
qr/^create 2 in 1
lua check broken conn
terminate 2: fail
(?:lua check broken conn
)?terminate 1: ok
delete thread 2
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
$/
--- timeout: 0.2
--- abort
--- wait: 0.6
--- ignore_response
--- error_log eval
[
'client prematurely closed connection',
'on abort called',
qr/lua user thread aborted: runtime error: rewrite_by_lua\(nginx\.conf:\d+\):4: attempt to abort with pending subrequests/,
'main handler done',
]
=== TEST 7: accessing cosocket in callback
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
ngx.exit(499)
end
local bytes, err = sock:send("flushall\\r\\n")
if not bytes then
ngx.log(ngx.ERR, "failed to send query: ", err)
ngx.exit(499)
end
local res, err = sock:receive()
if not res then
ngx.log(ngx.ERR, "failed to receive: ", err)
ngx.exit(499)
end
ngx.log(ngx.NOTICE, "callback done: ", res)
ngx.exit(499)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- wait: 0.5
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
callback done: +OK
=== TEST 8: ignore the client abort event in the user callback (no check)
--- config
location /t {
lua_check_client_abort off;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("cannot set on_abort: ", err)
return
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
lua req cleanup
--- timeout: 0.2
--- abort
--- response_body
cannot set on_abort: lua_check_client_abort is off
--- no_error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 9: register on_abort callback but no client abortion
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.say("done")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
terminate 1: ok
delete thread 1
lua req cleanup
delete thread 2
--- response_body
done
--- no_error_log
[error]
client prematurely closed connection
on abort called
main handler done
=== TEST 10: ignore the client abort event in the user callback (uthread)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
lua check broken conn
terminate 2: ok
delete thread 2
terminate 3: ok
delete thread 3
terminate 4: ok
delete thread 4
lua req cleanup
--- timeout: 0.2
--- abort
--- wait: 0.7
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 11: abort in the user callback (uthread)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(444)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 3
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
=== TEST 12: register on_abort callback but no client abortion (uthread)
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.1)
ngx.say("done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
delete thread 2
--- wait: 0.5
--- response_body
done
--- no_error_log
[error]
client prematurely closed connection
on abort called
main handler done
=== TEST 13: register on_abort callback multiple times
--- config
location /t {
lua_check_client_abort on;
rewrite_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("1: cannot set on_abort: " .. err)
return
end
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("2: cannot set on_abort: " .. err)
return
end
ngx.thread.spawn(function ()
ngx.sleep(0.1)
ngx.say("done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
terminate 1: ok
delete thread 1
lua req cleanup
delete thread 2
--- response_body
2: cannot set on_abort: duplicate call
--- no_error_log
[error]

View file

@ -1,173 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => blocks() * repeat_each() * 3;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: default 302
--- config
location /read {
rewrite_by_lua '
ngx.redirect("http://www.taobao.com/foo");
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 2: explicit 302
--- config
location /read {
rewrite_by_lua '
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_TEMPORARILY);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 3: explicit 301
--- config
location /read {
rewrite_by_lua '
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_PERMANENTLY);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 301 Moved Permanently
--- error_code: 301
=== TEST 4: bad rc
--- config
location /read {
rewrite_by_lua '
ngx.redirect("http://www.taobao.com/foo", 404);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 5: no args
--- config
location /read {
rewrite_by_lua '
ngx.redirect()
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: relative uri
--- config
location /read {
rewrite_by_lua '
ngx.redirect("/foo")
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- raw_response_headers_like eval
my $headers;
if (defined($ENV{TEST_NGINX_USE_HTTP3}) || defined($ENV{TEST_NGINX_USE_HTTP2})) {
$headers = "location: /foo\r\n"
} else {
$headers = "Location: /foo\r\n"
}
$headers;
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 7: internal redirects that do not clear module ctx
--- http_config
rewrite_by_lua_no_postpone on;
--- config
rewrite_by_lua_block {
-- this is empty by intention
}
location /url1 {
rewrite ^ /url2;
}
--- request
GET /url1
--- response_body_like: 404 Not Found
--- error_log eval
qr{\[error\] .*?/html/url2".*?No such file or directory}
--- error_code: 404
=== TEST 8: internal redirects that do not clear module ctx (yield in rewrite handler)
--- http_config
rewrite_by_lua_no_postpone on;
--- config
rewrite_by_lua_block {
ngx.sleep(0.001)
}
location /url1 {
rewrite ^ /url2;
}
--- request
GET /url1
--- response_body_like: 404 Not Found
--- error_log eval
qr{\[error\] .*?/html/url2".*?No such file or directory}
--- error_code: 404

View file

@ -1,224 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4 + 5);
#no_diff();
#no_long_string();
#master_on();
#workers(2);
run_tests();
__DATA__
=== TEST 1: read buffered body
--- config
location = /test {
rewrite_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
=== TEST 2: read buffered body (timed out)
--- config
client_body_timeout 1ms;
location = /test {
rewrite_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
';
content_by_lua return;
}
--- raw_request eval
"POST /test HTTP/1.1\r
Host: localhost\r
Content-Length: 100\r
Connection: close\r
\r
hello, world"
--- response_body:
--- error_code_like: ^(?:500)?$
=== TEST 3: read buffered body and then subrequest
--- config
location /foo {
echo -n foo;
}
location = /test {
rewrite_by_lua '
ngx.req.read_body()
local res = ngx.location.capture("/foo");
ngx.say(ngx.var.request_body)
ngx.say("sub: ", res.body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
sub: foo
=== TEST 4: first subrequest and then read buffered body
--- config
location /foo {
echo -n foo;
}
location = /test {
rewrite_by_lua '
local res = ngx.location.capture("/foo");
ngx.req.read_body()
ngx.say(ngx.var.request_body)
ngx.say("sub: ", res.body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
sub: foo
--- no_error_log
[error]
[alert]
=== TEST 5: failed to write 100 continue
--- config
location = /test {
rewrite_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
ngx.exit(200)
';
}
--- request
POST /test
hello, world
--- more_headers
Expect: 100-Continue
--- ignore_response
--- no_error_log
[alert]
[error]
http finalize request: 500, "/test?" a:1, c:0
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 6: not discard body (exit 200)
--- config
location = /foo {
rewrite_by_lua '
-- ngx.req.discard_body()
ngx.say("body: ", ngx.var.request_body)
ngx.exit(200)
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
["body: nil\n",
"body: hiya, world\n",
]
--- error_code eval
[200, 200]
--- no_error_log
[error]
[alert]
=== TEST 7: not discard body (exit 201)
--- config
location = /foo {
rewrite_by_lua '
-- ngx.req.discard_body()
ngx.say("body: ", ngx.var.request_body)
ngx.exit(201)
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
["body: nil\n",
"body: hiya, world\n",
]
--- error_code eval
[200, 200]
--- no_error_log
[error]
[alert]
=== TEST 8: not discard body (exit 302)
--- config
location = /foo {
rewrite_by_lua '
-- ngx.req.discard_body()
-- ngx.say("body: ", ngx.var.request_body)
ngx.redirect("/blah")
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
[qr/302 Found/,
"body: hiya, world\n",
]
--- error_code eval
[302, 200]
--- no_error_log
[error]
[alert]

File diff suppressed because one or more lines are too long

View file

@ -1,172 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('debug'); # to ensure any log-level can be outputted
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: test reading request body
--- config
location /echo_body {
lua_need_request_body on;
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 2: test not reading request body
--- config
location /echo_body {
lua_need_request_body off;
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 3: test default setting (not reading request body)
--- config
location /echo_body {
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 4: test main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 5: test server conf
--- config
lua_need_request_body on;
location /echo_body {
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 6: test override main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
lua_need_request_body off;
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 7: test override server conf
--- config
lua_need_request_body on;
location /echo_body {
lua_need_request_body off;
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 8: Expect: 100-Continue
--- config
location /echo_body {
lua_need_request_body on;
rewrite_by_lua '
ngx.print(ngx.var.request_body or "nil")
ngx.exit(200)
';
}
--- request
POST /echo_body
hello world
--- more_headers
Expect: 100-Continue
--- ignore_response
--- no_error_log
[error]
[alert]
http finalize request: 500, "/echo_body?" a:1, c:2
http finalize request: 500, "/echo_body?" a:1, c:0
--- log_level: debug

View file

@ -1,801 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#no_nginx_manager();
#log_level('warn');
#master_on();
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 12);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: basic print
--- config
location /lua {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
rewrite_by_lua 'ngx.print("Hello, Lua!\\n")';
content_by_lua return;
#content_by_lua 'ngx.say("Hi")';
}
--- request
GET /lua
--- response_body
Hello, Lua!
=== TEST 2: basic say
--- config
location /say {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
rewrite_by_lua '
ngx.say("Hello, Lua!")
ngx.say("Yay! ", 123)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /say
--- response_body
Hello, Lua!
Yay! 123
=== TEST 3: no ngx.echo
--- config
location /lua {
rewrite_by_lua 'ngx.echo("Hello, Lua!\\n")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: variable
--- config
location /lua {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
rewrite_by_lua 'local v = ngx.var["request_uri"] ngx.print("request_uri: ", v, "\\n")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua?a=1&b=2
--- response_body
request_uri: /lua?a=1&b=2
=== TEST 5: variable (file)
--- config
location /lua {
rewrite_by_lua_file html/test.lua;
content_by_lua 'ngx.exit(ngx.OK)';
}
--- user_files
>>> test.lua
local v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- response_body
request_uri: /lua?a=1&b=2
=== TEST 6: calc expression
--- config
location /lua {
rewrite_by_lua_file html/calc.lua;
content_by_lua 'ngx.exit(ngx.OK)';
}
--- user_files
>>> calc.lua
local function uri_unescape(uri)
local function convert(hex)
return string.char(tonumber("0x"..hex))
end
local s = string.gsub(uri, "%%([0-9a-fA-F][0-9a-fA-F])", convert)
return s
end
local function eval_exp(str)
return loadstring("return "..str)()
end
local exp_str = ngx.var["arg_exp"]
-- print("exp: '", exp_str, "'\n")
local status, res
status, res = pcall(uri_unescape, exp_str)
if not status then
ngx.print("error: ", res, "\n")
return
end
status, res = pcall(eval_exp, res)
if status then
ngx.print("result: ", res, "\n")
else
ngx.print("error: ", res, "\n")
end
--- request
GET /lua?exp=1%2B2*math.sin(3)%2Fmath.exp(4)-math.sqrt(2)
--- response_body
result: -0.4090441561579
=== TEST 7: read $arg_xxx
--- config
location = /lua {
rewrite_by_lua 'local who = ngx.var.arg_who
ngx.print("Hello, ", who, "!")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua?who=agentzh
--- response_body chomp
Hello, agentzh!
=== TEST 8: capture location
--- config
location /other {
echo "hello, world";
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other")
ngx.print("status=", res.status, " ")
ngx.print("body=", res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
status=200 body=hello, world
=== TEST 9: capture non-existed location
--- config
location /lua {
rewrite_by_lua 'local res = ngx.location.capture("/other"); ngx.print("status=", res.status)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body: status=404
=== TEST 10: invalid capture location (not as expected...)
--- config
location /lua {
rewrite_by_lua 'local res = ngx.location.capture("*(#*"); ngx.say("res=", res.status)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
res=404
=== TEST 11: nil is "nil"
--- config
location /lua {
rewrite_by_lua 'ngx.say(nil)';
content_by_lua return;
}
--- request
GET /lua
--- response_body
nil
=== TEST 12: write boolean
--- config
location /lua {
rewrite_by_lua 'ngx.say(true, " ", false)';
content_by_lua return;
}
--- request
GET /lua
--- response_body
true false
=== TEST 13: bad argument type to ngx.location.capture
--- config
location /lua {
rewrite_by_lua 'ngx.location.capture(nil)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 14: capture location (default 0);
--- config
location /recur {
rewrite_by_lua '
local num = tonumber(ngx.var.arg_num) or 0;
ngx.print("num is: ", num, "\\n");
if (num > 0) then
res = ngx.location.capture("/recur?num="..tostring(num - 1));
ngx.print("status=", res.status, " ");
ngx.print("body=", res.body, "\\n");
else
ngx.print("end\\n");
end
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /recur
--- response_body
num is: 0
end
=== TEST 15: capture location
--- config
location /recur {
rewrite_by_lua '
local num = tonumber(ngx.var.arg_num) or 0;
ngx.print("num is: ", num, "\\n");
if (num > 0) then
local res = ngx.location.capture("/recur?num="..tostring(num - 1));
ngx.print("status=", res.status, " ");
ngx.print("body=", res.body);
else
ngx.print("end\\n");
end
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /recur?num=3
--- response_body
num is: 3
status=200 body=num is: 2
status=200 body=num is: 1
status=200 body=num is: 0
end
=== TEST 16: setting nginx variables from within Lua
--- config
location /set {
set $a "";
rewrite_by_lua 'ngx.var.a = 32; ngx.say(ngx.var.a)';
content_by_lua 'ngx.exit(ngx.OK)';
add_header Foo $a;
}
--- request
GET /set
--- response_headers
Foo: 32
--- response_body
32
=== TEST 17: nginx quote sql string 1
--- config
location /set {
set $a 'hello\n\r\'"\\'; # this runs after rewrite_by_lua
rewrite_by_lua 'ngx.say(ngx.quote_sql_str(ngx.var.a))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
'hello\n\r\'\"\\'
=== TEST 18: nginx quote sql string 2
--- config
location /set {
#set $a "hello\n\r'\"\\";
rewrite_by_lua 'ngx.say(ngx.quote_sql_str("hello\\n\\r\'\\"\\\\"))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
'hello\n\r\'\"\\'
=== TEST 19: use dollar
--- config
location /set {
rewrite_by_lua '
local s = "hello 112";
ngx.say(string.find(s, "%d+$"))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
79
=== TEST 20: subrequests do not share variables of main requests by default
--- config
location /sub {
echo $a;
}
location /parent {
set $a 12;
rewrite_by_lua 'local res = ngx.location.capture("/sub"); ngx.print(res.body)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body eval: "\n"
=== TEST 21: subrequests can share variables of main requests
--- config
location /sub {
echo $a;
}
location /parent {
set $a '';
rewrite_by_lua '
ngx.var.a = 12;
local res = ngx.location.capture(
"/sub",
{ share_all_vars = true }
);
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body
12
=== TEST 22: main requests use subrequests' variables
--- config
location /sub {
set $a 12;
}
location /parent {
rewrite_by_lua '
local res = ngx.location.capture("/sub", { share_all_vars = true });
ngx.say(ngx.var.a)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body
12
=== TEST 23: main requests do NOT use subrequests' variables
--- config
location /sub {
set $a 12;
content_by_lua return;
}
location /parent {
rewrite_by_lua '
local res = ngx.location.capture("/sub", { share_all_vars = false });
ngx.say(ngx.var.a)
';
content_by_lua return;
}
--- request
GET /parent
--- response_body_like eval: "\n"
=== TEST 24: capture location headers
--- config
location /other {
default_type 'foo/bar';
echo "hello, world";
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
=== TEST 25: capture location headers
--- config
location /other {
default_type 'foo/bar';
rewrite_by_lua '
ngx.header.Bar = "Bah";
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
ngx.say("Bar: ", res.header["Bar"]);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
Bar: Bah
=== TEST 26: capture location headers
--- config
location /other {
default_type 'foo/bar';
rewrite_by_lua '
ngx.header.Bar = "Bah";
ngx.header.Bar = nil;
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
ngx.say("Bar: ", res.header["Bar"] or "nil");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
Bar: nil
=== TEST 27: rewrite_by_lua runs before ngx_access
--- config
location /lua {
deny all;
rewrite_by_lua '
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
';
content_by_lua return;
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 28: rewrite_by_lua shouldn't send headers automatically (on simple return)
--- config
location /lua {
rewrite_by_lua 'return';
proxy_pass http://127.0.0.1:$server_port/foo;
}
location = /foo {
default_type 'text/css';
add_header Bar Baz;
echo foo;
}
--- request
GET /lua
--- response_headers
Bar: Baz
Content-Type: text/css
--- response_body
foo
=== TEST 29: rewrite_by_lua shouldn't send headers automatically (on simple exit)
--- config
location /lua {
rewrite_by_lua 'ngx.exit(ngx.OK)';
proxy_pass http://127.0.0.1:$server_port/foo;
}
location = /foo {
default_type 'text/css';
add_header Bar Baz;
echo foo;
}
--- request
GET /lua
--- response_headers
Bar: Baz
Content-Type: text/css
--- response_body
foo
=== TEST 30: short circuit
--- config
location /lua {
rewrite_by_lua '
ngx.say("Hi")
ngx.eof()
ngx.exit(ngx.HTTP_OK)
';
content_by_lua '
print("HERE")
ngx.print("BAD")
';
}
--- request
GET /lua
--- response_body
Hi
=== TEST 31: nginx vars in script path
--- config
location ~ /lua/(.+)$ {
rewrite_by_lua_file html/$1.lua;
content_by_lua '
print("HERE")
ngx.print("BAD")
';
}
--- user_files
>>> hi.lua
ngx.say("Hi")
ngx.eof()
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua/hi
--- response_body
Hi
=== TEST 32: phase postponing works for various locations
--- config
location ~ '^/lua/(.+)' {
set $path $1;
rewrite_by_lua 'ngx.say(ngx.var.path)';
content_by_lua return;
}
location ~ '^/lua2/(.+)' {
set $path $1;
rewrite_by_lua 'ngx.say(ngx.var.path)';
content_by_lua return;
}
location /main {
echo_location /lua/foo;
echo_location /lua/bar;
echo_location /lua2/baz;
echo_location /lua2/bah;
}
--- request
GET /main
--- response_body
foo
bar
baz
bah
=== TEST 33: server rewrite_by_lua
--- config
rewrite_by_lua 'ngx.header["X-Foo"] = "bar" -- ngx.send_headers()';
--- request
GET /
--- response_body chop
<html><head><title>It works!</title></head><body>It works!</body></html>
--- response_headers
X-Foo: bar
--- no_error_log
[error]
=== TEST 34: server rewrite_by_lua_file
--- config
rewrite_by_lua_file html/foo.lua;
--- user_files
>>> foo.lua
ngx.header["X-Foo"] = "bar" -- ngx.send_headers()
--- request
GET /
--- response_body chop
<html><head><title>It works!</title></head><body>It works!</body></html>
--- response_headers
X-Foo: bar
=== TEST 35: rewrite last before rewrite_by_lua
--- config
location /main {
rewrite ^/main/xyz\.html$ /abc.html last;
rewrite_by_lua 'ngx.exit(503)';
}
location ~ /abc.html {
echo abc;
}
--- request
GET /main/xyz.html
--- response_body
abc
=== TEST 36: rewrite last before rewrite_by_lua_file
--- config
location /main {
rewrite ^/main/xyz\.html$ /abc.html last;
rewrite_by_lua_file html/exit.lua;
}
location ~ /abc.html {
echo abc;
}
--- user_files
>>> exit.lua
ngx.exit(503)
--- request
GET /main/xyz.html
--- response_body
abc
=== TEST 37: rewrite before rewrite_by_lua
--- config
location /main {
rewrite ^/main/xyz\.html$ /abc.html;
rewrite_by_lua 'ngx.exit(503)';
}
location ~ /abc.html {
echo abc;
}
--- request
GET /main/xyz.html
--- response_body
abc
=== TEST 38: rewrite break before rewrite_by_lua
--- config
location /main {
rewrite ^/main/xyz\.html$ /abc.html break;
rewrite_by_lua 'ngx.exit(503)';
}
location ~ /abc.html {
echo abc;
}
--- request
GET /main/xyz.html
--- response_body_like: 503 Service Temporarily Unavailable
--- error_code: 503
=== TEST 39: Lua file does not exist
--- config
location /lua {
rewrite_by_lua_file html/test2.lua;
}
--- user_files
>>> test.lua
v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- response_body_like: 404 Not Found
--- error_code: 404
--- error_log eval
qr/failed to load external Lua file ".*?\btest2\.lua": cannot open .*? No such file or directory/
=== TEST 40: use of ngx.say() in rewrite_by_lua without exiting with 200+.
--- config
location /t {
rewrite_by_lua "ngx.say('test')";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]
=== TEST 41: use of ngx.say() in rewrite_by_lua without exiting with 200+. (with explicit ngx.eof())
--- config
location /t {
rewrite_by_lua "ngx.say('test') ngx.eof()";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]
=== TEST 42: use of ngx.say() in rewrite_by_lua without exiting with 200+. (with IO)
--- config
location /t {
rewrite_by_lua "ngx.say('test') ngx.sleep(0.001)";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]

View file

@ -1,224 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
log_level('debug');
repeat_each(2);
plan tests => repeat_each() * 33;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sleep 0.5
--- config
location /test {
rewrite_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.sleep(0.5)
local now = ngx.now()
ngx.say(now - before)
ngx.exit(200)
';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:4[5-9]\d*|5[0-9]\d*|5)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
=== TEST 2: sleep ag
--- config
location /test {
rewrite_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.sleep("a")
local now = ngx.now()
ngx.say(now - before)
ngx.exit(200)
';
}
--- request
GET /test
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log
bad argument #1 to 'sleep'
=== TEST 3: sleep 0.5 in subrequest
--- config
location /test {
rewrite_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.location.capture("/sleep")
local now = ngx.now()
local delay = now - before
ngx.say(delay)
ngx.exit(200)
';
}
location /sleep {
rewrite_by_lua 'ngx.sleep(0.5) ngx.exit(200)';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:4[5-9]\d*|5[0-9]\d*|5)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/sleep?"
--- no_error_log
[error]
=== TEST 4: sleep a in subrequest with bad argument
--- config
location /test {
rewrite_by_lua '
local res = ngx.location.capture("/sleep");
ngx.say(res.status)
ngx.exit(200)
';
}
location /sleep {
rewrite_by_lua 'ngx.sleep("a") ngx.exit(200)';
}
--- request
GET /test
--- response_body
500
--- error_log
bad argument #1 to 'sleep'
=== TEST 5: sleep 0.5 - multi-times
--- quic_max_idle_timeout: 1.0
--- config
location /test {
rewrite_by_lua '
ngx.update_time()
local start = ngx.now()
ngx.sleep(0.3)
ngx.sleep(0.3)
ngx.sleep(0.3)
ngx.say(ngx.now() - start)
ngx.exit(200)
';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:8[5-9]\d*|9[0-9]\d*|9)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 6: sleep 0.5 - interleaved by ngx.say() - ended by ngx.sleep
--- quic_max_idle_timeout: 2.05
--- config
location /test {
rewrite_by_lua '
ngx.send_headers()
-- ngx.location.capture("/sleep")
ngx.sleep(1)
ngx.say("blah")
ngx.sleep(1)
-- ngx.location.capture("/sleep")
ngx.exit(200)
';
}
location = /sleep {
echo_sleep 0.1;
}
--- request
GET /test
--- response_body
blah
--- error_log
lua ready to sleep
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 7: sleep 0.5 - interleaved by ngx.say() - not ended by ngx.sleep
--- quic_max_idle_timeout: 0.85
--- config
location /test {
rewrite_by_lua '
ngx.send_headers()
-- ngx.location.capture("/sleep")
ngx.sleep(0.3)
ngx.say("blah")
ngx.sleep(0.5)
-- ngx.location.capture("/sleep")
ngx.say("hiya")
ngx.exit(200)
';
}
location = /sleep {
echo_sleep 0.1;
}
--- request
GET /test
--- response_body
blah
hiya
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 8: ngx.location.capture before and after ngx.sleep
--- config
location /test {
rewrite_by_lua '
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.sleep(0.1)
res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.exit(200)
';
}
location = /hello {
echo hello world;
}
location = /sub {
proxy_pass http://127.0.0.1:$server_port/hello;
}
--- request
GET /test
--- response_body
hello world
hello world
--- no_error_log
[error]

File diff suppressed because it is too large Load diff

View file

@ -1,641 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: DELETE
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_DELETE });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
DELETE
=== TEST 2: DELETE (proxy method)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_DELETE });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
DELETE
=== TEST 3: POST (nobody, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_POST });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
POST
=== TEST 4: HEAD
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_HEAD });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
=== TEST 5: explicit GET
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_GET });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 6: implicit GET
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo")
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 7: implicit GET (empty option table)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo", {})
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 8: PUT (nobody, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo_read_request_body;
echo $echo_request_method;
echo_request_body;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
PUT
hello
=== TEST 9: PUT (nobody, no proxy method)
--- config
location /other {
default_type 'foo/bar';
#echo_read_request_body;
echo $echo_request_method;
#echo $echo_request_body;
echo_request_body;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
PUT
hello
=== TEST 10: PUT (nobody, no proxy method)
--- config
location /other {
default_type 'foo/bar';
#echo_read_request_body;
echo $echo_request_method;
#echo $echo_request_body;
echo_request_body;
#echo "[$http_content_length]";
echo;
}
location /foo {
echo $echo_request_method;
echo -n "[$http_content_length]";
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
res = ngx.location.capture("/foo")
ngx.say(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
PUT
hello
GET
[]
=== TEST 11: POST (with body, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo_read_request_body;
echo $echo_request_method;
echo_request_body;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_POST, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
POST
hello
=== TEST 12: POST (with body, memc method)
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
rewrite_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
ngx.say("GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.say("PUT: " .. res.status);
res = ngx.location.capture("/memc");
ngx.say("cached: " .. res.body);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET: 404
PUT: 201
cached: hello
=== TEST 13: POST (with body, memc method)
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_cmd "";
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
rewrite_by_lua '
ngx.location.capture("/flush",
{ share_all_vars = true });
local res = ngx.location.capture("/memc",
{ share_all_vars = true });
ngx.say("GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello", share_all_vars = true });
ngx.say("PUT: " .. res.status);
res = ngx.location.capture("/memc", { share_all_vars = true });
ngx.say("cached: " .. res.body);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET: 404
PUT: 201
cached: hello
=== TEST 14: empty args option table
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = {} })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body eval: "\n"
=== TEST 15: non-empty args option table (1 pair)
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = { ["fo="] = "=>" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
fo%3D=%3D%3E
=== TEST 16: non-empty args option table (2 pairs)
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = { ["fo="] = "=>",
["="] = ":" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like chop
^(?:fo%3D=%3D%3E\&%3D=%3A|%3D=%3A\&fo%3D=%3D%3E)$
=== TEST 17: non-empty args option table (2 pairs, no special chars)
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = { foo = 3,
bar = "hello" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like chop
^(?:bar=hello\&foo=3|foo=3\&bar=hello)$
=== TEST 18: non-empty args option table (number key)
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = { [57] = "hi" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 19: non-empty args option table (plain arrays)
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo",
{ args = { "hi" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 20: more args
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo?a=3",
{ args = { b = 4 } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
a=3&b=4
=== TEST 21: more args
--- config
location /foo {
echo $query_string;
}
location /lua {
rewrite_by_lua '
local res = ngx.location.capture("/foo?a=3",
{ args = "b=4" })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
a=3&b=4
=== TEST 22: more args
--- config
location /memc {
set $memc_cmd get;
set $memc_key $arg_key;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc_set {
#set $memc_cmd set;
#set $memc_key $arg_key;
#memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
echo OK;
}
location /lua {
rewrite_by_lua '
print("HELLO")
local memc_key = "hello"
local res = ngx.location.capture("/memc?key=" .. memc_key )
ngx.say("copass: res " .. res.status)
if res.status == 404 then
ngx.say("copas: capture /memc_set")
res = ngx.location.capture("/memc_set?key=" .. memc_key)
ngx.say("copss: status " .. res.status);
end
';
content_by_lua 'return';
#echo Hi;
}
--- request
GET /lua
--- response_body
copass: res 404
copas: capture /memc_set
copss: status 200
=== TEST 23: I/O in named location
the nginx core requires the patch https://github.com/agentzh/ngx_openresty/blob/master/patches/nginx-1.0.15-reset_wev_handler_in_named_locations.patch
--- config
location /t {
echo_exec @named;
}
location @named {
rewrite_by_lua '
ngx.location.capture("/hello")
';
echo done;
}
location /hello {
echo hello;
}
--- request
GET /t
--- response_body
done

View file

@ -1,607 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
BEGIN {
if (!defined $ENV{LD_PRELOAD}) {
$ENV{LD_PRELOAD} = '';
}
if ($ENV{LD_PRELOAD} !~ /\bmockeagain\.so\b/) {
$ENV{LD_PRELOAD} = "mockeagain.so $ENV{LD_PRELOAD}";
}
if ($ENV{MOCKEAGAIN} eq 'r') {
$ENV{MOCKEAGAIN} = 'rw';
} else {
$ENV{MOCKEAGAIN} = 'w';
}
delete($ENV{TEST_NGINX_USE_HTTP2});
$ENV{TEST_NGINX_EVENT_TYPE} = 'poll';
$ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'get helloworld';
}
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4 + 8);
our $HtmlDir = html_dir;
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
no_long_string();
no_diff();
run_tests();
__DATA__
=== TEST 1: lua_socket_connect_timeout only
--- config
server_tokens off;
lua_socket_connect_timeout 100ms;
resolver $TEST_NGINX_RESOLVER ipv6=off;
resolver_timeout 3s;
location /t1 {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.2", 12345)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /t1
--- response_body
failed to connect: timeout
--- error_log
lua tcp socket connect timeout: 100
lua tcp socket connect timed out, when connecting to 127.0.0.2:12345
--- timeout: 10
=== TEST 2: sock:settimeout() overrides lua_socket_connect_timeout
--- config
server_tokens off;
lua_socket_connect_timeout 60s;
lua_socket_log_errors off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
resolver_timeout 3s;
location /t2 {
rewrite_by_lua '
local sock = ngx.socket.tcp()
sock:settimeout(150)
local ok, err = sock:connect("127.0.0.2", 12345)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /t2
--- response_body
failed to connect: timeout
--- error_log
lua tcp socket connect timeout: 150
--- no_error_log
[error]
[alert]
--- timeout: 10
=== TEST 3: sock:settimeout(nil) does not override lua_socket_connect_timeout
--- config
server_tokens off;
lua_socket_log_errors off;
lua_socket_connect_timeout 102ms;
resolver $TEST_NGINX_RESOLVER ipv6=off;
#resolver_timeout 3s;
location /t3 {
rewrite_by_lua '
local sock = ngx.socket.tcp()
sock:settimeout(nil)
local ok, err = sock:connect("127.0.0.2", 12345)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /t3
--- response_body
failed to connect: timeout
--- error_log
lua tcp socket connect timeout: 102
--- no_error_log
[error]
[alert]
--- timeout: 5
=== TEST 4: sock:settimeout(0) does not override lua_socket_connect_timeout
--- config
server_tokens off;
lua_socket_connect_timeout 102ms;
lua_socket_log_errors off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
resolver_timeout 3s;
location /t4 {
rewrite_by_lua '
local sock = ngx.socket.tcp()
sock:settimeout(0)
local ok, err = sock:connect("127.0.0.2", 12345)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /t4
--- response_body
failed to connect: timeout
--- error_log
lua tcp socket connect timeout: 102
--- timeout: 5
--- no_error_log
[error]
[alert]
--- timeout: 10
=== TEST 5: -1 is bad timeout value
--- config
server_tokens off;
lua_socket_connect_timeout 102ms;
lua_socket_log_errors off;
resolver $TEST_NGINX_RESOLVER ipv6=off;
resolver_timeout 3s;
location /t5 {
rewrite_by_lua '
local sock = ngx.socket.tcp()
sock:settimeout(-1)
local ok, err = sock:connect("127.0.0.2", 12345)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /t5
--- response_body_like chomp
500 Internal Server Error
--- error_log
bad timeout value
--- timeout: 10
--- error_code: 500
=== TEST 6: lua_socket_read_timeout only
--- config
server_tokens off;
lua_socket_read_timeout 100ms;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local line
line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to receive: timeout
--- error_log
lua tcp socket read timeout: 100
lua tcp socket connect timeout: 60000
lua tcp socket read timed out
=== TEST 7: sock:settimeout() overrides lua_socket_read_timeout
--- config
server_tokens off;
lua_socket_read_timeout 60s;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(150)
local line
line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to receive: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket read timeout: 150
lua tcp socket read timed out
=== TEST 8: sock:settimeout(nil) does not override lua_socket_read_timeout
--- config
server_tokens off;
lua_socket_read_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(nil)
local line
line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to receive: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket read timeout: 102
lua tcp socket read timed out
=== TEST 9: sock:settimeout(0) does not override lua_socket_read_timeout
--- config
server_tokens off;
lua_socket_read_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(0)
local line
line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to receive: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket read timeout: 102
lua tcp socket read timed out
=== TEST 10: -1 is bad timeout value
--- config
server_tokens off;
lua_socket_read_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
sock:settimeout(-1)
local line
line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body_like chomp
500 Internal Server Error
--- error_log
bad timeout value
--- timeout: 10
--- error_code: 500
=== TEST 11: lua_socket_send_timeout only
--- config
server_tokens off;
lua_socket_send_timeout 100ms;
resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local bytes
bytes, err = sock:send("get helloworld!")
if bytes then
ngx.say("sent: ", bytes)
else
ngx.say("failed to send: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to send: timeout
--- error_log
lua tcp socket send timeout: 100
lua tcp socket connect timeout: 60000
lua tcp socket write timed out
=== TEST 12: sock:settimeout() overrides lua_socket_send_timeout
--- config
server_tokens off;
lua_socket_send_timeout 60s;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(150)
local bytes
bytes, err = sock:send("get helloworld!")
if bytes then
ngx.say("sent: ", bytes)
else
ngx.say("failed to send: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to send: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket send timeout: 150
lua tcp socket write timed out
=== TEST 13: sock:settimeout(nil) does not override lua_socket_send_timeout
--- config
server_tokens off;
lua_socket_send_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(nil)
local bytes
bytes, err = sock:send("get helloworld!")
if bytes then
ngx.say("sent: ", bytes)
else
ngx.say("failed to send: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to send: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket send timeout: 102
lua tcp socket write timed out
=== TEST 14: sock:settimeout(0) does not override lua_socket_send_timeout
--- config
server_tokens off;
lua_socket_send_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
sock:settimeout(0)
local bytes
bytes, err = sock:send("get helloworld!")
if bytes then
ngx.say("sent: ", bytes)
else
ngx.say("failed to send: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body
connected: 1
failed to send: timeout
--- error_log
lua tcp socket connect timeout: 60000
lua tcp socket send timeout: 102
lua tcp socket write timed out
=== TEST 15: -1 is bad timeout value
--- config
server_tokens off;
lua_socket_send_timeout 102ms;
#resolver $TEST_NGINX_RESOLVER ipv6=off;
location /t {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
sock:settimeout(-1)
local bytes
bytes, err = sock:send("get helloworld!")
if bytes then
ngx.say("sent: ", bytes)
else
ngx.say("failed to send: ", err)
end
';
content_by_lua return;
}
--- request
GET /t
--- response_body_like chomp
500 Internal Server Error
--- error_log
bad timeout value
--- timeout: 10
--- error_code: 500

File diff suppressed because it is too large Load diff

View file

@ -1,152 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (2 * blocks() + 1);
$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();
no_long_string();
#no_shuffle();
run_tests();
__DATA__
=== TEST 1: connection refused (unix domain socket)
--- config
location /test {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/tmp/nosuchfile.sock")
ngx.say("connect: ", ok, " ", err)
local bytes
bytes, err = sock:send("hello")
ngx.say("send: ", bytes, " ", err)
local line
line, err = sock:receive()
ngx.say("receive: ", line, " ", err)
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
content_by_lua return;
}
--- request
GET /test
--- response_body
connect: nil no such file or directory
send: nil closed
receive: nil closed
close: nil closed
--- error_log eval
qr{\[crit\] .*? connect\(\) to unix:/tmp/nosuchfile\.sock failed}
=== TEST 2: invalid host argument
--- http_server
server {
listen /tmp/test-nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua 'ngx.say("foo")';
more_clear_headers Date;
}
}
--- config
location /test {
rewrite_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("/tmp/test-nginx.sock")
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
content_by_lua return;
}
--- request
GET /test
--- response_body
failed to connect: missing the port number
=== TEST 3: sanity
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua 'ngx.say("foo")';
more_clear_headers Date;
}
}
--- config
location /test {
rewrite_by_lua '
local sock = ngx.socket.tcp()
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 req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
print("calling receive")
local line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err)
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
content_by_lua return;
}
--- request
GET /test
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed
close: 1 nil

View file

@ -1,345 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = $t::StapThread::GCScript;
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4);
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: exec in user thread (entry still pending)
--- config
location /lua {
rewrite_by_lua '
local function f()
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.sleep(1)
ngx.say("hello")
';
content_by_lua return;
}
location /foo {
echo i am foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
spawn user thread 2 in 1
terminate 2: ok
delete thread 2
delete thread 1
--- response_body
i am foo
--- no_error_log
[error]
=== TEST 2: exec in user thread (entry already quits)
--- config
location /lua {
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
';
content_by_lua return;
}
location /foo {
echo i am foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
spawn user thread 2 in 1
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
--- response_body
i am foo
--- no_error_log
[error]
=== TEST 3: exec in user thread (entry thread is still pending on ngx.sleep)
--- config
location /lua {
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.sleep(1)
';
content_by_lua return;
}
location = /foo {
echo hello foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 1000
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 1
free request
--- response_body
hello foo
--- no_error_log
[error]
=== TEST 4: exec in a user thread (another user thread is still pending on ngx.sleep)
--- config
location /lua {
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
local function g()
ngx.sleep(1)
end
ngx.thread.spawn(f)
ngx.thread.spawn(g)
';
content_by_lua return;
}
location = /foo {
echo hello foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
create 3 in 1
spawn user thread 3 in 1
add timer 1000
terminate 1: ok
delete thread 1
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 3
free request
--- response_body
hello foo
--- no_error_log
[error]
=== TEST 5: exec in user thread (entry thread is still pending on ngx.location.capture), without pending output
--- config
location /lua {
client_body_timeout 12000ms;
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.location.capture("/sleep")
ngx.say("end")
';
}
location = /sleep {
echo_sleep 0.2;
}
location = /foo {
echo hello world;
}
--- request
POST /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 200 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 200
expire timer 100
terminate 2: fail
expire timer 200
terminate 1: ok
delete thread 2
delete thread 1
free request
--- wait: 0.1
--- response_body
end
--- error_log
attempt to abort with pending subrequests

File diff suppressed because it is too large Load diff

View file

@ -1,188 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = $t::StapThread::GCScript;
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4);
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: ngx.redirect() in user thread (entry thread is still pending on ngx.location.capture_multi), without pending output
--- config
location /lua {
client_body_timeout 12000ms;
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.redirect(301)
end
ngx.thread.spawn(f)
ngx.location.capture_multi{
{"/echo"},
{"/sleep"}
}
ngx.say("end")
';
}
location = /echo {
echo hello;
}
location = /sleep {
echo_sleep 0.2;
}
--- request
POST /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 200 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_post_subrequest) {
printf("post subreq %s\n", ngx_http_req_uri($r))
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
post subreq /echo
add timer 200
expire timer 100
terminate 2: fail
expire timer 200
post subreq /sleep
terminate 1: ok
delete thread 2
delete thread 1
free request
--- response_body
end
--- error_log
attempt to abort with pending subrequests
=== TEST 2: redirect in user thread (entry thread is still pending on ngx.sleep)
--- config
location /lua {
rewrite_by_lua '
local function f()
ngx.sleep(0.1)
ngx.redirect(301)
end
ngx.thread.spawn(f)
ngx.sleep(1)
ngx.say("end")
';
content_by_lua return;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 1000
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 1
free request
--- response_body_like: 302 Found
--- error_code: 302
--- no_error_log
[error]

File diff suppressed because it is too large Load diff

View file

@ -1,109 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
#no_nginx_manager();
#repeat_each(1);
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 1);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: basic test passing
--- config
location /lua {
lua_need_request_body on;
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua '
-- check the client IP addr is in our black list
if ngx.var.remote_addr == "132.5.72.3" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the request body contains bad words
if ngx.var.request_body and string.match(ngx.var.request_body, "fuck") then
return ngx.redirect("/terms_of_use.html")
end
-- tests passed
';
echo Logged in;
}
--- request
GET /lua
--- response_body
Logged in
=== TEST 2: bad words in request body
--- config
location /lua {
lua_need_request_body on;
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua '
-- check the client IP addr is in our black list
if ngx.var.remote_addr == "132.5.72.3" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the request body contains bad words
if ngx.var.request_body and string.match(ngx.var.request_body, "fuck") then
return ngx.redirect("/terms_of_use.html")
end
-- tests passed
';
echo Logged in;
}
--- request
POST /lua
He fucks himself!
--- response_body_like: 302 Found
--- response_headers_like
Location: /terms_of_use\.html
--- error_code: 302
=== TEST 3: client IP
--- config
location /lua {
lua_need_request_body on;
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua '
-- check the client IP addr is in our black list
if ngx.var.remote_addr == "127.0.0.1" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the request body contains bad words
if ngx.var.request_body and string.match(ngx.var.request_body, "fuck") then
return ngx.redirect("/terms_of_use.html")
end
-- tests passed
';
echo Logged in;
}
--- request
GET /lua
--- response_body_like: 403 Forbidden
--- error_code: 403

View file

@ -1,862 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
our $SkipReason;
BEGIN {
if ($ENV{TEST_NGINX_USE_HTTP3}) {
$SkipReason = "http3 does not support ngx.req.socket and lua_check_client_abort";
} elsif ($ENV{TEST_NGINX_USE_HTTP2}) {
$SkipReason = "http2 does not support ngx.req.socket and lua_check_client_abort";
}
}
use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : ();
use t::StapThread;
our $GCScript = <<_EOC_;
$t::StapThread::GCScript
F(ngx_http_lua_check_broken_connection) {
println("lua check broken conn")
}
F(ngx_http_lua_request_cleanup) {
println("lua req cleanup")
}
_EOC_
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 3 - 1);
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 0.1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 2: sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- wait: 0.1
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 3: sleep + ignore
--- config
location /t {
lua_check_client_abort off;
access_by_lua '
ngx.sleep(1)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
=== TEST 4: subrequest + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location /sub {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 5: subrequest + ignore
--- config
location /t {
lua_check_client_abort off;
access_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location /sub {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: fail
lua req cleanup
delete thread 1
--- wait: 1.1
--- timeout: 0.2
--- abort
--- ignore_response
--- error_log
bad things happen
=== TEST 6: subrequest + stop (proxy, ignore client abort)
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location = /sub {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.2:12345/;
}
location = /sleep {
lua_check_client_abort on;
access_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 7: subrequest + stop (proxy, check client abort)
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
ngx.location.capture("/sub")
error("bad things happen")
';
}
location = /sub {
proxy_ignore_client_abort off;
proxy_pass http://127.0.0.2:12345/;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 8: need body on + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
lua_need_request_body on;
access_by_lua '
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 9: ngx.req.read_body + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.req.read_body()
ngx.sleep(1)
';
log_by_lua '
ngx.log(ngx.NOTICE, "here in log by lua")
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
here in log by lua
=== TEST 10: ngx.req.socket + receive() + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
sock:receive()
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 11: ngx.req.socket + receive(N) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
sock:receive(5)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 0.1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 12: ngx.req.socket + receive(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
sock:receive(2)
ngx.sleep(1)
';
content_by_lua return;
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out_like
^(?:lua check broken conn
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup|lua check broken conn
lua req cleanup
delete thread 1)$
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
=== TEST 13: ngx.req.socket + m * receive(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
sock:receive(2)
sock:receive(2)
sock:receive(1)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 14: ngx.req.socket + receiveuntil + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
local it = sock:receiveuntil("\\n")
it()
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 15: ngx.req.socket + receiveuntil + it(n) + sleep + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
local it = sock:receiveuntil("\\n")
it(2)
it(3)
ngx.sleep(1)
';
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 16: cosocket + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.req.discard_body()
local sock, err = ngx.socket.tcp()
if not sock then
ngx.log(ngx.ERR, "failed to get socket: ", err)
return
end
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
if not ok then
ngx.log(ngx.ERR, "failed to connect: ", err)
return
end
local bytes, err = sock:send("blpop nonexist 2\\r\\n")
if not bytes then
ngx.log(ngx.ERR, "failed to send query: ", err)
return
end
-- ngx.log(ngx.ERR, "about to receive")
local res, err = sock:receive()
if not res then
ngx.log(ngx.ERR, "failed to receive query: ", err)
return
end
ngx.log(ngx.ERR, "res: ", res)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 17: ngx.req.socket + receive n < content-length + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
error("bad")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 100\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
failed to receive: client aborted
=== TEST 18: ngx.req.socket + receive n == content-length + stop
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
ngx.sleep(1)
error("bad")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 5\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
lua check broken conn
lua check broken conn
lua req cleanup
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
=== TEST 19: ngx.req.socket + receive n == content-length + ignore
--- config
location /t {
access_by_lua '
local sock = ngx.req.socket()
local res, err = sock:receive("*a")
if not res then
ngx.log(ngx.NOTICE, "failed to receive: ", err)
return
end
ngx.say("done")
';
content_by_lua return;
}
--- raw_request eval
"POST /t HTTP/1.0\r
Host: localhost\r
Connection: close\r
Content-Length: 5\r
\r
hello"
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- shutdown: 1
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 20: ngx.req.read_body + sleep + stop (log handler still gets called)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
ngx.req.read_body()
';
content_by_lua return;
}
--- request
POST /t
hello
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- shutdown: 1
--- wait: 0.1
--- ignore_response
--- no_error_log
[error]
=== TEST 21: exec to lua + ignore
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
ngx.exec("/t2")
';
}
location = /t2 {
lua_check_client_abort off;
content_by_lua '
ngx.sleep(1)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
terminate 2: ok
delete thread 2
lua req cleanup
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 22: exec to proxy + ignore
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
ngx.exec("/t2")
';
}
location = /t2 {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.1:$server_port/sleep;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]
=== TEST 23: exec (named location) to proxy + ignore
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
ngx.exec("@t2")
';
}
location @t2 {
proxy_ignore_client_abort on;
proxy_pass http://127.0.0.1:$server_port/sleep;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
lua req cleanup
delete thread 1
--- wait: 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
[alert]

View file

@ -1,393 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 6);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /read {
access_by_lua '
ngx.exec("/hi");
ngx.say("Hi");
';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body
Hello
=== TEST 2: empty uri arg
--- config
location /read {
access_by_lua '
ngx.exec("");
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 3: no arg
--- config
location /read {
access_by_lua '
ngx.exec();
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: too many args
--- config
location /read {
access_by_lua '
ngx.exec(1, 2, 3, 4);
ngx.say("Hi");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 5: null uri
--- config
location /read {
access_by_lua '
ngx.exec(nil)
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: user args
--- config
location /read {
access_by_lua '
ngx.exec("/hi", "Yichun Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello Yichun Zhang
=== TEST 7: args in uri
--- config
location /read {
access_by_lua '
ngx.exec("/hi?agentzh")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello agentzh
=== TEST 8: args in uri and user args
--- config
location /read {
access_by_lua '
ngx.exec("/hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello a=Yichun&b=Zhang
=== TEST 9: args in uri and user args
--- config
location /read {
access_by_lua '
ngx.exec("@hi?a=Yichun", "b=Zhang")
ngx.say("Hi")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location @hi {
echo Hello $query_string;
}
--- request
GET /read
--- response_body
Hello
=== TEST 10: exec after location capture
--- config
location /test {
access_by_lua_file 'html/test.lua';
echo world;
}
location /a {
echo "hello";
}
location /b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('/b')
--- request
GET /test
--- response_body
hello
=== TEST 11: exec after (named) location capture
--- config
location /test {
access_by_lua_file 'html/test.lua';
}
location /a {
echo "hello";
}
location @b {
echo "hello";
}
--- user_files
>>> test.lua
ngx.location.capture('/a')
ngx.exec('@b')
--- request
GET /test
--- response_body
hello
=== TEST 12: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
access_by_lua '
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
--- timeout: 3
=== TEST 13: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (named location)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location @p {
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /lua {
access_by_lua '
ngx.exec("@p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 14: github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location (post subrequest)
--- config
location = /hi {
echo hello;
}
location /sub {
proxy_pass http://127.0.0.1:$server_port/hi;
}
location /p{
#content_by_lua '
#local res = ngx.location.capture("/sub")
#ngx.print(res.body)
#';
echo_location /sub;
}
location /blah {
echo blah;
}
location /lua {
access_by_lua '
ngx.location.capture("/blah")
ngx.exec("/p")
';
}
--- request
GET /lua
--- response_body
hello
=== TEST 15: access_by_lua + ngx.exec + subrequest capture
--- config
location /main {
access_by_lua '
local res = ngx.location.capture("/test_loc");
ngx.print("hello, ", res.body)
';
content_by_lua return;
}
location /test_loc {
rewrite_by_lua '
ngx.exec("@proxy")
';
}
location @proxy {
#echo proxy;
proxy_pass http://127.0.0.1:$server_port/foo;
}
location /foo {
echo bah;
}
--- request
GET /main
--- response_body
hello, bah
=== TEST 16: github issue #905: unsafe uri
--- config
location /read {
access_by_lua_block {
ngx.exec("/hi/../");
}
}
location /hi {
echo "Hello";
}
--- request
GET /read
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
[
'unsafe URI "/hi/../" was detected',
qr/runtime error: access_by_lua\(nginx.conf:\d+\):2: unsafe uri/,
]
=== TEST 17: pipelined requests
--- config
location /t {
access_by_lua_block {
ngx.exec("@foo")
}
}
location @foo {
return 200;
}
--- pipelined_requests eval
["GET /t", "GET /t"]
--- error_code eval
[200, 200]
--- response_body eval
["", ""]
--- no_error_log
[error]

View file

@ -1,550 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#repeat_each(20000);
repeat_each(2);
#master_on();
#workers(1);
#log_level('debug');
#log_level('warn');
#worker_connections(1024);
plan tests => repeat_each() * (blocks() * 2 + 2);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
our $LuaCpath = $ENV{LUA_CPATH} ||
'/usr/local/openresty-debug/lualib/?.so;/usr/local/openresty/lualib/?.so;;';
no_long_string();
run_tests();
__DATA__
=== TEST 1: throw 403
--- config
location /lua {
access_by_lua "ngx.exit(403);ngx.say('hi')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 403
--- response_body_like: 403 Forbidden
=== TEST 2: throw 404
--- config
location /lua {
access_by_lua "ngx.exit(404);ngx.say('hi');";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 404
--- response_body_like: 404 Not Found
=== TEST 3: throw 404 after sending the header and partial body
--- config
location /lua {
access_by_lua "ngx.say('hi');ngx.exit(404);ngx.say(', you')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
hi
--- no_error_log
[alert]
--- error_log
attempt to set status 404 via ngx.exit after sending out the response status 200
=== TEST 4: working with ngx_auth_request (succeeded)
--- config
location /auth {
access_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
content_by_lua 'ngx.exit(ngx.OK)';
}
location /api {
set $user $arg_user;
auth_request /auth;
echo "Logged in";
}
--- request
GET /api?user=agentzh
--- error_code: 200
--- response_body
Logged in
=== TEST 5: working with ngx_auth_request (failed)
--- config
location /api {
set $user $arg_user;
access_by_lua "
if ngx.var.user == 'agentzh' then
ngx.eof();
else
ngx.exit(403)
end";
echo "Logged in";
}
--- request
GET /api?user=agentz
--- error_code: 403
--- response_body_like: 403 Forbidden
=== TEST 6: working with ngx_auth_request (simplest form, w/o ngx_memc)
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /api {
set $uid $arg_uid;
access_by_lua_file 'html/foo.lua';
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
-- ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- timeout: 3
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 7: working with ngx_auth_request (simplest form)
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /api {
set $uid $arg_uid;
access_by_lua_file html/foo.lua;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 8: working with ngx_auth_request
--- http_config eval
"
lua_package_cpath '$::LuaCpath';
upstream backend {
drizzle_server 127.0.0.1:\$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream memc_b {
server 127.0.0.1:\$TEST_NGINX_MEMCACHED_PORT;
}
upstream_list memc_cluster memc_a memc_b;
"
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass $backend;
}
location /conv-uid-mysql {
internal;
set $key "conv-uid-$arg_uid";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
drizzle_query "select new_uid as uid from conv_uid where old_uid=$arg_uid";
drizzle_pass backend;
rds_json on;
}
location /api {
set $uid $arg_uid;
access_by_lua_file html/foo.lua;
echo "Logged in $uid";
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local old_uid = ngx.var.uid
-- print('about to run sr')
local res = ngx.location.capture('/conv-uid-mysql?uid=' .. old_uid)
-- print('just have run sr' .. res.body)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].uid or
not string.match(res[1].uid, '^%d+$')) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.uid = res[1].uid;
-- print('done')
--- request
GET /api?uid=32
--- response_body
Logged in 56
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 9: working with ngx_auth_request
--- http_config
upstream backend {
drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
upstream memc_a {
server 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
keepalive 300;
}
#upstream_list memc_cluster memc_a memc_b;
--- config
location /memc {
internal;
set $memc_key $arg_key;
set $memc_exptime $arg_exptime;
#set_hashed_upstream $backend memc_cluster $arg_key;
memc_pass memc_a;
}
location /conv-mysql {
internal;
set $key "conv-uri-$query_string";
#srcache_fetch GET /memc key=$key;
#srcache_store PUT /memc key=$key;
default_type 'application/json';
set_quote_sql_str $seo_uri $query_string;
drizzle_query "select url from my_url_map where seo_url=$seo_uri";
drizzle_pass backend;
rds_json on;
}
location /conv-uid {
internal;
access_by_lua_file 'html/foo.lua';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /baz {
set $my_uri $uri;
auth_request /conv-uid;
echo_exec /jump $my_uri;
}
location /jump {
internal;
rewrite ^ $query_string? redirect;
}
--- user_files
>>> foo.lua
local cjson = require('cjson');
local seo_uri = ngx.var.my_uri
-- print('about to run sr')
local res = ngx.location.capture('/conv-mysql?' .. seo_uri)
if (res.status ~= ngx.HTTP_OK) then
ngx.exit(res.status)
end
res = cjson.decode(res.body)
if (not res or not res[1] or not res[1].url) then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.var.my_uri = res[1].url;
-- print('done')
--- request
GET /baz
--- response_body_like: 302
--- error_code: 302
--- response_headers
Location: http://localhost:$ServerPort/foo/bar
--- SKIP
=== TEST 10: throw 0
--- config
location /lua {
access_by_lua "ngx.say('Hi'); ngx.eof(); ngx.exit(0);ngx.say('world')";
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- error_code: 200
--- response_body
Hi
=== TEST 11: throw ngx.OK does *not* skip other later phase handlers
--- config
location /lua {
access_by_lua "ngx.exit(ngx.OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
hello
=== TEST 12: throw ngx.HTTP_OK *does* skip other later phase handlers (by inlined code)
--- config
location /lua {
access_by_lua "ngx.exit(ngx.HTTP_OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
=== TEST 13: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by inlined code + partial output)
--- config
location /lua {
rewrite_by_lua "ngx.say('hiya') ngx.exit(ngx.HTTP_OK)";
set $foo hello;
echo $foo;
}
--- request
GET /lua
--- response_body
hiya
=== TEST 14: throw ngx.HTTP_OK *does* skip other later phase handlers (by file)
--- config
location /lua {
access_by_lua_file html/foo.lua;
set $foo hello;
echo $foo;
}
--- user_files
>>> foo.lua
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua
--- response_body
=== TEST 15: throw ngx.HTTP_OK *does* skip other rewrite phase handlers (by file + partial output)
--- config
location /lua {
rewrite_by_lua_file html/foo.lua;
set $foo hello;
echo $foo;
}
--- user_files
>>> foo.lua
ngx.say("morning")
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua
--- response_body
morning
=== TEST 16: error page with custom body
--- config
error_page 410 @err;
location @err {
echo blah blah;
}
location /foo {
access_by_lua '
ngx.status = ngx.HTTP_GONE
ngx.say("This is our own content")
-- to cause quit the whole request rather than the current phase handler
ngx.exit(ngx.HTTP_OK)
';
echo Hello;
}
--- request
GET /foo
--- response_body
This is our own content
--- error_code: 410
=== TEST 17: exit(404) after I/O
--- config
error_page 400 /400.html;
error_page 404 /404.html;
location /foo {
access_by_lua '
ngx.location.capture("/sleep")
ngx.exit(ngx.HTTP_NOT_FOUND)
';
echo Hello;
}
location /sleep {
echo_sleep 0.002;
}
--- user_files
>>> 400.html
Bad request, dear...
>>> 404.html
Not found, dear...
--- request
GET /bah
--- response_body
Not found, dear...
--- error_code: 404

View file

@ -1,261 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2 + 4);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: access I/O with content I/O
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
access_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
print("access GET: ", res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
print("access PUT: ", res.status);
res = ngx.location.capture("/memc");
print("access cached: ", res.body);
';
content_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
ngx.say("content GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.say("content PUT: " .. res.status);
res = ngx.location.capture("/memc");
ngx.say("content cached: " .. res.body);
';
}
--- request
GET /lua
--- response_body
content GET: 404
content PUT: 201
content cached: hello
--- grep_error_log eval: qr/access .+?(?= while )/
--- grep_error_log_out
access GET: 404
access PUT: 201
access cached: hello
--- log_level: info
--- no_error_log
[error]
[alert]
=== TEST 2: share data via nginx variables
--- config
location /foo {
set $foo '';
access_by_lua '
ngx.var.foo = 32
';
content_by_lua '
ngx.say(tonumber(ngx.var.foo) * 2)
';
}
--- request
GET /foo
--- response_body
64
=== TEST 3: share the request body (need request body explicitly off)
--- config
location /echo_body {
lua_need_request_body off;
set $res '';
access_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body
nil
nil
=== TEST 4: share the request body (need request body off by default)
--- config
location /echo_body {
#lua_need_request_body off;
set $res '';
access_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body
nil
nil
=== TEST 5: share the request body (need request body on)
--- config
location /echo_body {
lua_need_request_body on;
set $res '';
access_by_lua '
ngx.var.res = ngx.var.request_body or "nil"
';
content_by_lua '
ngx.say(ngx.var.res or "nil")
ngx.say(ngx.var.request_body or "nil")
';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff
hello\x00\x01\x02
world\x03\x04\xff
"
=== TEST 6: rewrite I/O with access I/O with content I/O
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
rewrite_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
print("rewrite GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
print("rewrite PUT: " .. res.status);
res = ngx.location.capture("/memc");
print("rewrite cached: " .. res.body);
';
access_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
print("access GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
print("access PUT: " .. res.status);
res = ngx.location.capture("/memc");
print("access cached: " .. res.body);
';
content_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
ngx.say("content GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.say("content PUT: " .. res.status);
res = ngx.location.capture("/memc");
ngx.say("content cached: " .. res.body);
';
}
--- request
GET /lua
--- response_body
content GET: 404
content PUT: 201
content cached: hello
--- grep_error_log eval: qr/(?:rewrite|access) .+?(?= while )/
--- grep_error_log_out
rewrite GET: 404
rewrite PUT: 201
rewrite cached: hello
access GET: 404
access PUT: 201
access cached: hello
--- log_level: info
=== TEST 7: I/O in access shortcuts content automatically
--- config
location = /t {
access_by_lua_block {
ngx.print("")
}
echo ok;
}
--- request
GET /t
--- response_body

View file

@ -1,394 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(10);
plan tests => blocks() * repeat_each() * 2;
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /foo {
access_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
=== TEST 2: 4 concurrent requests
--- config
location /foo {
access_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
content_by_lua return;
}
location ~ '^/([a-d])$' {
echo -n $1;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
res3.status = 200
res3.body = c
res4.status = 200
res4.body = d
=== TEST 3: capture multi in series
--- config
location /foo {
access_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("2 res1.status = " .. res1.status)
ngx.say("2 res1.body = " .. res1.body)
ngx.say("2 res2.status = " .. res2.status)
ngx.say("2 res2.body = " .. res2.body)
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
2 res1.status = 200
2 res1.body = a
2 res2.status = 200
2 res2.body = b
=== TEST 4: capture multi in subrequest
--- config
location /foo {
rewrite_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location /main {
access_by_lua '
local res = ngx.location.capture("/foo?n=1")
ngx.say("top res.status = " .. res.status)
ngx.say("top res.body = [" .. res.body .. "]")
';
content_by_lua return;
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /main
--- response_body
top res.status = 200
top res.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
=== TEST 5: capture multi in parallel
--- config
location ~ '^/(foo|bar)$' {
set $tag $1;
rewrite_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location /main {
access_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("top res1.status = " .. res1.status)
ngx.say("top res1.body = [" .. res1.body .. "]")
ngx.say("top res2.status = " .. res2.status)
ngx.say("top res2.body = [" .. res2.body .. "]")
';
content_by_lua return;
}
location ~ '^/([abcd])$' {
echo -n $1;
}
--- request
GET /main
--- response_body
top res1.status = 200
top res1.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
top res2.status = 200
top res2.body = [2 res1.status = 200
2 res1.body = c
2 res2.status = 200
2 res2.body = d
]
=== TEST 6: memc sanity
--- config
location /foo {
access_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
content_by_lua return;
}
location ~ '^/[ab]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
"
=== TEST 7: memc muti + multi
--- config
location /main {
access_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = [" .. res1.body .. "]")
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = [" .. res2.body .. "]")
';
content_by_lua return;
}
location ~ '^/(foo|bar)$' {
set $tag $1;
rewrite_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
print("args: " .. ngx.var.args)
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
content_by_lua return;
}
location ~ '^/[abcd]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /main
--- response_body eval
"res1.status = 200
res1.body = [1 res1.status = 201
1 res1.body = STORED\r
1 res2.status = 201
1 res2.body = STORED\r
]
res2.status = 200
res2.body = [2 res1.status = 201
2 res1.body = STORED\r
2 res2.status = 201
2 res2.body = STORED\r
]
"
=== TEST 8: memc 4 concurrent requests
--- config
location /foo {
access_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
content_by_lua return;
}
location ~ '^/[a-d]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
res3.status = 201
res3.body = STORED\r
res4.status = 201
res4.body = STORED\r
"

View file

@ -1,657 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = <<_EOC_;
$t::StapThread::GCScript
F(ngx_http_lua_check_broken_connection) {
println("lua check broken conn")
}
F(ngx_http_lua_request_cleanup) {
println("lua req cleanup")
}
_EOC_
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
plan(skip_all => "HTTP3 does not support on_abort");
} elsif (defined $ENV{TEST_NGINX_USE_HTTP2}) {
plan(skip_all => "HTTP2 does not support on_abort");
} else {
plan tests => repeat_each() * (blocks() * 4 + 15);
}
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: ignore the client abort event in the user callback
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
terminate 1: ok
delete thread 2
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
--- timeout: 0.2
--- abort
--- wait: 0.7
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 2: abort in the user callback
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(444)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
=== TEST 3: ngx.exit(499) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(499)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 4: ngx.exit(408) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(408)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- wait: 0.1
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 5: ngx.exit(-1) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(-1)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
';
}
location = /sleep {
echo_sleep 1;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
=== TEST 6: ngx.exit(0) with pending subrequest
--- config
location = /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(0)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.location.capture("/sleep")
ngx.log(ngx.ERR, "main handler done")
';
content_by_lua return;
}
location = /sleep {
echo_sleep 0.7;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
lua check broken conn
terminate 2: fail
terminate 1: ok
delete thread 2
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
--- timeout: 0.2
--- abort
--- wait: 0.6
--- ignore_response
--- error_log eval
[
'client prematurely closed connection',
'on abort called',
qr/lua user thread aborted: runtime error: access_by_lua\(nginx\.conf:\d+\):4: attempt to abort with pending subrequests/,
'main handler done',
]
=== TEST 7: accessing cosocket in callback
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
local sock = ngx.socket.tcp()
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
ngx.exit(499)
end
local bytes, err = sock:send("flushall\\r\\n")
if not bytes then
ngx.log(ngx.ERR, "failed to send query: ", err)
ngx.exit(499)
end
local res, err = sock:receive()
if not res then
ngx.log(ngx.ERR, "failed to receive: ", err)
ngx.exit(499)
end
ngx.log(ngx.NOTICE, "callback done: ", res)
ngx.exit(499)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out_like chop
^create 2 in 1
lua check broken conn
(?:lua check broken conn
)?terminate 2: ok
lua req cleanup
delete thread 2
delete thread 1
$
--- timeout: 0.2
--- abort
--- wait: 0.2
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
callback done: +OK
=== TEST 8: ignore the client abort event in the user callback (no check)
--- config
location /t {
lua_check_client_abort off;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("cannot set on_abort: ", err)
return
end
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
terminate 1: ok
delete thread 1
lua req cleanup
--- timeout: 0.2
--- abort
--- response_body
cannot set on_abort: lua_check_client_abort is off
--- no_error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 9: register on_abort callback but no client abortion
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.say("done")
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
terminate 1: ok
delete thread 1
lua req cleanup
delete thread 2
--- response_body
done
--- no_error_log
[error]
client prematurely closed connection
on abort called
main handler done
=== TEST 10: ignore the client abort event in the user callback (uthread)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
lua check broken conn
terminate 2: ok
delete thread 2
terminate 3: ok
delete thread 3
terminate 4: ok
delete thread 4
lua req cleanup
--- timeout: 0.2
--- abort
--- wait: 0.7
--- ignore_response
--- no_error_log
[error]
--- error_log
client prematurely closed connection
on abort called
main handler done
=== TEST 11: abort in the user callback (uthread)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
ngx.exit(444)
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.7)
ngx.log(ngx.NOTICE, "main handler done")
end)
';
content_by_lua return;
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
lua check broken conn
terminate 2: ok
lua req cleanup
delete thread 2
delete thread 3
--- timeout: 0.2
--- abort
--- ignore_response
--- no_error_log
[error]
main handler done
--- error_log
client prematurely closed connection
on abort called
=== TEST 12: register on_abort callback but no client abortion (uthread)
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
error("cannot set on_abort: " .. err)
end
ngx.thread.spawn(function ()
ngx.sleep(0.1)
ngx.say("done")
end)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
create 3 in 1
spawn user thread 3 in 1
terminate 1: ok
delete thread 1
terminate 3: ok
delete thread 3
lua req cleanup
delete thread 2
--- response_body
done
--- no_error_log
[error]
client prematurely closed connection
on abort called
main handler done
=== TEST 13: register on_abort callback multiple times
--- config
location /t {
lua_check_client_abort on;
access_by_lua '
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("1: cannot set on_abort: " .. err)
return
end
local ok, err = ngx.on_abort(function ()
ngx.log(ngx.NOTICE, "on abort called")
end)
if not ok then
ngx.say("2: cannot set on_abort: " .. err)
return
end
ngx.thread.spawn(function ()
ngx.sleep(0.1)
ngx.say("done")
end)
';
}
--- request
GET /t
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
terminate 1: ok
delete thread 1
lua req cleanup
delete thread 2
--- response_body
2: cannot set on_abort: duplicate call
--- no_error_log
[error]

View file

@ -1,133 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => blocks() * repeat_each() * 3;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: default 302
--- config
location /read {
access_by_lua '
ngx.redirect("http://www.taobao.com/foo");
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 2: explicit 302
--- config
location /read {
access_by_lua '
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_TEMPORARILY);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 302 Found
--- error_code: 302
=== TEST 3: explicit 301
--- config
location /read {
access_by_lua '
ngx.redirect("http://www.taobao.com/foo", ngx.HTTP_MOVED_PERMANENTLY);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
Location: http://www.taobao.com/foo
--- response_body_like: 301 Moved Permanently
--- error_code: 301
=== TEST 4: bad rc
--- config
location /read {
access_by_lua '
ngx.redirect("http://www.taobao.com/foo", 404);
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 5: no args
--- config
location /read {
access_by_lua '
ngx.redirect()
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- response_headers
!Location
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 6: relative uri
--- config
location /read {
access_by_lua '
ngx.redirect("/foo")
ngx.say("hi")
';
content_by_lua 'return';
}
--- request
GET /read
--- raw_response_headers_like eval
my $headers;
if (defined($ENV{TEST_NGINX_USE_HTTP3}) || defined($ENV{TEST_NGINX_USE_HTTP2})) {
$headers = "location: /foo\r\n"
} else {
$headers = "Location: /foo\r\n"
}
$headers;
--- response_body_like: 302 Found
--- error_code: 302

View file

@ -1,221 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 19);
#no_diff();
#no_long_string();
#master_on();
#workers(2);
run_tests();
__DATA__
=== TEST 1: read buffered body
--- config
location = /test {
access_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
=== TEST 2: read buffered body (timed out)
--- config
client_body_timeout 1ms;
location = /test {
access_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
';
content_by_lua return;
}
--- raw_request eval
"POST /test HTTP/1.1\r
Host: localhost\r
Content-Length: 100\r
Connection: close\r
\r
hello, world"
--- response_body:
--- error_code_like: ^(?:500)?$
=== TEST 3: read buffered body and then subrequest
--- config
location /foo {
echo -n foo;
}
location = /test {
access_by_lua '
ngx.req.read_body()
local res = ngx.location.capture("/foo");
ngx.say(ngx.var.request_body)
ngx.say("sub: ", res.body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
sub: foo
=== TEST 4: first subrequest and then read buffered body
--- config
location /foo {
echo -n foo;
}
location = /test {
access_by_lua '
local res = ngx.location.capture("/foo");
ngx.req.read_body()
ngx.say(ngx.var.request_body)
ngx.say("sub: ", res.body)
';
content_by_lua return;
}
--- request
POST /test
hello, world
--- response_body
hello, world
sub: foo
=== TEST 5: failed to write 100 continue
--- config
location = /test {
access_by_lua '
ngx.req.read_body()
ngx.say(ngx.var.request_body)
ngx.exit(200)
';
}
--- request
POST /test
hello, world
--- more_headers
Expect: 100-Continue
--- ignore_response
--- no_error_log
[alert]
[error]
http finalize request: 500, "/test?" a:1, c:0
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 6: not discard body (exit 200)
--- config
location = /foo {
access_by_lua '
-- ngx.req.discard_body()
ngx.say("body: ", ngx.var.request_body)
ngx.exit(200)
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
["body: nil\n",
"body: hiya, world\n",
]
--- error_code eval
[200, 200]
--- no_error_log
[error]
[alert]
=== TEST 7: not discard body (exit 201)
--- config
location = /foo {
access_by_lua '
-- ngx.req.discard_body()
ngx.say("body: ", ngx.var.request_body)
ngx.exit(201)
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
["body: nil\n",
"body: hiya, world\n",
]
--- error_code eval
[200, 200]
--- no_error_log
[error]
[alert]
=== TEST 8: not discard body (exit 302)
--- config
location = /foo {
access_by_lua '
-- ngx.req.discard_body()
-- ngx.say("body: ", ngx.var.request_body)
ngx.redirect("/blah")
';
}
location = /bar {
content_by_lua '
ngx.req.read_body()
ngx.say("body: ", ngx.var.request_body)
';
}
--- pipelined_requests eval
["POST /foo
hello, world",
"POST /bar
hiya, world"]
--- response_body eval
[qr/302 Found/,
"body: hiya, world\n",
]
--- error_code eval
[302, 200]
--- no_error_log
[error]
[alert]

View file

@ -1,172 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('debug'); # to ensure any log-level can be outputted
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: test reading request body
--- config
location /echo_body {
lua_need_request_body on;
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 2: test not reading request body
--- config
location /echo_body {
lua_need_request_body off;
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 3: test default setting (not reading request body)
--- config
location /echo_body {
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 4: test main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 5: test server conf
--- config
lua_need_request_body on;
location /echo_body {
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"hello\x00\x01\x02
world\x03\x04\xff"
=== TEST 6: test override main conf
--- http_config
lua_need_request_body on;
--- config
location /echo_body {
lua_need_request_body off;
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 7: test override server conf
--- config
lua_need_request_body on;
location /echo_body {
lua_need_request_body off;
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request eval
"POST /echo_body
hello\x00\x01\x02
world\x03\x04\xff"
--- response_body eval
"nil"
=== TEST 8: Expect: 100-Continue
--- config
location /echo_body {
lua_need_request_body on;
access_by_lua '
ngx.print(ngx.var.request_body or "nil")
ngx.exit(200)
';
}
--- request
POST /echo_body
hello world
--- more_headers
Expect: 100-Continue
--- ignore_response
--- no_error_log
[error]
[alert]
http finalize request: 500, "/echo_body?" a:1, c:2
http finalize request: 500, "/echo_body?" a:1, c:0
--- log_level: debug

View file

@ -1,743 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#log_level('warn');
#no_nginx_manager();
#master_on();
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 11);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: basic print
--- config
location /lua {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
access_by_lua 'ngx.print("Hello, Lua!\\n")';
content_by_lua return;
#content_by_lua 'ngx.say("Hi")';
}
--- request
GET /lua
--- response_body
Hello, Lua!
=== TEST 2: basic say
--- config
location /say {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
access_by_lua '
ngx.say("Hello, Lua!")
ngx.say("Yay! ", 123)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /say
--- response_body
Hello, Lua!
Yay! 123
=== TEST 3: no ngx.echo
--- config
location /lua {
access_by_lua 'ngx.echo("Hello, Lua!\\n")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: variable
--- config
location /lua {
# NOTE: the newline escape sequence must be double-escaped, as nginx config
# parser will unescape first!
access_by_lua 'local v = ngx.var["request_uri"] ngx.print("request_uri: ", v, "\\n")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua?a=1&b=2
--- response_body
request_uri: /lua?a=1&b=2
=== TEST 5: variable (file)
--- config
location /lua {
access_by_lua_file html/test.lua;
content_by_lua 'ngx.exit(ngx.OK)';
}
--- user_files
>>> test.lua
local v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- response_body
request_uri: /lua?a=1&b=2
=== TEST 6: calc expression
--- config
location /lua {
access_by_lua_file html/calc.lua;
content_by_lua 'ngx.exit(ngx.OK)';
}
--- user_files
>>> calc.lua
local function uri_unescape(uri)
local function convert(hex)
return string.char(tonumber("0x"..hex))
end
local s = string.gsub(uri, "%%([0-9a-fA-F][0-9a-fA-F])", convert)
return s
end
local function eval_exp(str)
return loadstring("return "..str)()
end
local exp_str = ngx.var["arg_exp"]
-- print("exp: '", exp_str, "'\n")
local status, res
status, res = pcall(uri_unescape, exp_str)
if not status then
ngx.print("error: ", res, "\n")
return
end
status, res = pcall(eval_exp, res)
if status then
ngx.print("result: ", res, "\n")
else
ngx.print("error: ", res, "\n")
end
--- request
GET /lua?exp=1%2B2*math.sin(3)%2Fmath.exp(4)-math.sqrt(2)
--- response_body
result: -0.4090441561579
=== TEST 7: read $arg_xxx
--- config
location = /lua {
access_by_lua 'local who = ngx.var.arg_who
ngx.print("Hello, ", who, "!")';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua?who=agentzh
--- response_body chomp
Hello, agentzh!
=== TEST 8: capture location
--- config
location /other {
echo "hello, world";
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other")
ngx.print("status=", res.status, " ")
ngx.print("body=", res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
status=200 body=hello, world
=== TEST 9: capture non-existed location
--- config
location /lua {
access_by_lua 'local res = ngx.location.capture("/other"); ngx.print("status=", res.status)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body: status=404
=== TEST 10: invalid capture location (not as expected...)
--- config
location /lua {
access_by_lua 'local res = ngx.location.capture("*(#*"); ngx.say("res=", res.status)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
res=404
=== TEST 11: nil is "nil"
--- config
location /lua {
access_by_lua 'ngx.say(nil)';
content_by_lua return;
}
--- request
GET /lua
--- response_body
nil
=== TEST 12: write boolean
--- config
location /lua {
access_by_lua 'ngx.say(true, " ", false)';
content_by_lua return;
}
--- request
GET /lua
--- response_body
true false
=== TEST 13: bad argument type to ngx.location.capture
--- config
location /lua {
access_by_lua 'ngx.location.capture(nil)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 14: capture location (default 0);
--- config
location /recur {
access_by_lua '
local num = tonumber(ngx.var.arg_num) or 0;
ngx.print("num is: ", num, "\\n");
if (num > 0) then
local res = ngx.location.capture("/recur?num="..tostring(num - 1));
ngx.print("status=", res.status, " ");
ngx.print("body=", res.body, "\\n");
else
ngx.print("end\\n");
end
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /recur
--- response_body
num is: 0
end
=== TEST 15: capture location
access phase not running in subrequests
--- config
location /recur {
access_by_lua '
local num = tonumber(ngx.var.arg_num) or 0;
ngx.print("num is: ", num, "\\n");
if (num > 0) then
local res = ngx.location.capture("/recur?num="..tostring(num - 1));
ngx.print("status=", res.status, " ");
ngx.print("body=", res.body);
else
ngx.print("end\\n");
end
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /recur?num=3
--- response_body chomp
num is: 3
status=200 body=
=== TEST 16: setting nginx variables from within Lua
--- config
location /set {
set $a "";
access_by_lua 'ngx.var.a = 32; ngx.say(ngx.var.a)';
content_by_lua 'ngx.exit(ngx.OK)';
add_header Foo $a;
}
--- request
GET /set
--- response_headers
Foo: 32
--- response_body
32
=== TEST 17: nginx quote sql string 1
--- config
location /set {
set $a 'hello\n\r\'"\\'; # this runs after access_by_lua
access_by_lua 'ngx.say(ngx.quote_sql_str(ngx.var.a))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
'hello\n\r\'\"\\'
=== TEST 18: nginx quote sql string 2
--- config
location /set {
#set $a "hello\n\r'\"\\";
access_by_lua 'ngx.say(ngx.quote_sql_str("hello\\n\\r\'\\"\\\\"))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
'hello\n\r\'\"\\'
=== TEST 19: use dollar
--- config
location /set {
access_by_lua '
local s = "hello 112";
ngx.say(string.find(s, "%d+$"))';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /set
--- response_body
79
=== TEST 20: subrequests do not share variables of main requests by default
--- config
location /sub {
echo $a;
}
location /parent {
set $a 12;
access_by_lua 'local res = ngx.location.capture("/sub"); ngx.print(res.body)';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body eval: "\n"
=== TEST 21: subrequests can share variables of main requests
--- config
location /sub {
echo $a;
}
location /parent {
set $a '';
access_by_lua '
ngx.var.a = 12;
local res = ngx.location.capture(
"/sub",
{ share_all_vars = true }
);
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body
12
=== TEST 22: main requests use subrequests' variables
--- config
location /sub {
set $a 12;
}
location /parent {
access_by_lua '
local res = ngx.location.capture("/sub", { share_all_vars = true });
ngx.say(ngx.var.a)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /parent
--- response_body
12
=== TEST 23: main requests do NOT use subrequests' variables
--- config
location /sub {
set $a 12;
content_by_lua return;
}
location /parent {
access_by_lua '
local res = ngx.location.capture("/sub", { share_all_vars = false });
ngx.say(ngx.var.a)
';
content_by_lua return;
}
--- request
GET /parent
--- response_body_like eval: "\n"
=== TEST 24: capture location headers
--- config
location /other {
default_type 'foo/bar';
echo "hello, world";
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
=== TEST 25: capture location headers
--- config
location /other {
default_type 'foo/bar';
rewrite_by_lua '
ngx.header.Bar = "Bah";
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
ngx.say("Bar: ", res.header["Bar"]);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
Bar: Bah
=== TEST 26: capture location headers
--- config
location /other {
default_type 'foo/bar';
access_by_lua '
ngx.header.Bar = "Bah";
ngx.header.Bar = nil;
';
content_by_lua 'ngx.exit(ngx.OK)';
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other");
ngx.say("type: ", res.header["Content-Type"]);
ngx.say("Bar: ", res.header["Bar"] or "nil");
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
type: foo/bar
Bar: nil
=== TEST 27: access_by_lua runs after ngx_access
--- config
location /lua {
deny all;
access_by_lua '
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
';
content_by_lua return;
}
--- request
GET /lua
--- response_body_like: 403 Forbidden
--- error_code: 403
=== TEST 28: auth_request runs before ngx_access
--- config
location /lua {
deny all;
auth_request /auth;
content_by_lua return;
}
--- request
GET /lua
--- response_body_like: 403 Forbidden
--- error_code: 403
--- SKIP
=== TEST 29: access_by_lua shouldn't send headers automatically (on simple return)
--- config
location /lua {
access_by_lua 'return';
proxy_pass http://127.0.0.1:$server_port/foo;
}
location = /foo {
default_type 'text/css';
add_header Bar Baz;
echo foo;
}
--- request
GET /lua
--- response_headers
Bar: Baz
Content-Type: text/css
--- response_body
foo
=== TEST 30: access_by_lua shouldn't send headers automatically (on simple exit)
--- config
location /lua {
access_by_lua 'ngx.exit(ngx.OK)';
proxy_pass http://127.0.0.1:$server_port/foo;
}
location = /foo {
default_type 'text/css';
add_header Bar Baz;
echo foo;
}
--- request
GET /lua
--- response_headers
Bar: Baz
Content-Type: text/css
--- response_body
foo
=== TEST 31: short circuit
--- config
location /lua {
access_by_lua '
ngx.say("Hi")
ngx.eof()
ngx.exit(ngx.HTTP_OK)
';
content_by_lua '
print("HERE")
ngx.print("BAD")
';
}
--- request
GET /lua
--- response_body
Hi
=== TEST 32: nginx vars in script path
--- config
location ~ ^/lua/(.+)$ {
access_by_lua_file html/$1.lua;
content_by_lua '
print("HERE")
ngx.print("BAD")
';
}
--- user_files
>>> hi.lua
ngx.say("Hi")
ngx.eof()
ngx.exit(ngx.HTTP_OK)
--- request
GET /lua/hi
--- response_body
Hi
=== TEST 33: phase postponing works for various locations (access phase not running in subrequest)
--- config
location ~ '^/lua/(.+)' {
set $path $1;
access_by_lua 'ngx.say(ngx.var.path)';
content_by_lua return;
}
location ~ '^/lua2/(.+)' {
set $path $1;
access_by_lua 'ngx.say(ngx.var.path)';
content_by_lua return;
}
location /main {
echo_location /lua/foo;
echo_location /lua/bar;
echo_location /lua2/baz;
echo_location /lua2/bah;
}
--- request
GET /main
--- response_body
=== TEST 34: server access_by_lua
--- config
access_by_lua 'ngx.header["X-Foo"] = "bar" -- ngx.send_headers()';
--- request
GET /
--- response_body chop
<html><head><title>It works!</title></head><body>It works!</body></html>
--- response_headers
X-Foo: bar
=== TEST 35: server access_by_lua_file
--- config
access_by_lua_file html/foo.lua;
--- user_files
>>> foo.lua
ngx.header["X-Foo"] = "bar" -- ngx.send_headers()
--- request
GET /
--- response_body chop
<html><head><title>It works!</title></head><body>It works!</body></html>
--- response_headers
X-Foo: bar
=== TEST 36: Lua file does not exist
--- config
location /lua {
access_by_lua_file html/test2.lua;
}
--- user_files
>>> test.lua
v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- response_body_like: 404 Not Found
--- error_code: 404
--- error_log eval
qr/failed to load external Lua file ".*?test2\.lua": cannot open .*? No such file or directory/
=== TEST 37: use of ngx.say() in access_by_lua without exiting with 200+.
--- config
location /t {
access_by_lua "ngx.say('test')";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]
=== TEST 38: use of ngx.say() in access_by_lua without exiting with 200+. (with explicit ngx.eof())
--- config
location /t {
access_by_lua "ngx.say('test') ngx.eof()";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]
=== TEST 39: use of ngx.say() in access_by_lua without exiting with 200+. (with IO)
--- config
location /t {
access_by_lua "ngx.say('test') ngx.sleep(0.001)";
echo_exec /t2;
}
--- request
GET /t
--- response_body
test
--- no_error_log
[alert]

View file

@ -1,211 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
worker_connections(1014);
#master_on();
#workers(4);
#log_level('warn');
no_root_location();
#repeat_each(2);
#repeat_each(2);
plan tests => repeat_each() * (blocks() * 3);
our $HtmlDir = html_dir;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: satisfy any
--- config
location /test {
satisfy any;
allow all;
access_by_lua 'ngx.exit(403)';
echo something important;
}
--- request
GET /test
--- more_headers
--- response_body
something important
--- no_error_log
[error]
=== TEST 2: satisfy any
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.exit(403)';
echo something important;
}
--- request
GET /test
--- more_headers
--- response_body_like: 403 Forbidden
--- error_code: 403
--- error_log
access forbidden by rule
=== TEST 3: satisfy any (explicit ngx.exit(0))
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.exit(0)';
echo something important;
}
--- request
GET /test
--- more_headers
--- response_body
something important
--- error_code: 200
--- no_error_log
[error]
=== TEST 4: satisfy any (simple return)
--- config
location /test {
satisfy any;
deny all;
access_by_lua return;
echo something important;
}
--- request
GET /test
--- more_headers
--- response_body
something important
--- error_code: 200
--- no_error_log
[error]
=== TEST 5: satisfy any (declined)
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.exit(ngx.DECLINED)';
echo something important;
}
--- request
GET /test
--- more_headers
--- response_body_like: 403 Forbidden
--- error_code: 403
--- error_log
access forbidden by rule
=== TEST 6: satisfy any (declined, with I/O)
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.location.capture("/echo") ngx.exit(ngx.DECLINED)';
echo something important;
}
location /echo {
echo hi;
#echo_sleep 0.01;
}
--- request
GET /test
--- more_headers
--- response_body_like: 403 Forbidden
--- error_code: 403
--- error_log
access forbidden by rule
=== TEST 7: satisfy any (simple return, with I/O)
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.location.capture("/echo") return';
echo something important;
}
location /echo {
echo hi;
}
--- request
GET /test
--- more_headers
--- response_body
something important
--- error_code: 200
--- no_error_log
[error]
=== TEST 8: satisfy any - with I/O
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.location.capture("/echo") ngx.exit(403)';
echo something important;
}
location /echo {
echo hi;
}
--- request
GET /test
--- more_headers
--- response_body_like: 403 Forbidden
--- error_code: 403
--- error_log
access forbidden by rule
=== TEST 9: satisfy any (explicit ngx.exit(0), with I/O)
--- config
location /test {
satisfy any;
deny all;
access_by_lua 'ngx.location.capture("/echo") ngx.exit(0)';
echo something important;
}
location /echo {
echo hi;
}
--- request
GET /test
--- more_headers
--- response_body
something important
--- error_code: 200
--- no_error_log
[error]

View file

@ -1,224 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
log_level('debug');
repeat_each(2);
plan tests => repeat_each() * 33;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sleep 0.5
--- config
location /test {
access_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.sleep(0.5)
local now = ngx.now()
ngx.say(now - before)
ngx.exit(200)
';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:4[5-9]\d*|5[0-5]\d*|5)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
=== TEST 2: sleep ag
--- config
location /test {
access_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.sleep("a")
local now = ngx.now()
ngx.say(now - before)
ngx.exit(200)
';
}
--- request
GET /test
--- error_code: 500
--- response_body_like: 500 Internal Server Error
--- error_log
bad argument #1 to 'sleep'
=== TEST 3: sleep 0.5 in subrequest
--- config
location /test {
access_by_lua '
ngx.update_time()
local before = ngx.now()
ngx.location.capture("/sleep")
local now = ngx.now()
local delay = now - before
ngx.say(delay)
ngx.exit(200)
';
}
location /sleep {
content_by_lua 'ngx.sleep(0.5)';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:4[5-9]\d*|5[0-9]\d*|5)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/sleep?"
--- no_error_log
[error]
=== TEST 4: sleep a in subrequest with bad argument
--- config
location /test {
access_by_lua '
local res = ngx.location.capture("/sleep");
ngx.say(res.status)
ngx.exit(200)
';
}
location /sleep {
content_by_lua 'ngx.sleep("a")';
}
--- request
GET /test
--- response_body
500
--- error_log
bad argument #1 to 'sleep'
=== TEST 5: sleep 0.5 - multi-times
--- quic_max_idle_timeout: 1.0
--- config
location /test {
access_by_lua '
ngx.update_time()
local start = ngx.now()
ngx.sleep(0.3)
ngx.sleep(0.3)
ngx.sleep(0.3)
ngx.say(ngx.now() - start)
ngx.exit(200)
';
}
--- request
GET /test
--- response_body_like chop
^0\.(?:8[5-9]\d*|9[0-9]\d*|9)$
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 6: sleep 0.5 - interleaved by ngx.say() - ended by ngx.sleep
--- quic_max_idle_timeout: 2.2
--- config
location /test {
access_by_lua '
ngx.send_headers()
-- ngx.location.capture("/sleep")
ngx.sleep(1)
ngx.say("blah")
ngx.sleep(1)
-- ngx.location.capture("/sleep")
ngx.exit(200)
';
}
location = /sleep {
echo_sleep 0.1;
}
--- request
GET /test
--- response_body
blah
--- error_log
lua ready to sleep
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 7: sleep 0.5 - interleaved by ngx.say() - not ended by ngx.sleep
--- quic_max_idle_timeout: 0.85
--- config
location /test {
access_by_lua '
ngx.send_headers()
-- ngx.location.capture("/sleep")
ngx.sleep(0.3)
ngx.say("blah")
ngx.sleep(0.5)
-- ngx.location.capture("/sleep")
ngx.say("hiya")
ngx.exit(200)
';
}
location = /sleep {
echo_sleep 0.1;
}
--- request
GET /test
--- response_body
blah
hiya
--- error_log
lua ready to sleep for
lua sleep timer expired: "/test?"
--- no_error_log
[error]
=== TEST 8: ngx.location.capture before and after ngx.sleep
--- config
location /test {
access_by_lua '
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.sleep(0.1)
res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.exit(200)
';
}
location = /hello {
echo hello world;
}
location = /sub {
proxy_pass http://127.0.0.1:$server_port/hello;
}
--- request
GET /test
--- response_body
hello world
hello world
--- no_error_log
[error]

View file

@ -1,601 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: DELETE
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_DELETE });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
DELETE
=== TEST 2: DELETE (proxy method)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_DELETE });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
DELETE
=== TEST 3: POST (nobody, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_POST });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
POST
=== TEST 4: HEAD
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_HEAD });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
=== TEST 5: explicit GET
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_GET });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 6: implicit GET
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo")
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 7: implicit GET (empty option table)
--- config
location /other {
default_type 'foo/bar';
echo $echo_request_method;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo", {})
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET
=== TEST 8: PUT (nobody, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo_read_request_body;
echo $echo_request_method;
echo_request_body;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
PUT
hello
=== TEST 9: PUT (nobody, no proxy method)
--- config
location /other {
default_type 'foo/bar';
#echo_read_request_body;
echo $echo_request_method;
#echo $echo_request_body;
echo_request_body;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
PUT
hello
=== TEST 10: PUT (nobody, no proxy method)
--- config
location /other {
default_type 'foo/bar';
#echo_read_request_body;
echo $echo_request_method;
#echo $echo_request_body;
echo_request_body;
#echo "[$http_content_length]";
echo;
}
location /foo {
echo $echo_request_method;
echo -n "[$http_content_length]";
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/other",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.print(res.body)
res = ngx.location.capture("/foo")
ngx.say(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
PUT
hello
GET
[]
=== TEST 11: POST (with body, proxy method)
--- config
location /other {
default_type 'foo/bar';
echo_read_request_body;
echo $echo_request_method;
echo_request_body;
}
location /foo {
proxy_pass http://127.0.0.1:$server_port/other;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ method = ngx.HTTP_POST, body = "hello" });
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body chomp
POST
hello
=== TEST 12: POST (with body, memc method)
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
access_by_lua '
ngx.location.capture("/flush");
local res = ngx.location.capture("/memc");
ngx.say("GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello" });
ngx.say("PUT: " .. res.status);
res = ngx.location.capture("/memc");
ngx.say("cached: " .. res.body);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET: 404
PUT: 201
cached: hello
=== TEST 13: POST (with body, memc method)
--- config
location /flush {
set $memc_cmd flush_all;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /memc {
set $memc_cmd "";
set $memc_key $echo_request_uri;
set $memc_exptime 600;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location /lua {
access_by_lua '
ngx.location.capture("/flush",
{ share_all_vars = true });
local res = ngx.location.capture("/memc",
{ share_all_vars = true });
ngx.say("GET: " .. res.status);
res = ngx.location.capture("/memc",
{ method = ngx.HTTP_PUT, body = "hello", share_all_vars = true });
ngx.say("PUT: " .. res.status);
res = ngx.location.capture("/memc", { share_all_vars = true });
ngx.say("cached: " .. res.body);
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
GET: 404
PUT: 201
cached: hello
=== TEST 14: empty args option table
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = {} })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body eval: "\n"
=== TEST 15: non-empty args option table (1 pair)
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = { ["fo="] = "=>" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
fo%3D=%3D%3E
=== TEST 16: non-empty args option table (2 pairs)
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = { ["fo="] = "=>",
["="] = ":" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like chop
^(?:fo%3D=%3D%3E\&%3D=%3A|%3D=%3A\&fo%3D=%3D%3E)$
=== TEST 17: non-empty args option table (2 pairs, no special chars)
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = { foo = 3,
bar = "hello" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like chop
^(?:bar=hello\&foo=3|foo=3\&bar=hello)$
=== TEST 18: non-empty args option table (number key)
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = { [57] = "hi" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 19: non-empty args option table (plain arrays)
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo",
{ args = { "hi" } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 20: more args
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo?a=3",
{ args = { b = 4 } })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
a=3&b=4
=== TEST 21: more args
--- config
location /foo {
echo $query_string;
}
location /lua {
access_by_lua '
local res = ngx.location.capture("/foo?a=3",
{ args = "b=4" })
ngx.print(res.body)
';
content_by_lua 'ngx.exit(ngx.OK)';
}
--- request
GET /lua
--- response_body
a=3&b=4
=== TEST 22: I/O in named location
the nginx core requires the patch https://github.com/agentzh/ngx_openresty/blob/master/patches/nginx-1.0.15-reset_wev_handler_in_named_locations.patch
--- config
location /t {
echo_exec @named;
}
location @named {
access_by_lua '
ngx.location.capture("/hello")
';
echo done;
}
location /hello {
echo hello;
}
--- request
GET /t
--- response_body
done

View file

@ -1,346 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = $t::StapThread::GCScript;
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4);
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: exec in user thread (entry still pending)
--- config
location /lua {
access_by_lua '
local function f()
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.sleep(1)
ngx.say("hello")
';
content_by_lua return;
}
location /foo {
echo i am foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
spawn user thread 2 in 1
terminate 2: ok
delete thread 2
delete thread 1
--- response_body
i am foo
--- no_error_log
[error]
=== TEST 2: exec in user thread (entry already quits)
--- config
location /lua {
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
';
content_by_lua return;
}
location /foo {
echo i am foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval: $::GCScript
--- stap_out
create 2 in 1
spawn user thread 2 in 1
terminate 1: ok
delete thread 1
terminate 2: ok
delete thread 2
--- response_body
i am foo
--- no_error_log
[error]
=== TEST 3: exec in user thread (entry thread is still pending on ngx.sleep)
--- config
location /lua {
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.sleep(1)
';
content_by_lua return;
}
location = /foo {
echo hello foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 1000
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 1
free request
--- wait: 0.1
--- response_body
hello foo
--- no_error_log
[error]
=== TEST 4: exec in a user thread (another user thread is still pending on ngx.sleep)
--- config
location /lua {
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
local function g()
ngx.sleep(1)
end
ngx.thread.spawn(f)
ngx.thread.spawn(g)
';
content_by_lua return;
}
location = /foo {
echo hello foo;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
create 3 in 1
spawn user thread 3 in 1
add timer 1000
terminate 1: ok
delete thread 1
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 3
free request
--- response_body
hello foo
--- no_error_log
[error]
=== TEST 5: exec in user thread (entry thread is still pending on ngx.location.capture), without pending output
--- config
location /lua {
client_body_timeout 12000ms;
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.exec("/foo")
end
ngx.thread.spawn(f)
ngx.location.capture("/sleep")
ngx.say("end")
';
}
location = /sleep {
echo_sleep 0.2;
}
location = /foo {
echo hello world;
}
--- request
POST /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 200 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 200
expire timer 100
terminate 2: fail
expire timer 200
terminate 1: ok
delete thread 2
delete thread 1
free request
--- wait: 0.1
--- response_body
end
--- error_log
attempt to abort with pending subrequests

File diff suppressed because it is too large Load diff

View file

@ -1,189 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
use t::StapThread;
our $GCScript = $t::StapThread::GCScript;
our $StapScript = $t::StapThread::StapScript;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 4);
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
#no_shuffle();
no_long_string();
run_tests();
__DATA__
=== TEST 1: ngx.redirect() in user thread (entry thread is still pending on ngx.location.capture_multi), without pending output
--- config
location /lua {
client_body_timeout 12000ms;
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.redirect(301)
end
ngx.thread.spawn(f)
ngx.location.capture_multi{
{"/echo"},
{"/sleep"}
}
ngx.say("end")
';
}
location = /echo {
echo hello;
}
location = /sleep {
echo_sleep 0.2;
}
--- request
POST /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 200 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_post_subrequest) {
printf("post subreq %s\n", ngx_http_req_uri($r))
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
post subreq /echo
add timer 200
expire timer 100
terminate 2: fail
expire timer 200
post subreq /sleep
terminate 1: ok
delete thread 2
delete thread 1
free request
--- response_body
end
--- error_log
attempt to abort with pending subrequests
=== TEST 2: redirect in user thread (entry thread is still pending on ngx.sleep)
--- config
location /lua {
access_by_lua '
local function f()
ngx.sleep(0.1)
ngx.redirect(301)
end
ngx.thread.spawn(f)
ngx.sleep(1)
ngx.say("end")
';
content_by_lua return;
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 1000 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
/*
if (tm == 1000) {
print_ubacktrace()
}
*/
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 1000 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_sleep_cleanup) {
println("lua sleep cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 1000
expire timer 100
terminate 2: ok
delete thread 2
lua sleep cleanup
delete timer 1000
delete thread 1
free request
--- wait: 0.1
--- response_body_like: 302 Found
--- error_code: 302
--- no_error_log
[error]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,131 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => blocks() * repeat_each() * 3;
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
no_long_string();
run_tests();
__DATA__
=== TEST 1: when mysql query timed out, kill that query by Lua
--- http_config
upstream backend {
drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
--- config
location = /mysql {
#internal;
drizzle_send_query_timeout 100ms;
#drizzle_send_query_timeout 1s;
drizzle_query $echo_request_body;
drizzle_pass backend;
#error_page 504 /ret/504;
rds_json on;
more_set_headers -s 504 "X-Mysql-Tid: $drizzle_thread_id";
}
location /lua {
content_by_lua '
local sql = "select sleep(5)"
local res = ngx.location.capture("/mysql",
{ method = ngx.HTTP_POST, body = sql })
ngx.say("status = " .. res.status)
local tid = res.header["X-Mysql-Tid"]
if tid == nil then
ngx.say("thread id = nil")
return
end
tid = tonumber(tid)
ngx.say("thread id = " .. tid)
res = ngx.location.capture("/mysql",
{ method = ngx.HTTP_POST,
body = "kill query " .. tid })
ngx.say("kill status = " .. res.status)
ngx.say("kill body = " .. res.body)
';
}
--- request
GET /lua
--- response_body_like
^status = 504
thread id = \d+
kill status = 200
kill body = \{"errcode":0\}$
--- error_log eval
qr{upstream timed out \(\d+: Connection timed out\) while sending query to drizzle upstream}
--- skip_eval: 3:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 2: no error pages
--- http_config
upstream backend {
drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=300 mode=single overflow=ignore;
}
--- config
location @err { echo Hi; }
error_page 504 = @err;
location = /mysql {
#internal;
drizzle_send_query_timeout 100ms;
#drizzle_send_query_timeout 1s;
drizzle_query $echo_request_body;
drizzle_pass backend;
no_error_pages;
rds_json on;
more_set_headers -s 504 "X-Mysql-Tid: $drizzle_thread_id";
}
location /lua {
content_by_lua '
local sql = "select sleep(3)"
local res = ngx.location.capture("/mysql",
{ method = ngx.HTTP_POST, body = sql })
ngx.say("status = " .. res.status)
local tid = res.header["X-Mysql-Tid"]
if tid == nil then
ngx.say("thread id = nil")
return
end
tid = tonumber(tid)
ngx.say("thread id = " .. tid)
res = ngx.location.capture("/mysql",
{ method = ngx.HTTP_POST,
body = "kill query " .. tid })
ngx.say("kill status = " .. res.status)
ngx.say("kill body = " .. res.body)
';
}
--- request
GET /lua
--- response_body_like
^status = 504
thread id = \d+
kill status = 200
kill body = \{"errcode":0\}$
--- SKIP

View file

@ -1,826 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(10);
plan tests => repeat_each() * (blocks() * 2 + 4);
#$ENV{LUA_PATH} = $ENV{HOME} . '/work/JSON4Lua-0.9.30/json/?.lua';
$ENV{TEST_NGINX_MYSQL_PORT} ||= 3306;
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#log_level 'warn';
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
=== TEST 2: 4 concurrent requests
--- config
location /foo {
content_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
}
location ~ '^/([a-d])$' {
echo -n $1;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
res3.status = 200
res3.body = c
res4.status = 200
res4.body = d
=== TEST 3: capture multi in series
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("2 res1.status = " .. res1.status)
ngx.say("2 res1.body = " .. res1.body)
ngx.say("2 res2.status = " .. res2.status)
ngx.say("2 res2.body = " .. res2.body)
';
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /foo
--- response_body
res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
2 res1.status = 200
2 res1.body = a
2 res2.status = 200
2 res2.body = b
=== TEST 4: capture multi in subrequest
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
}
location /main {
content_by_lua '
local res = ngx.location.capture("/foo?n=1")
ngx.say("top res.status = " .. res.status)
ngx.say("top res.body = [" .. res.body .. "]")
';
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
--- request
GET /main
--- response_body
top res.status = 200
top res.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
=== TEST 5: capture multi in parallel
--- config
location ~ '^/(foo|bar)$' {
set $tag $1;
content_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
}
location /main {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("top res1.status = " .. res1.status)
ngx.say("top res1.body = [" .. res1.body .. "]")
ngx.say("top res2.status = " .. res2.status)
ngx.say("top res2.body = [" .. res2.body .. "]")
';
}
location ~ '^/([abcd])$' {
echo -n $1;
}
--- request
GET /main
--- response_body
top res1.status = 200
top res1.body = [1 res1.status = 200
1 res1.body = a
1 res2.status = 200
1 res2.body = b
]
top res2.status = 200
top res2.body = [2 res1.status = 200
2 res1.body = c
2 res2.status = 200
2 res2.body = d
]
=== TEST 6: memc sanity
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = " .. res1.body)
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = " .. res2.body)
';
}
location ~ '^/[ab]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
"
=== TEST 7: memc muti + multi
--- config
location /main {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo?n=1" },
{ "/bar?n=2" },
}
ngx.say("res1.status = " .. res1.status)
ngx.say("res1.body = [" .. res1.body .. "]")
ngx.say("res2.status = " .. res2.status)
ngx.say("res2.body = [" .. res2.body .. "]")
';
}
location ~ '^/(foo|bar)$' {
set $tag $1;
content_by_lua '
local res1, res2
if ngx.var.tag == "foo" then
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
else
res1, res2 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
end
print("args: " .. ngx.var.args)
local n = ngx.var.arg_n
ngx.say(n .. " res1.status = " .. res1.status)
ngx.say(n .. " res1.body = " .. res1.body)
ngx.say(n .. " res2.status = " .. res2.status)
ngx.say(n .. " res2.body = " .. res2.body)
';
}
location ~ '^/[abcd]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /main
--- response_body eval
"res1.status = 200
res1.body = [1 res1.status = 201
1 res1.body = STORED\r
1 res2.status = 201
1 res2.body = STORED\r
]
res2.status = 200
res2.body = [2 res1.status = 201
2 res1.body = STORED\r
2 res2.status = 201
2 res2.body = STORED\r
]
"
=== TEST 8: memc 4 concurrent requests
--- config
location /foo {
content_by_lua '
local res1, res2, res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
{ "/c" },
{ "/d" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
}
location ~ '^/[a-d]$' {
set $memc_key $uri;
set $memc_value hello;
set $memc_cmd set;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
--- request
GET /foo
--- response_body eval
"res1.status = 201
res1.body = STORED\r
res2.status = 201
res2.body = STORED\r
res3.status = 201
res3.body = STORED\r
res4.status = 201
res4.body = STORED\r
"
=== TEST 9: capture multi in series (more complex)
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
local res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
res3, res4 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
}
location /a {
echo -n a;
}
location /b {
echo -n b;
}
location /main {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo" },
{ "/foo" },
}
local res3, res4 = ngx.location.capture_multi{
{ "/foo" },
{ "/foo" },
}
ngx.print(res1.body)
ngx.print(res2.body)
ngx.print(res3.body)
ngx.print(res4.body)
';
}
--- request
GET /main
--- response_body eval
"res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
res3.status = 200
res3.body = a
res4.status = 200
res4.body = b
" x 4
=== TEST 10: capture multi in series (more complex, using memc)
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
res1, res2 = ngx.location.capture_multi{
{ "/a" },
{ "/b" },
}
local res3, res4 = ngx.location.capture_multi{
{ "/c" },
{ "/d" },
}
res3, res4 = ngx.location.capture_multi{
{ "/e" },
{ "/f" },
}
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)
ngx.say("res4.status = " .. res4.status)
ngx.say("res4.body = " .. res4.body)
';
}
location /memc {
set $memc_key $arg_val;
set $memc_value $arg_val;
set $memc_cmd $arg_cmd;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location ~ '^/([a-f])$' {
set $tag $1;
content_by_lua '
ngx.location.capture("/memc?cmd=set&val=" .. ngx.var.tag)
local res = ngx.location.capture("/memc?cmd=get&val=" .. ngx.var.tag)
ngx.print(res.body)
';
}
location /main {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/foo" },
{ "/foo" },
}
local res3, res4 = ngx.location.capture_multi{
{ "/foo" },
{ "/foo" },
}
ngx.print(res1.body)
ngx.print(res2.body)
ngx.print(res3.body)
ngx.print(res4.body)
';
}
--- request
GET /main
--- response_body2
--- response_body eval
"res1.status = 200
res1.body = a
res2.status = 200
res2.body = b
res3.status = 200
res3.body = e
res4.status = 200
res4.body = f
" x 4
--- no_error_log eval
["[error]", "[alert]"]
--- timeout: 10
=== TEST 11: a mixture of rewrite, access, content phases
--- config
location /main {
rewrite_by_lua '
local res = ngx.location.capture("/a")
print("rewrite a: " .. res.body)
res = ngx.location.capture("/b")
print("rewrite b: " .. res.body)
res = ngx.location.capture("/c")
print("rewrite c: " .. res.body)
';
access_by_lua '
local res = ngx.location.capture("/A")
print("access A: " .. res.body)
res = ngx.location.capture("/B")
print("access B: " .. res.body)
';
content_by_lua '
local res = ngx.location.capture("/d")
ngx.say("content d: " .. res.body)
res = ngx.location.capture("/e")
ngx.say("content e: " .. res.body)
res = ngx.location.capture("/f")
ngx.say("content f: " .. res.body)
';
}
location /memc {
set $memc_key $arg_val;
set $memc_value $arg_val;
set $memc_cmd $arg_cmd;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location ~ '^/([A-F])$' {
echo -n $1;
}
location ~ '^/([a-f])$' {
set $tag $1;
content_by_lua '
ngx.location.capture("/memc?cmd=set&val=" .. ngx.var.tag)
local res = ngx.location.capture("/memc?cmd=get&val=" .. ngx.var.tag)
ngx.print(res.body)
';
}
--- request
GET /main
--- response_body
content d: d
content e: e
content f: f
--- log_level: info
--- grep_error_log eval: qr/rewrite .+?(?= while )|access .+?(?=,)/
--- grep_error_log_out
rewrite a: a
rewrite b: b
rewrite c: c
access A: A
access B: B
=== TEST 12: a mixture of rewrite, access, content phases
--- config
location /main {
rewrite_by_lua '
local a, b, c = ngx.location.capture_multi{
{"/a"}, {"/b"}, {"/c"},
}
print("rewrite a: " .. a.body)
print("rewrite b: " .. b.body)
print("rewrite c: " .. c.body)
';
access_by_lua '
local A, B = ngx.location.capture_multi{
{"/A"}, {"/B"},
}
print("access A: " .. A.body)
print("access B: " .. B.body)
';
content_by_lua '
local d, e, f = ngx.location.capture_multi{
{"/d"}, {"/e"}, {"/f"},
}
ngx.say("content d: " .. d.body)
ngx.say("content e: " .. e.body)
ngx.say("content f: " .. f.body)
';
}
location /memc {
set $memc_key $arg_val;
set $memc_value $arg_val;
set $memc_cmd $arg_cmd;
memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
}
location ~ '^/([A-F])$' {
echo -n $1;
}
location ~ '^/([a-f])$' {
set $tag $1;
content_by_lua '
ngx.location.capture("/memc?cmd=set&val=" .. ngx.var.tag)
local res = ngx.location.capture("/memc?cmd=get&val=" .. ngx.var.tag)
ngx.print(res.body)
';
}
--- request
GET /main
--- stap2
global delta = " "
M(http-subrequest-start) {
r = $arg1
n = ngx_http_subreq_depth(r)
pr = ngx_http_req_parent(r)
printf("%sbegin %s -> %s (%d)\n", ngx_indent(n, delta),
ngx_http_req_uri(pr),
ngx_http_req_uri(r),
n)
}
F(ngx_http_lua_run_thread) {
r = $r
uri = ngx_http_req_uri(r)
if (uri == "/main") {
printf("run thread %s: %d\n", uri, $nret)
#print_ubacktrace()
}
}
M(http-lua-info) {
uri = ngx_http_req_uri($r)
#if (uri == "/main") {
printf("XXX info: %s: %s", uri, user_string($arg1))
#}
}
F(ngx_http_lua_post_subrequest) {
r = $r
n = ngx_http_subreq_depth(r)
pr = ngx_http_req_parent(r)
printf("%send %s -> %s (%d)\n", ngx_indent(n, delta),
ngx_http_req_uri(r),
ngx_http_req_uri(pr),
n)
}
F(ngx_http_lua_handle_subreq_responses) {
r = $r
n = ngx_http_subreq_depth(r)
printf("%shandle res %s (%d)\n", ngx_indent(n, delta), ngx_http_req_uri(r), n)
}
--- response_body
content d: d
content e: e
content f: f
--- log_level: info
--- grep_error_log eval: qr/rewrite .+?(?= while )|access .+?(?=,)/
--- grep_error_log_out
rewrite a: a
rewrite b: b
rewrite c: c
access A: A
access B: B
=== TEST 13: proxy_cache_lock in subrequests
--- http_config
proxy_cache_lock on;
proxy_cache_lock_timeout 100ms;
proxy_connect_timeout 300ms;
proxy_cache_path conf/cache levels=1:2 keys_zone=STATIC:10m inactive=10m max_size=1m;
--- config
location /foo {
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{ "/proxy" },
{ "/proxy" },
{ "/proxy" },
{ "/proxy" },
}
ngx.say("ok")
';
}
location = /proxy {
proxy_cache STATIC;
proxy_pass http://127.0.0.2:12345;
proxy_cache_key $proxy_host$uri$args;
proxy_cache_valid any 1s;
#proxy_http_version 1.1;
}
--- request
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

File diff suppressed because it is too large Load diff

View file

@ -1,87 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: http_time in content_by_lua
--- config
location /lua {
content_by_lua '
ngx.say(ngx.http_time(1290079655))
';
}
--- request
GET /lua
--- response_body
Thu, 18 Nov 2010 11:27:35 GMT
=== TEST 2: http_time in set_by_lua
--- config
location /lua {
set_by_lua $a '
return ngx.http_time(1290079655)
';
echo $a;
}
--- request
GET /lua
--- response_body
Thu, 18 Nov 2010 11:27:35 GMT
=== TEST 3: parse_http_time in set_by_lua
--- config
location /lua {
set_by_lua $a '
return ngx.parse_http_time("Thu, 18 Nov 2010 11:27:35 GMT")
';
echo $a;
}
--- request
GET /lua
--- response_body
1290079655
=== TEST 4: parse_http_time in content_by_lua
--- config
location /lua {
content_by_lua '
ngx.say(ngx.parse_http_time("Thu, 18 Nov 2010 11:27:35 GMT"))
';
}
--- request
GET /lua
--- response_body
1290079655
=== TEST 5: bad arg for parse_http_time in content_by_lua
--- config
location /lua {
content_by_lua '
ngx.say(ngx.parse_http_time("abc") or "nil")
';
}
--- request
GET /lua
--- response_body
nil

View file

@ -1,137 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 3);
no_root_location();
no_long_string();
run_tests();
__DATA__
=== TEST 1: rewrite args (string with \r)
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("a\rb")
}
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/echo;
}
location /echo {
content_by_lua_block {
ngx.say(ngx.var.request_uri);
}
}
--- request
GET /foo?world
--- error_code: 200
--- response_body
/echo?a%0Db
=== TEST 2: rewrite args (string with \n)
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("a\nb")
}
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/echo;
}
location /echo {
content_by_lua_block {
ngx.say(ngx.var.request_uri);
}
}
--- request
GET /foo?world
--- response_body
/echo?a%0Ab
=== TEST 3: rewrite args (string with \0)
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("a\0b")
}
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/echo;
}
location /echo {
content_by_lua_block {
ngx.say(ngx.var.request_uri);
}
}
--- request
GET /foo?world
--- response_body
/echo?a%00b
=== TEST 4: rewrite args (string arg with 'lang=中文')
ngx.req.set_uri_args with string argument should be carefully encoded.
For backward compatibility, we are allowed to pass such parameters.
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("lang=中文")
}
content_by_lua_block {
ngx.say(ngx.var.arg_lang)
}
}
--- request
GET /foo?world
--- response_body
中文
--- no_error_log
[error]
=== TEST 5: rewrite args (string arg with '语言=chinese')
ngx.req.set_uri_args with string argument should be carefully encoded.
For backward compatibility, we are allowed to pass such parameters.
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("语言=chinese")
}
content_by_lua_block {
ngx.say(ngx.var.arg_语言)
}
}
--- request
GET /foo?world
--- response_body
chinese
--- no_error_log
[error]
=== TEST 6: rewrite args (string arg with '语言=中文')
ngx.req.set_uri_args with string argument should be carefully encoded.
For backward compatibility, we are allowed to pass such parameters.
--- config
location /foo {
rewrite_by_lua_block {
ngx.req.set_uri_args("语言=中文")
}
content_by_lua_block {
ngx.say(ngx.var.arg_语言)
}
}
--- request
GET /foo?world
--- response_body
中文
--- no_error_log
[error]

File diff suppressed because it is too large Load diff

View file

@ -1,407 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 6);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /lua {
lua_need_request_body on;
content_by_lua '
local args, err = ngx.req.get_post_args()
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request
POST /lua
a=3&b=4&c
--- response_body
a = 3
b = 4
c = true
=== TEST 2: lua_need_request_body off
--- config
location /lua {
lua_need_request_body off;
content_by_lua '
local args, err = ngx.req.get_post_args()
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request
POST /lua
a=3&b=4&c
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 3: empty request body
--- config
location /lua {
lua_need_request_body on;
content_by_lua '
local args, err = ngx.req.get_post_args()
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
local val = args[key]
if type(val) == "table" then
ngx.say(key, ": ", table.concat(val, ", "))
else
ngx.say(key, ": ", val)
end
end
';
}
--- request
POST /lua
--- response_body
--- skip_eval: 2:$ENV{TEST_NGINX_USE_HTTP3}
=== TEST 4: max args (limited after normal key=value)
--- config
location /lua {
content_by_lua '
ngx.req.read_body();
local args, err = ngx.req.get_post_args(2)
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request
POST /lua
foo=3&bar=4&baz=2
--- response_body
err: truncated
bar = 4
foo = 3
--- error_log
lua hit query args limit 2
=== TEST 5: max args (limited after an orphan key)
--- config
location /lua {
content_by_lua '
ngx.req.read_body();
local args, err = ngx.req.get_post_args(2)
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request
POST /lua
foo=3&bar&baz=2
--- response_body
err: truncated
bar = true
foo = 3
--- error_log
lua hit query args limit 2
=== TEST 6: max args (limited after an empty key, but non-empty values)
--- config
location /lua {
content_by_lua '
ngx.req.read_body();
local args, err = ngx.req.get_post_args(2)
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
ngx.say("done")
';
}
--- request
POST /lua
foo=3&=hello&=world
--- response_body
err: truncated
foo = 3
done
--- error_log
lua hit query args limit 2
=== TEST 7: default max 100 args
--- config
location /lua {
content_by_lua '
ngx.req.read_body();
local args, err = ngx.req.get_post_args()
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request eval
my $s = "POST /lua\n";
my $i = 1;
while ($i <= 102) {
if ($i != 1) {
$s .= '&';
}
$s .= "a$i=$i";
$i++;
}
$s
--- response_body eval
my @k;
my $i = 1;
while ($i <= 100) {
push @k, "a$i";
$i++;
}
@k = sort @k;
for my $k (@k) {
if ($k =~ /\d+/) {
$k .= " = $&\n";
}
}
"err: truncated\n" . CORE::join("", @k);
--- timeout: 4
--- error_log
lua hit query args limit 100
=== TEST 8: custom max 102 args
--- config
location /lua {
content_by_lua '
ngx.req.read_body()
local args, err = ngx.req.get_post_args(102)
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request eval
my $s = "POST /lua\n";
my $i = 1;
while ($i <= 103) {
if ($i != 1) {
$s .= '&';
}
$s .= "a$i=$i";
$i++;
}
$s
--- response_body eval
my @k;
my $i = 1;
while ($i <= 102) {
push @k, "a$i";
$i++;
}
@k = sort @k;
for my $k (@k) {
if ($k =~ /\d+/) {
$k .= " = $&\n";
}
}
"err: truncated\n" . CORE::join("", @k);
--- timeout: 4
--- error_log
lua hit query args limit 102
=== TEST 9: custom unlimited args
--- config
location /lua {
content_by_lua '
ngx.req.read_body()
local args, err = ngx.req.get_post_args(0)
if err then
ngx.say("err: ", err)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
';
}
--- request eval
my $s = "POST /lua\n";
my $i = 1;
while ($i <= 105) {
if ($i != 1) {
$s .= '&';
}
$s .= "a$i=$i";
$i++;
}
$s
--- response_body eval
my @k;
my $i = 1;
while ($i <= 105) {
push @k, "a$i";
$i++;
}
@k = sort @k;
for my $k (@k) {
if ($k =~ /\d+/) {
$k .= " = $&\n";
}
}
CORE::join("", @k);
--- timeout: 4
=== TEST 10: request body in temp file
--- config
location /lua {
lua_need_request_body on;
client_body_in_file_only clean;
content_by_lua_block {
local args, err = ngx.req.get_post_args()
if err then
ngx.say("err: ", err)
end
if args then
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
ngx.say(key, " = ", args[key])
end
end
}
}
--- request
POST /lua
a=3&b=4&c
--- response_body
err: request body in temp file not supported
--- no_error_log
[error]

View file

@ -1,78 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /lua {
content_by_lua '
local table = {"hello", nil, true, false, 32.5, 56}
ngx.say(table)
';
}
--- request
GET /lua
--- response_body
helloniltruefalse32.556
=== TEST 2: nested table
--- config
location /lua {
content_by_lua '
local table = {"hello", nil, true, false, 32.5, 56}
local table2 = {table, "--", table}
ngx.say(table2)
';
}
--- request
GET /lua
--- response_body
helloniltruefalse32.556--helloniltruefalse32.556
=== TEST 3: non-array table
--- config
location /lua {
content_by_lua '
local table = {foo = 3}
ngx.say(table)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
=== TEST 4: bad data type in table
--- config
location /lua {
content_by_lua '
local f = function () return end
local table = {1, 3, f}
ngx.say(table)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500

View file

@ -1,444 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 3 + 8);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /lua {
content_by_lua '
ngx.ctx.foo = 32;
ngx.say(ngx.ctx.foo)
';
}
--- request
GET /lua
--- response_body
32
--- no_error_log
[error]
=== TEST 2: rewrite, access, and content
--- config
location /lua {
rewrite_by_lua '
print("foo = ", ngx.ctx.foo)
ngx.ctx.foo = 76
';
access_by_lua '
ngx.ctx.foo = ngx.ctx.foo + 3
';
content_by_lua '
ngx.say(ngx.ctx.foo)
';
}
--- request
GET /lua
--- response_body
79
--- no_error_log
[error]
--- grep_error_log eval: qr/foo = [^,]+/
--- log_level: info
--- grep_error_log_out
foo = nil
=== TEST 3: interal redirect clears ngx.ctx
--- config
location /echo {
content_by_lua '
ngx.say(ngx.ctx.foo)
';
}
location /lua {
content_by_lua '
ngx.ctx.foo = ngx.var.arg_data
-- ngx.say(ngx.ctx.foo)
ngx.exec("/echo")
';
}
--- request
GET /lua?data=hello
--- response_body
nil
--- no_error_log
[error]
=== TEST 4: subrequest has its own ctx
--- config
location /sub {
content_by_lua '
ngx.say("sub pre: ", ngx.ctx.blah)
ngx.ctx.blah = 32
ngx.say("sub post: ", ngx.ctx.blah)
';
}
location /main {
content_by_lua '
ngx.ctx.blah = 73
ngx.say("main pre: ", ngx.ctx.blah)
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.say("main post: ", ngx.ctx.blah)
';
}
--- request
GET /main
--- response_body
main pre: 73
sub pre: nil
sub post: 32
main post: 73
--- no_error_log
[error]
=== TEST 5: overriding ctx
--- config
location /lua {
content_by_lua '
ngx.ctx = { foo = 32, bar = 54 };
ngx.say(ngx.ctx.foo)
ngx.say(ngx.ctx.bar)
ngx.ctx = { baz = 56 };
ngx.say(ngx.ctx.foo)
ngx.say(ngx.ctx.baz)
';
}
--- request
GET /lua
--- response_body
32
54
nil
56
--- no_error_log
[error]
=== TEST 6: header filter
--- config
location /lua {
content_by_lua '
ngx.ctx.foo = 32;
ngx.say(ngx.ctx.foo)
';
header_filter_by_lua '
ngx.header.blah = ngx.ctx.foo + 1
';
}
--- request
GET /lua
--- response_headers
blah: 33
--- response_body
32
--- no_error_log
[error]
=== TEST 7: capture_multi
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.ctx.dog)
';
}
location /lua {
set $dog 'blah';
set $cat 'foo';
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{"/other/1",
{ ctx = { dog = "hello" }}
},
{"/other/2",
{ ctx = { dog = "hiya" }}
}
};
ngx.print(res1.body)
ngx.print(res2.body)
ngx.say("parent: ", ngx.ctx.dog)
';
}
--- request
GET /lua
--- response_body
dog = hello
dog = hiya
parent: nil
--- no_error_log
[error]
=== TEST 8: set_by_lua
--- config
location /lua {
set_by_lua $bar 'ngx.ctx.foo = 3 return 4';
set_by_lua $foo 'return ngx.ctx.foo';
echo "foo = $foo, bar = $bar";
}
--- request
GET /lua
--- response_body
foo = 3, bar = 4
--- no_error_log
[error]
=== TEST 9: ngx.ctx leaks with ngx.exec + log_by_lua
--- config
location = /t {
content_by_lua '
ngx.ctx.foo = 32;
ngx.exec("/f")
';
log_by_lua 'ngx.log(ngx.WARN, "ctx.foo = ", ngx.ctx.foo)';
}
location = /f {
content_by_lua '
ngx.say(ngx.ctx.foo)
';
}
--- request
GET /t
--- response_body
nil
--- no_error_log
[error]
ctx.foo =
=== TEST 10: memory leaks with ngx.ctx + ngx.req.set_uri + log_by_lua
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = 32;
ngx.req.set_uri("/f", true)
';
log_by_lua 'ngx.log(ngx.WARN, "ctx.foo = ", ngx.ctx.foo)';
}
location = /f {
content_by_lua '
ngx.say(ngx.ctx.foo)
';
}
--- request
GET /t
--- response_body
nil
--- no_error_log
[error]
ctx.foo =
=== TEST 11: ngx.ctx + ngx.exit(ngx.ERROR) + log_by_lua
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = 32;
ngx.exit(ngx.ERROR)
';
log_by_lua 'ngx.log(ngx.WARN, "ngx.ctx = ", ngx.ctx.foo)';
}
--- request
GET /t
--- ignore_response
--- no_error_log
[error]
--- error_log
ngx.ctx = 32
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 12: ngx.ctx + ngx.exit(200) + log_by_lua
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = 32;
ngx.say(ngx.ctx.foo)
ngx.exit(200)
';
log_by_lua 'ngx.log(ngx.WARN, "ctx.foo = ", ngx.ctx.foo)';
}
--- request
GET /t
--- response_body
32
--- no_error_log
[error]
--- error_log
ctx.foo = 32
=== TEST 13: ngx.ctx + ngx.redirect + log_by_lua
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = 32;
ngx.redirect("/f")
';
log_by_lua 'ngx.log(ngx.WARN, "ngx.ctx.foo = ", 32)';
}
--- request
GET /t
--- response_body_like: 302 Found
--- error_code: 302
--- error_log
ctx.foo = 32
--- no_error_log
[error]
=== TEST 14: set ngx.ctx before internal redirects performed by other nginx modules
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = "hello world";
';
echo_exec /foo;
}
location = /foo {
echo hello;
}
--- request
GET /t
--- response_body
hello
--- no_error_log
[error]
--- log_level: debug
--- error_log
lua release ngx.ctx at ref
=== TEST 15: set ngx.ctx before internal redirects performed by other nginx modules (with log_by_lua)
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = "hello world";
';
echo_exec /foo;
}
location = /foo {
echo hello;
log_by_lua return;
}
--- request
GET /t
--- response_body
hello
--- no_error_log
[error]
--- log_level: debug
--- error_log
lua release ngx.ctx at ref
=== TEST 16: set ngx.ctx before simple uri rewrite performed by other nginx modules
--- config
location = /t {
set_by_lua $a 'ngx.ctx.foo = "hello world"; return 1';
rewrite ^ /foo last;
echo blah;
}
location = /foo {
echo foo;
}
--- request
GET /t
--- response_body
foo
--- no_error_log
[error]
--- log_level: debug
--- error_log
lua release ngx.ctx at ref
=== TEST 17: ngx.ctx gets prematurely released ngx.exit()
--- config
location = /t {
rewrite_by_lua '
ngx.ctx.foo = 3
';
content_by_lua '
-- if ngx.headers_sent ~= true then ngx.send_headers() end
return ngx.exit(200)
';
header_filter_by_lua '
if ngx.ctx.foo ~= 3 then
ngx.log(ngx.ERR, "bad ngx.ctx.foo: ", ngx.ctx.foo)
end
';
}
--- request
GET /t
--- response_body
--- no_error_log
[error]
=== TEST 18: ngx.ctx gets prematurely released ngx.exit() (lua_code_cache off)
--- config
location = /t {
lua_code_cache off;
rewrite_by_lua '
ngx.ctx.foo = 3
';
content_by_lua '
-- if ngx.headers_sent ~= true then ngx.send_headers() end
return ngx.exit(200)
';
header_filter_by_lua '
if ngx.ctx.foo ~= 3 then
ngx.log(ngx.ERR, "bad ngx.ctx.foo: ", ngx.ctx.foo)
end
';
}
--- request
GET /t
--- response_body
--- no_error_log
[error]

File diff suppressed because it is too large Load diff

View file

@ -1,916 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(5);
plan tests => repeat_each() * (blocks() * 2 + 7);
our $HtmlDir = html_dir;
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: gmatch
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, world", "[a-z]+") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hello
world
=== TEST 2: fail to match
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[0-9]")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
nil
nil
nil
=== TEST 3: match but iterate more times (not just match at the end)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world!", "[a-z]+")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
hello
world
nil
nil
=== TEST 4: match but iterate more times (just matched at the end)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
hello
world
nil
nil
=== TEST 5: anchored match (failed)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, 1234", "([0-9]+)", "a")
ngx.say(it())
';
}
--- request
GET /re
--- response_body
nil
=== TEST 6: anchored match (succeeded)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("12 hello 34", "[0-9]", "a")
local m = it()
ngx.say(m[0])
m = it()
ngx.say(m[0])
ngx.say(it())
';
}
--- request
GET /re
--- response_body
1
2
nil
=== TEST 7: non-anchored gmatch (without regex cache)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("12 hello 34", "[0-9]")
local m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1
2
3
4
nil
=== TEST 8: non-anchored gmatch (with regex cache)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("12 hello 34", "[0-9]", "o")
local m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
m = it()
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1
2
3
4
nil
=== TEST 9: anchored match (succeeded)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("12 hello 34", "[0-9]", "a")
local m = it()
ngx.say(m[0])
m = it()
ngx.say(m[0])
ngx.say(it())
';
}
--- request
GET /re
--- response_body
1
2
nil
=== TEST 10: anchored match (succeeded, set_by_lua)
--- config
location /re {
set_by_lua $res '
local it = ngx.re.gmatch("12 hello 34", "[0-9]", "a")
local m = it()
return m[0]
';
echo $res;
}
--- request
GET /re
--- response_body
1
=== TEST 11: gmatch (look-behind assertion)
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("{foobar}, {foobaz}", "(?<=foo)ba[rz]") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
bar
baz
=== TEST 12: gmatch (look-behind assertion 2)
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
bar
baz
=== TEST 13: with regex cache
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, 1234", "([A-Z]+)", "io")
local m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("1234, okay", "([A-Z]+)", "io")
m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("hi, 1234", "([A-Z]+)", "o")
m = it()
ngx.say(m and m[0])
';
}
--- request
GET /re
--- stap2
F(ngx_http_lua_ngx_re_gmatch_iterator) { println("iterator") }
F(ngx_http_lua_ngx_re_gmatch_gc) { println("gc") }
F(ngx_http_lua_ngx_re_gmatch_cleanup) { println("cleanup") }
--- response_body
hello
okay
nil
=== TEST 14: exceeding regex cache max entries
--- http_config
lua_regex_cache_max_entries 2;
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, 1234", "([0-9]+)", "o")
local m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("howdy, 567", "([0-9]+)", "oi")
m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("hiya, 98", "([0-9]+)", "ox")
m = it()
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1234
567
98
=== TEST 15: disable regex cache completely
--- http_config
lua_regex_cache_max_entries 0;
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, 1234", "([0-9]+)", "o")
local m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("howdy, 567", "([0-9]+)", "oi")
local m = it()
ngx.say(m and m[0])
it = ngx.re.gmatch("hiya, 98", "([0-9]+)", "ox")
local m = it()
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1234
567
98
=== TEST 16: gmatch matched but no iterate
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+")
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
=== TEST 17: gmatch matched but only iterate once and still matches remain
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /re
--- response_body
hello
=== TEST 18: gmatch matched but no iterate and early forced GC
--- config
location /re {
content_by_lua '
local a = {}
for i = 1, 3 do
local it = ngx.re.gmatch("hello, world", "[a-z]+")
it()
collectgarbage()
table.insert(a, {"hello", "world"})
end
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
=== TEST 19: gmatch iterator used by another request
--- http_config eval
"lua_package_path '$::HtmlDir/?.lua;;';"
--- config
location /main {
content_by_lua '
package.loaded.foo = nil
collectgarbage()
local res = ngx.location.capture("/t")
if res.status == 200 then
ngx.print(res.body)
else
ngx.say("sr failed: ", res.status)
end
res = ngx.location.capture("/t")
if res.status == 200 then
ngx.print(res.body)
else
ngx.say("sr failed: ", res.status)
end
';
}
location /t {
content_by_lua '
local foo = require "foo"
local m = foo.go()
ngx.say(m and "matched" or "no")
';
}
--- user_files
>>> foo.lua
module("foo", package.seeall)
local it
function go()
if not it then
it = ngx.re.gmatch("hello, world", "[a-z]+")
end
return it()
end
--- request
GET /main
--- response_body
matched
matched
--- no_error_log
[error]
=== TEST 20: gmatch (empty matched string)
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello", "a|") do
if m then
ngx.say("matched: [", m[0], "]")
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
matched: []
matched: []
matched: []
matched: []
matched: []
matched: []
=== TEST 21: gmatch with named pattern
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("1234, 1234", "(?<first>[0-9]+)")
local m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m["first"])
else
ngx.say("not matched!")
end
m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m["first"])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
1234
1234
1234
1234
1234
=== TEST 22: gmatch with multiple named pattern
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("1234, abcd, 1234", "(?<first>[0-9]+)|(?<second>[a-z]+)")
local m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(m["first"])
ngx.say(m["second"])
else
ngx.say("not matched!")
end
m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(m["first"])
ngx.say(m["second"])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
1234
false
1234
false
abcd
false
abcd
false
abcd
=== TEST 23: gmatch with duplicate named pattern w/ extraction
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, 1234", "(?<first>[a-z]+), (?<first>[0-9]+)", "D")
local m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(table.concat(m.first,"-"))
else
ngx.say("not matched!")
end
m = it()
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(table.concat(m.first,"-"))
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hello, 1234
hello
1234
hello-1234
not matched!
=== TEST 24: named captures are empty
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("1234", "(?<first>[a-z]*)([0-9]+)", "")
local m = it()
if m then
ngx.say(m[0])
ngx.say(m.first)
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
1234
=== TEST 25: named captures are empty (with regex cache)
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("1234", "(?<first>[a-z]*)([0-9]+)", "o")
local m = it()
if m then
ngx.say(m[0])
ngx.say(m.first)
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
1234
=== TEST 26: bad pattern
--- config
location /re {
content_by_lua '
local it, err = ngx.re.gmatch("hello\\nworld", "(abc")
if not err then
ngx.say("good")
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 27: bad UTF-8
--- config
location = /t {
content_by_lua '
local target = "你好"
local regex = "你好"
-- Note the D here
local it, err = ngx.re.gmatch(string.sub(target, 1, 4), regex, "u")
if err then
ngx.say("error: ", err)
return
end
local m, err = it()
if err then
ngx.say("error: ", err)
return
end
if m then
ngx.say("matched: ", m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /t
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre_exec\(\) failed: -4\n"
:
"error: pcre_exec\(\) failed: -10\n"
--- no_error_log
[error]
=== TEST 28: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("你好", ".", "U")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
--- request
GET /re
--- response_body
--- no_error_log
[error]
=== TEST 29: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("你好", ".", "u")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
--- request
GET /re
--- response_body
--- no_error_log
[error]
=== TEST 30: just hit match limit
--- http_config
lua_regex_match_limit 5000;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local it, err = ngx.re.gmatch(s, re, "o")
if not it then
ngx.say("failed to gen iterator: ", err)
return
end
local res, err = it()
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if not res then
if err then
ngx.say("error: ", err)
return
end
ngx.say("failed to match")
return
end
--- request
GET /re
--- response_body eval
# lua_regex_match_limit uses pcre_extra->match_limit in the PCRE,
# but PCRE2 replaces this with pcre2_set_match_limit interface,
# which has different effects.
$Test::Nginx::Util::PcreVersion == 2 ?
"failed to match\n"
:
"error: pcre_exec() failed: -8\n"
=== TEST 31: just not hit match limit
--- http_config
lua_regex_match_limit 5100;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local it, err = ngx.re.gmatch(s, re, "o")
if not it then
ngx.say("failed to gen iterator: ", err)
return
end
local res, err = it()
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if not res then
if err then
ngx.say("error: ", err)
return
end
ngx.say("failed to match")
return
end
--- request
GET /re
--- response_body
failed to match

View file

@ -1,769 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 19);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched but w/o variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "howdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
howdy, world
1
=== TEST 2: not matched
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[A-Z]+", "howdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, world
0
=== TEST 3: matched and with variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", "(b) (c)", "[$0] [$1] [$2] [$3] [$134]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] [] [] d
1
=== TEST 4: matched and with named variables
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("a b c d",
"(b) (c)", "[$0] [$1] [$2] [$3] [$hello]")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
attempt to use named capturing variable "hello" (named captures not supported yet)
=== TEST 5: matched and with named variables (bracketed)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("a b c d",
"(b) (c)", "[$0] [$1] [$2] [$3] [${hello}]")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
attempt to use named capturing variable "hello" (named captures not supported yet)
=== TEST 6: matched and with bracketed variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134}]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[b c] [b] [c] [] [] d
1
=== TEST 7: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134]")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
the closing bracket in "134" variable is missing
=== TEST 8: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
the closing bracket in "134" variable is missing
=== TEST 9: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
lua script: invalid capturing variable name found in "[$0] [$1] [${2}] [$3] [${"
=== TEST 10: trailing $
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [$")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
lua script: invalid capturing variable name found in "[$0] [$1] [${2}] [$3] [$"
=== TEST 11: matched but w/o variables and with literal $
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "ho$$wdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
ho$wdy, world
1
=== TEST 12: non-anchored match
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "[0-9]", "x")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, x234
1
=== TEST 13: anchored match
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "[0-9]", "x", "a")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, 1234
0
=== TEST 14: function replace
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.sub("hello, 34", "([0-9])", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, [3] [3]4
1
=== TEST 15: function replace (failed)
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.sub("hello, 34", "([A-Z])", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, 34
0
=== TEST 16: bad repl arg type
--- config
location /re {
content_by_lua '
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([A-Z])", true)
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
false
bad argument #3 to '?' (string, number, or function expected, got boolean)
nil
--- SKIP
=== TEST 17: use number to replace
--- config
location /re {
content_by_lua '
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([0-9])", 72)
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
true
hello, 724
1
=== TEST 18: bad function return value type
--- SKIP
--- config
location /re {
content_by_lua '
local f = function (m) end
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([0-9])", f)
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
false
bad argument #3 to '?' (string or number expected to be returned by the replace function, got nil)
nil
=== TEST 19: matched but w/o variables (set_by_lua)
--- config
location /re {
set_by_lua $res '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "howdy")
return s
';
echo $res;
}
--- request
GET /re
--- response_body
howdy, world
=== TEST 20: matched and with variables w/o using named patterns in sub
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", "(?<first>b) (?<second>c)", "[$0] [$1] [$2] [$3] [$134]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] [] [] d
1
=== TEST 21: matched and with variables using named patterns in func
--- config
error_log /tmp/nginx_error debug;
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m["first"] .. "] [" .. m[2] .. "]"
end
local s, n = ngx.re.sub("a b c d", "(?<first>b) (?<second>c)", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] d
1
--- no_error_log
[error]
[alert]
--- timeout: 5
=== TEST 22: matched and with variables w/ using named patterns in sub
This is still a TODO
--- SKIP
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", "(?<first>b) (?<second>c)", "[$0] [${first}] [${second}] [$3] [$134]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] [] [] d
1
--- no_error_log
[error]
=== TEST 23: $0 without parens
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", [[\w]], "[$0]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[a] b c d
1
--- no_error_log
[error]
=== TEST 24: bad pattern
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("hello\\nworld", "(abc", "")
if s then
ngx.say("subs: ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 25: bad UTF-8
--- config
location = /t {
content_by_lua '
local target = "你好"
local regex = "你好"
-- Note the D here
local s, n, err = ngx.re.sub(string.sub(target, 1, 4), regex, "", "u")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /t
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre_exec\(\) failed: -4\n"
:
"error: pcre_exec\(\) failed: -10\n"
--- no_error_log
[error]
=== TEST 26: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("你好", ".", "a", "U")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
--- request
GET /re
--- response_body
s: a好
--- no_error_log
[error]
=== TEST 27: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("你好", ".", "a", "u")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
--- request
GET /re
--- response_body
s: a好
--- no_error_log
[error]
=== TEST 28: just hit match limit
--- http_config
lua_regex_match_limit 5000;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local res, cnt, err = ngx.re.sub(s, re, "", "o")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if err then
ngx.say("error: ", err)
return
end
ngx.say("sub: ", cnt)
--- request
GET /re
--- response_body eval
# lua_regex_match_limit uses pcre_extra->match_limit in the PCRE,
# but PCRE2 replaces this with pcre2_set_match_limit interface,
# which has different effects.
$Test::Nginx::Util::PcreVersion == 2 ?
"sub: 0\n"
:
"error: pcre_exec() failed: -8\n"
=== TEST 29: just not hit match limit
--- http_config
lua_regex_match_limit 5100;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local res, cnt, err = ngx.re.sub(s, re, "", "o")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if err then
ngx.say("error: ", err)
return
end
ngx.say("sub: ", cnt)
--- request
GET /re
--- response_body
sub: 0
=== TEST 30: bug: sub incorrectly swallowed a character is the first character
Original bad result: estCase
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("TestCase", "^ *", "", "o")
if s then
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
TestCase
=== TEST 31: bug: sub incorrectly swallowed a character is not the first character
Original bad result: .b.d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("abcd", "(?=c)", ".")
if s then
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
ab.cd
=== TEST 32: ngx.re.gsub: recursive calling (github #445)
--- config
location = /t {
content_by_lua '
local function test()
local data = [[
OUTER {FIRST}
]]
local p1 = "(OUTER)(.+)"
local p2 = "{([A-Z]+)}"
ngx.print(data)
local res = ngx.re.gsub(data, p1, function(m)
-- ngx.say("pre: m[1]: [", m[1], "]")
-- ngx.say("pre: m[2]: [", m[2], "]")
local res = ngx.re.gsub(m[2], p2, function(_)
return "REPLACED"
end, "")
-- ngx.say("post: m[1]: [", m[1], "]")
-- ngx.say("post m[2]: [", m[2], "]")
return m[1] .. res
end, "")
ngx.print(res)
end
test()
';
}
--- request
GET /t
--- response_body
OUTER {FIRST}
OUTER REPLACED
--- no_error_log
[error]
bad argument type
NYI
=== TEST 33: function replace (false for groups)
--- config
location /re {
content_by_lua '
local repl = function (m)
print("group 1: ", m[2])
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.sub("hello, 34", "([0-9])|(world)", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, [3] [3]4
1
--- error_log
group 1: false

View file

@ -1,708 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 17);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("[hello, world]", "[a-z]+", "howdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[howdy, howdy]
2
=== TEST 2: trimmed
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[a-z]+", "howdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
howdy, howdy
2
=== TEST 3: not matched
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[A-Z]+", "howdy")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, world
0
=== TEST 4: replace by function (trimmed)
--- config
location /re {
content_by_lua '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("hello, world", "([a-z])[a-z]+", f)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2
=== TEST 5: replace by function (not trimmed)
--- config
location /re {
content_by_lua '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", f)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
2
=== TEST 6: replace by script (trimmed)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "([a-z])[a-z]+", "[$0,$1]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2
=== TEST 7: replace by script (not trimmed)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", "[$0,$1]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
2
=== TEST 8: set_by_lua
--- config
location /re {
set_by_lua $res '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", f)
return s
';
echo $res;
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
=== TEST 9: look-behind assertion
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "h$0")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{foohbarhbaz}
2
=== TEST 10: gsub with a patch matching an empty substring (string template)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello", "a|", "b")
ngx.say("s: ", s)
ngx.say("n: ", n)
';
}
--- request
GET /re
--- response_body
s: bhbeblblbob
n: 6
--- no_error_log
[error]
=== TEST 11: gsub with a patch matching an empty substring (string template, empty subj)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("", "a|", "b")
ngx.say("s: ", s)
ngx.say("n: ", n)
';
}
--- request
GET /re
--- response_body
s: b
n: 1
--- no_error_log
[error]
=== TEST 12: gsub with a patch matching an empty substring (func)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello", "a|", function () return "b" end)
ngx.say("s: ", s)
ngx.say("n: ", n)
';
}
--- request
GET /re
--- response_body
s: bhbeblblbob
n: 6
--- no_error_log
[error]
=== TEST 13: gsub with a patch matching an empty substring (func, empty subj)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("", "a|", function () return "b" end)
ngx.say("s: ", s)
ngx.say("n: ", n)
';
}
--- request
GET /re
--- response_body
s: b
n: 1
--- no_error_log
[error]
=== TEST 14: big subject string exceeding the luabuf chunk size (with trailing unmatched data, func repl)
--- config
location /re {
content_by_lua '
local subj = string.rep("a", 8000)
.. string.rep("b", 1000)
.. string.rep("a", 8000)
.. string.rep("b", 1000)
.. "aaa"
local function repl(m)
return string.rep("c", string.len(m[0]))
end
local s, n = ngx.re.gsub(subj, "b+", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body eval
("a" x 8000) . ("c" x 1000) . ("a" x 8000) . ("c" x 1000)
. "aaa
2
"
--- no_error_log
[error]
=== TEST 15: big subject string exceeding the luabuf chunk size (without trailing unmatched data, func repl)
--- config
location /re {
content_by_lua '
local subj = string.rep("a", 8000)
.. string.rep("b", 1000)
.. string.rep("a", 8000)
.. string.rep("b", 1000)
local function repl(m)
return string.rep("c", string.len(m[0]))
end
local s, n = ngx.re.gsub(subj, "b+", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body eval
("a" x 8000) . ("c" x 1000) . ("a" x 8000) . ("c" x 1000)
. "\n2\n"
--- no_error_log
[error]
=== TEST 16: big subject string exceeding the luabuf chunk size (with trailing unmatched data, str repl)
--- config
location /re {
content_by_lua '
local subj = string.rep("a", 8000)
.. string.rep("b", 1000)
.. string.rep("a", 8000)
.. string.rep("b", 1000)
.. "aaa"
local s, n = ngx.re.gsub(subj, "b(b+)(b)", "$1 $2")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body eval
("a" x 8000) . ("b" x 998) . " b" . ("a" x 8000) . ("b" x 998) . " baaa
2
"
--- no_error_log
[error]
=== TEST 17: big subject string exceeding the luabuf chunk size (without trailing unmatched data, str repl)
--- config
location /re {
content_by_lua '
local subj = string.rep("a", 8000)
.. string.rep("b", 1000)
.. string.rep("a", 8000)
.. string.rep("b", 1000)
local s, n = ngx.re.gsub(subj, "b(b+)(b)", "$1 $2")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body eval
("a" x 8000) . ("b" x 998) . " b" . ("a" x 8000) . ("b" x 998) . " b\n2\n"
--- no_error_log
[error]
=== TEST 18: named pattern repl w/ callback
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "," .. m["first"] .. "]"
end
local s, n = ngx.re.gsub("hello, world", "(?<first>[a-z])[a-z]+", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2
=== TEST 19: $0 without parens
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("a b c d", [[\w]], "[$0]")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[a] [b] [c] [d]
4
--- no_error_log
[error]
=== TEST 20: bad UTF-8
--- config
location = /t {
content_by_lua '
local target = "你好"
local regex = "你好"
-- Note the D here
local s, n, err = ngx.re.gsub(string.sub(target, 1, 4), regex, "", "u")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /t
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre_exec\(\) failed: -4\n"
:
"error: pcre_exec\(\) failed: -10\n"
--- no_error_log
[error]
=== TEST 21: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("你好", ".", "a", "U")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
exec opts: 2000
exec opts: 2000
--- request
GET /re
--- response_body
s: aa
--- no_error_log
[error]
=== TEST 22: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("你好", ".", "a", "u")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
exec opts: 0
exec opts: 0
--- request
GET /re
--- response_body
s: aa
--- no_error_log
[error]
=== TEST 23: just hit match limit
--- http_config
lua_regex_match_limit 5000;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local res, cnt, err = ngx.re.gsub(s, re, "", "o")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if err then
ngx.say("error: ", err)
return
end
ngx.say("gsub: ", cnt)
--- request
GET /re
--- response_body eval
# lua_regex_match_limit uses pcre_extra->match_limit in the PCRE,
# but PCRE2 replaces this with pcre2_set_match_limit interface,
# which has different effects.
$Test::Nginx::Util::PcreVersion == 2 ?
"gsub: 0\n"
:
"error: pcre_exec() failed: -8\n"
=== TEST 24: just not hit match limit
--- http_config
lua_regex_match_limit 5100;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 10)
local start = ngx.now()
local res, cnt, err = ngx.re.gsub(s, re, "", "o")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if err then
ngx.say("error: ", err)
return
end
ngx.say("gsub: ", cnt)
--- request
GET /re
--- response_body
gsub: 0
--- timeout: 10
=== TEST 25: bug: gsub incorrectly swallowed a character is the first character
Original bad result: estCase
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("TestCase", "^ *", "", "o")
if s then
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
TestCase
=== TEST 26: bug: gsub incorrectly swallowed a character is not the first character
Original bad result: .b.d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("abcd", "a|(?=c)", ".")
if s then
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
.b.cd
=== TEST 27: use of ngx.req.get_headers in the user callback
--- config
location = /t {
content_by_lua '
local data = [[
INNER
INNER
]]
-- ngx.say(data)
local res = ngx.re.gsub(data, "INNER", function(inner_matches)
local header = ngx.req.get_headers()["Host"]
-- local header = ngx.var["http_HEADER"]
return "INNER_REPLACED"
end, "s")
ngx.print(res)
';
}
--- request
GET /t
--- response_body
INNER_REPLACED
INNER_REPLACED
--- no_error_log
[error]
=== TEST 28: use of ngx.var in the user callback
--- config
location = /t {
content_by_lua '
local data = [[
INNER
INNER
]]
-- ngx.say(data)
local res = ngx.re.gsub(data, "INNER", function(inner_matches)
-- local header = ngx.req.get_headers()["Host"]
local header = ngx.var["http_HEADER"]
return "INNER_REPLACED"
end, "s")
ngx.print(res)
';
}
--- request
GET /t
--- response_body
INNER_REPLACED
INNER_REPLACED
--- no_error_log
[error]
=== TEST 29: function replace (false for groups)
--- config
location /re {
content_by_lua '
local repl = function (m)
print("group 1: ", m[2])
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.gsub("hello, 34", "([0-9])|(world)", repl)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, [3] [3][4] [4]
2
--- error_log
group 1: false

View file

@ -1,745 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 3);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
=== TEST 2: escaping sequences
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "(\\\\d+)", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
=== TEST 3: escaping sequences (bad)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "(\\d+)", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
[qr/invalid escape sequence near '"\('/]
=== TEST 4: escaping sequences in [[ ... ]]
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "[[\\d+]]", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log eval
[qr/invalid escape sequence near '"\[\['/]
=== TEST 5: single capture
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]{2})[0-9]+", "o")
if m then
ngx.say(m[0])
ngx.say(m[1])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
12
=== TEST 6: multiple captures
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([a-z]+).*?([0-9]{2})[0-9]+", "o")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hello, 1234
hello
12
=== TEST 7: not matched
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "foo", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
not matched: nil
=== TEST 8: case sensitive by default
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "HELLO", "o")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
not matched: nil
=== TEST 9: case sensitive by default
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "HELLO", "oi")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
hello
=== TEST 10: UTF-8 mode
--- config
location /re {
content_by_lua '
local rc, m = pcall(ngx.re.match, "hello章亦春", "HELLO.{2}", "iou")
if not rc then
ngx.say("error: ", m)
return
end
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body_like chop
this version of PCRE is not compiled with PCRE_UTF8 support|^hello章亦$
=== TEST 11: multi-line mode (^ at line head)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello\\nworld", "^world", "mo")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
world
=== TEST 12: multi-line mode (. does not match \n)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello\\nworld", ".*", "om")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
hello
=== TEST 13: single-line mode (^ as normal)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello\\nworld", "^world", "so")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
not matched: nil
=== TEST 14: single-line mode (dot all)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello\\nworld", ".*", "os")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
hello
world
=== TEST 15: extended mode (ignore whitespaces)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello\\nworld", "\\\\w \\\\w", "xo")
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
he
=== TEST 16: bad pattern
--- config
location /re {
content_by_lua '
local m, err = ngx.re.match("hello\\nworld", "(abc", "o")
if m then
ngx.say(m[0])
else
if err then
ngx.say("error: ", err)
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 17: bad option
--- config
location /re {
content_by_lua '
local rc, m = pcall(ngx.re.match, "hello\\nworld", ".*", "Ho")
if rc then
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
else
ngx.say("error: ", m)
end
';
}
--- request
GET /re
--- response_body_like chop
^error: .*?unknown flag "H"
=== TEST 18: extended mode (ignore whitespaces)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, world", "(world)|(hello)", "xo")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched: ", m)
end
';
}
--- request
GET /re
--- response_body
hello
false
hello
=== TEST 19: optional trailing captures
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)(h?)", "o")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body eval
"1234
1234
"
=== TEST 20: anchored match (failed)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "oa")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
not matched!
=== TEST 21: anchored match (succeeded)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("1234, hello", "([0-9]+)", "ao")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
=== TEST 22: match with ctx but no pos
--- config
location /re {
content_by_lua '
local ctx = {}
local m = ngx.re.match("1234, hello", "([0-9]+)", "o", ctx)
if m then
ngx.say(m[0])
ngx.say(ctx.pos)
else
ngx.say("not matched!")
ngx.say(ctx.pos)
end
';
}
--- request
GET /re
--- response_body
1234
5
=== TEST 23: match with ctx and a pos
--- config
location /re {
content_by_lua '
local ctx = { pos = 3 }
local m = ngx.re.match("1234, hello", "([0-9]+)", "o", ctx)
if m then
ngx.say(m[0])
ngx.say(ctx.pos)
else
ngx.say("not matched!")
ngx.say(ctx.pos)
end
';
}
--- request
GET /re
--- response_body
34
5
=== TEST 24: sanity (set_by_lua)
--- config
location /re {
set_by_lua $res '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "o")
if m then
return m[0]
else
return "not matched!"
end
';
echo $res;
}
--- request
GET /re
--- response_body
1234
=== TEST 25: match (look-behind assertion)
--- config
location /re {
content_by_lua '
local ctx = {}
local m = ngx.re.match("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "o", ctx)
ngx.say(m and m[0])
m = ngx.re.match("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "o", ctx)
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
bar
baz
=== TEST 26: match (with regex cache)
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([A-Z]+)", "io")
ngx.say(m and m[0])
m = ngx.re.match("1234, okay", "([A-Z]+)", "io")
ngx.say(m and m[0])
m = ngx.re.match("hello, 1234", "([A-Z]+)", "o")
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
hello
okay
nil
=== TEST 27: match (with regex cache and ctx)
--- config
location /re {
content_by_lua '
local ctx = {}
local m = ngx.re.match("hello, 1234", "([A-Z]+)", "io", ctx)
ngx.say(m and m[0])
ngx.say(ctx.pos)
m = ngx.re.match("1234, okay", "([A-Z]+)", "io", ctx)
ngx.say(m and m[0])
ngx.say(ctx.pos)
ctx.pos = 1
m = ngx.re.match("hi, 1234", "([A-Z]+)", "o", ctx)
ngx.say(m and m[0])
ngx.say(ctx.pos)
';
}
--- request
GET /re
--- response_body
hello
6
okay
11
nil
1
=== TEST 28: exceeding regex cache max entries
--- http_config
lua_regex_cache_max_entries 2;
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "o")
ngx.say(m and m[0])
m = ngx.re.match("howdy, 567", "([0-9]+)", "oi")
ngx.say(m and m[0])
m = ngx.re.match("hiya, 98", "([0-9]+)", "ox")
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1234
567
98
=== TEST 29: disable regex cache completely
--- http_config
lua_regex_cache_max_entries 0;
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "o")
ngx.say(m and m[0])
m = ngx.re.match("howdy, 567", "([0-9]+)", "oi")
ngx.say(m and m[0])
m = ngx.re.match("hiya, 98", "([0-9]+)", "ox")
ngx.say(m and m[0])
';
}
--- request
GET /re
--- response_body
1234
567
98
=== TEST 30: named subpatterns w/ extraction
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "(?<first>[a-z]+), [0-9]+", "o")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m.first)
ngx.say(m.second)
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hello, 1234
hello
hello
nil
=== TEST 31: duplicate named subpatterns w/ extraction
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "(?<first>[a-z]+), (?<first>[0-9]+)", "Do")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(table.concat(m.first,"-"))
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hello, 1234
hello
1234
hello-1234
=== TEST 32: named captures are empty strings
--- config
location /re {
content_by_lua '
local m = ngx.re.match("1234", "(?<first>[a-z]*)([0-9]+)", "o")
if m then
ngx.say(m[0])
ngx.say(m.first)
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
1234
=== TEST 33: named captures are false
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, world", "(world)|(hello)|(?<named>howdy)", "o")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
ngx.say(m[3])
ngx.say(m["named"])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hello
false
hello
false
false

View file

@ -1,580 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 6);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched but w/o variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "howdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
howdy, world
1
=== TEST 2: not matched
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[A-Z]+", "howdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, world
0
=== TEST 3: matched and with variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", "(b) (c)", "[$0] [$1] [$2] [$3] [$134]", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] [] [] d
1
=== TEST 4: matched and with named variables (bad template)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("a b c d",
"(b) (c)",
"[$0] [$1] [$2] [$3] [$hello]",
"o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
attempt to use named capturing variable "hello" (named captures not supported yet)
=== TEST 5: matched and with named variables (bracketed)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("a b c d",
"(b) (c)",
"[$0] [$1] [$2] [$3] [${hello}]",
"o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
attempt to use named capturing variable "hello" (named captures not supported yet)
=== TEST 6: matched and with bracketed variables
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134}]", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[b c] [b] [c] [] [] d
1
=== TEST 7: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134]", "o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
the closing bracket in "134" variable is missing
=== TEST 8: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${134", "o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
the closing bracket in "134" variable is missing
=== TEST 9: matched and with bracketed variables (unmatched brackets)
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [${", "o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
lua script: invalid capturing variable name found in "[$0] [$1] [${2}] [$3] [${"
=== TEST 10: trailing $
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("b c d", "(b) (c)", "[$0] [$1] [${2}] [$3] [$", "o")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body
error: failed to compile the replacement template
--- error_log
lua script: invalid capturing variable name found in "[$0] [$1] [${2}] [$3] [$"
=== TEST 11: matched but w/o variables and with literal $
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "ho$$wdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
ho$wdy, world
1
=== TEST 12: non-anchored match
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", " [0-9] ", "x", "xo")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, x234
1
=== TEST 13: anchored match
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "[0-9]", "x", "ao")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, 1234
0
=== TEST 14: function replace
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.sub("hello, 34", "([0-9])", repl, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, [3] [3]4
1
=== TEST 15: function replace (failed)
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m[1] .. "]"
end
local s, n = ngx.re.sub("hello, 34", "([A-Z])", repl, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, 34
0
=== TEST 16: bad repl arg type
--- SKIP
--- config
location /re {
content_by_lua '
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([A-Z])", true, "o")
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
false
bad argument #3 to '?' (string, number, or function expected, got boolean)
nil
=== TEST 17: use number to replace
--- config
location /re {
content_by_lua '
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([0-9])", 72, "o")
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
true
hello, 724
1
=== TEST 18: bad function return value type
--- SKIP
--- config
location /re {
content_by_lua '
local f = function (m) end
local rc, s, n = pcall(ngx.re.sub, "hello, 34", "([0-9])", f, "o")
ngx.say(rc)
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
false
bad argument #3 to '?' (string or number expected to be returned by the replace function, got nil)
nil
=== TEST 19: matched but w/o variables (set_by_lua)
--- config
location /re {
set_by_lua $res '
local s, n = ngx.re.sub("hello, world", "[a-z]+", "howdy", "o")
return s
';
echo $res;
}
--- request
GET /re
--- response_body
howdy, world
=== TEST 20: with regex cache (with text replace)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "([A-Z]+)", "baz", "io")
ngx.say(s)
ngx.say(n)
local s, n = ngx.re.sub("howdy, 1234", "([A-Z]+)", "baz", "io")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("1234, okay", "([A-Z]+)", "blah", "io")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("hi, 1234", "([A-Z]+)", "hello", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
baz, 1234
1
baz, 1234
1
1234, blah
1
hi, 1234
0
=== TEST 21: with regex cache (with func replace)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "([A-Z]+)", "baz", "io")
ngx.say(s)
ngx.say(n)
local s, n = ngx.re.sub("howdy, 1234", "([A-Z]+)", function () return "bah" end, "io")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("1234, okay", "([A-Z]+)", function () return "blah" end, "io")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("hi, 1234", "([A-Z]+)", "hello", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
baz, 1234
1
bah, 1234
1
1234, blah
1
hi, 1234
0
=== TEST 22: exceeding regex cache max entries
--- http_config
lua_regex_cache_max_entries 2;
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "([0-9]+)", "hello", "o")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("howdy, 567", "([0-9]+)", "hello", "oi")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("hiya, 98", "([0-9]+)", "hello", "ox")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, hello
1
howdy, hello
1
hiya, hello
1
=== TEST 23: disable regex cache completely
--- http_config
lua_regex_cache_max_entries 0;
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "([0-9]+)", "hello", "o")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("howdy, 567", "([0-9]+)", "hello", "oi")
ngx.say(s)
ngx.say(n)
s, n = ngx.re.sub("hiya, 98", "([0-9]+)", "hello", "ox")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, hello
1
howdy, hello
1
hiya, hello
1
=== TEST 24: empty replace
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234", "([0-9]+)", "", "o")
ngx.say(s)
ngx.say(n)
local s, n = ngx.re.sub("hi, 5432", "([0-9]+)", "", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello,
1
hi,
1
=== TEST 25: matched and with variables w/o using named patterns in sub
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("a b c d", "(?<first>b) (?<second>c)", "[$0] [$1] [$2] [$3] [$134]", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] [] [] d
1
=== TEST 26: matched and with variables using named patterns in func
--- config
error_log /tmp/nginx_error debug;
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "] [" .. m["first"] .. "] [" .. m[2] .. "]"
end
local s, n = ngx.re.sub("a b c d", "(?<first>b) (?<second>c)", repl, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
a [b c] [b] [c] d
1

View file

@ -1,200 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("[hello, world]", "[a-z]+", "howdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[howdy, howdy]
2
=== TEST 2: trimmed
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[a-z]+", "howdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
howdy, howdy
2
=== TEST 3: not matched
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[A-Z]+", "howdy", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
hello, world
0
=== TEST 4: replace by function (trimmed)
--- config
location /re {
content_by_lua '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("hello, world", "([a-z])[a-z]+", f, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2
=== TEST 5: replace by function (not trimmed)
--- config
location /re {
content_by_lua '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", f, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
2
=== TEST 6: replace by script (trimmed)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "([a-z])[a-z]+", "[$0,$1]", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2
=== TEST 7: replace by script (not trimmed)
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", "[$0,$1]", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
2
=== TEST 8: set_by_lua
--- config
location /re {
set_by_lua $res '
local f = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local s, n = ngx.re.gsub("{hello, world}", "([a-z])[a-z]+", f, "o")
return s
';
echo $res;
}
--- request
GET /re
--- response_body
{[hello,h], [world,w]}
=== TEST 9: look-behind assertion
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "h$0", "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
{foohbarhbaz}
2
=== TEST 10: named pattern repl w/ callback
--- config
location /re {
content_by_lua '
local repl = function (m)
return "[" .. m[0] .. "," .. m["first"] .. "]"
end
local s, n = ngx.re.gsub("hello, world", "(?<first>[a-z])[a-z]+", repl, "o")
ngx.say(s)
ngx.say(n)
';
}
--- request
GET /re
--- response_body
[hello,h], [world,w]
2

View file

@ -1,927 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
log_level('debug');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 13);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: set response content-type header
--- config
location /read {
echo "Hi";
header_filter_by_lua '
ngx.header.content_type = "text/my-plain";
';
}
--- request
GET /read
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 2: server config
--- config
header_filter_by_lua '
ngx.header.content_type = "text/my-plain";
';
location /read {
echo "Hi";
}
--- request
GET /read
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 3: set in http
--- http_config
header_filter_by_lua '
ngx.header.content_type = "text/my-plain";
';
--- config
location /read {
echo "Hi";
}
--- request
GET /read
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 4: overriding config
--- config
header_filter_by_lua '
ngx.header.content_type = "text/my-plain";
';
location /read {
echo "Hi";
header_filter_by_lua '
ngx.header.content_type = "text/read-plain";
';
}
--- request
GET /read
--- response_headers
Content-Type: text/read-plain
--- response_body
Hi
=== TEST 5: set response content-type header
--- config
location /read {
echo "Hi";
header_filter_by_lua '
ngx.header.content_type = "text/my-plain";
';
}
--- request
GET /read
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 6: lua code run failed
--- config
location /read {
echo "Hi";
header_filter_by_lua '
ngx.header.content_length = "text/my-plain";
';
}
--- request
GET /read
--- error_code
--- response_body
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 7: use variable generated by content phrase
--- config
location /read {
set $strvar '1';
content_by_lua '
ngx.var.strvar = "127.0.0.1:8080";
ngx.say("Hi");
';
header_filter_by_lua '
ngx.header.uid = ngx.var.strvar;
';
}
--- request
GET /read
--- response_headers
uid: 127.0.0.1:8080
--- response_body
Hi
=== TEST 8: use variable generated by content phrase for HEAD
--- config
location /read {
set $strvar '1';
content_by_lua '
ngx.var.strvar = "127.0.0.1:8080";
ngx.say("Hi");
';
header_filter_by_lua '
ngx.header.uid = ngx.var.strvar;
';
}
--- request
HEAD /read
--- response_headers
uid: 127.0.0.1:8080
--- response_body
=== TEST 9: use variable generated by content phrase for HTTP 1.0
--- config
location /read {
set $strvar '1';
content_by_lua '
ngx.var.strvar = "127.0.0.1:8080";
ngx.say("Hi");
';
header_filter_by_lua '
ngx.header.uid = ngx.var.strvar;
';
}
--- request
GET /read HTTP/1.0
--- response_headers
uid: 127.0.0.1:8080
--- response_body
Hi
=== TEST 10: use capture and header_filter_by
--- config
location /sub {
content_by_lua '
ngx.say("Hi");
';
header_filter_by_lua '
ngx.header.uid = "sub";
';
}
location /parent {
content_by_lua '
local res = ngx.location.capture("/sub")
if res.status == 200 then
ngx.say(res.header.uid)
else
ngx.say("parent")
end
';
header_filter_by_lua '
ngx.header.uid = "parent";
';
}
--- request
GET /parent
--- response_headers
uid: parent
--- response_body
sub
=== TEST 11: overriding ctx
--- config
location /lua {
content_by_lua '
ngx.ctx.foo = 32;
ngx.say(ngx.ctx.foo)
';
header_filter_by_lua '
ngx.ctx.foo = ngx.ctx.foo + 1;
ngx.header.uid = ngx.ctx.foo;
';
}
--- request
GET /lua
--- response_headers
uid: 33
--- response_body
32
=== TEST 12: use req
--- config
location /lua {
content_by_lua '
ngx.say("Hi");
';
header_filter_by_lua '
local str = "";
local args, err = ngx.req.get_uri_args()
if err then
ngx.log(ngx.ERR, "err: ", err)
return ngx.exit(500)
end
local keys = {}
for key, val in pairs(args) do
table.insert(keys, key)
end
table.sort(keys)
for i, key in ipairs(keys) do
local val = args[key]
if type(val) == "table" then
str = str .. table.concat(val, ", ")
else
str = str .. ":" .. val
end
end
ngx.header.uid = str;
';
}
--- request
GET /lua?a=1&b=2
--- response_headers
uid: :1:2
--- response_body
Hi
=== TEST 13: use ngx md5 function
--- config
location /lua {
content_by_lua '
ngx.say("Hi");
';
header_filter_by_lua '
ngx.header.uid = ngx.md5("Hi");
';
}
--- request
GET /lua
--- response_headers
uid: c1a5298f939e87e8f962a5edfc206918
--- response_body
Hi
=== TEST 14: set response content-type header (by file)
--- config
location /read {
echo "Hi";
header_filter_by_lua_file 'html/foo.lua';
}
--- request
GET /read
--- user_files
>>> foo.lua
ngx.header.content_type = "text/my-plain";
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 15: by_lua_file server config
--- config
header_filter_by_lua_file 'html/foo.lua';
location /read {
echo "Hi";
}
--- request
GET /read
--- user_files
>>> foo.lua
ngx.header.content_type = "text/my-plain";
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 16: by_lua_file set in http
--- http_config
header_filter_by_lua_file 'html/foo.lua';
--- config
location /read {
echo "Hi";
}
--- request
GET /read
--- user_files
>>> foo.lua
ngx.header.content_type = "text/my-plain";
--- response_headers
Content-Type: text/my-plain
--- response_body
Hi
=== TEST 17: by_lua_file overriding config
--- config
header_filter_by_lua 'html/foo.lua';
location /read {
echo "Hi";
header_filter_by_lua_file 'html/bar.lua';
}
--- request
GET /read
--- user_files
>>> foo.lua
ngx.header.content_type = "text/my-plain";
>>> bar.lua
ngx.header.content_type = "text/read-plain";
--- response_headers
Content-Type: text/read-plain
--- response_body
Hi
=== TEST 18: ngx.ctx available in header_filter_by_lua (already defined)
--- config
location /lua {
content_by_lua 'ngx.ctx.counter = 3 ngx.say(ngx.ctx.counter)';
header_filter_by_lua 'ngx.log(ngx.ERR, "ngx.ctx.counter: ", ngx.ctx.counter)';
}
--- request
GET /lua
--- response_body
3
--- error_log
ngx.ctx.counter: 3
lua release ngx.ctx
=== TEST 19: ngx.ctx available in header_filter_by_lua (not defined yet)
--- config
location /lua {
echo hello;
header_filter_by_lua '
ngx.log(ngx.ERR, "ngx.ctx.counter: ", ngx.ctx.counter)
ngx.ctx.counter = "hello world"
';
}
--- request
GET /lua
--- response_body
hello
--- error_log
ngx.ctx.counter: nil
lua release ngx.ctx
=== TEST 20: globals are shared by all requests
--- config
location /lua {
set $foo '';
content_by_lua '
ngx.send_headers()
ngx.say(ngx.var.foo)
';
header_filter_by_lua '
if not foo then
foo = 1
else
ngx.log(ngx.INFO, "old foo: ", foo)
foo = foo + 1
end
ngx.var.foo = foo
';
}
--- request
GET /lua
--- response_body_like
^[12]$
--- no_error_log
[error]
--- grep_error_log eval: qr/old foo: \d+/
--- grep_error_log_out eval
["", "old foo: 1\n"]
=== TEST 21: lua error (string)
--- config
location /lua {
set $foo '';
content_by_lua '
ngx.send_headers()
ngx.say(ngx.var.foo)
';
header_filter_by_lua '
error("Something bad")
';
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to run header_filter_by_lua*: header_filter_by_lua(nginx.conf:47):2: Something bad
--- no_error_log
[alert]
--- curl_error eval
qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 22: lua error (nil)
--- config
location /lua {
set $foo '';
content_by_lua '
ngx.send_headers()
ngx.say(ngx.var.foo)
';
header_filter_by_lua '
error(nil)
';
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to run header_filter_by_lua*: unknown reason
--- no_error_log
[alert]
--- curl_error eval
qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 23: no ngx.print
--- config
location /lua {
header_filter_by_lua "ngx.print(32) return 1";
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 24: no ngx.say
--- config
location /lua {
header_filter_by_lua "ngx.say(32) return 1";
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 25: no ngx.flush
--- config
location /lua {
header_filter_by_lua "ngx.flush()";
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 26: no ngx.eof
--- config
location /lua {
header_filter_by_lua "ngx.eof()";
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 27: no ngx.send_headers
--- config
location /lua {
header_filter_by_lua "ngx.send_headers()";
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 28: no ngx.location.capture
--- config
location /lua {
header_filter_by_lua 'ngx.location.capture("/sub")';
echo ok;
}
location /sub {
echo sub;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 29: no ngx.location.capture_multi
--- config
location /lua {
header_filter_by_lua 'ngx.location.capture_multi{{"/sub"}}';
echo ok;
}
location /sub {
echo sub;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 30: no ngx.redirect
--- config
location /lua {
header_filter_by_lua 'ngx.redirect("/blah")';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 31: no ngx.exec
--- config
location /lua {
header_filter_by_lua 'ngx.exec("/blah")';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 32: no ngx.req.set_uri(uri, true)
--- config
location /lua {
header_filter_by_lua 'ngx.req.set_uri("/blah", true)';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 33: ngx.req.set_uri(uri) exists
--- config
location /lua {
header_filter_by_lua 'ngx.req.set_uri("/blah") return 1';
content_by_lua '
ngx.send_headers()
ngx.say("uri: ", ngx.var.uri)
';
}
--- request
GET /lua
--- response_body
uri: /blah
--- no_error_log
[error]
=== TEST 34: no ngx.req.read_body()
--- config
location /lua {
header_filter_by_lua 'ngx.req.read_body()';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log eval
qr/API disabled in the context of header_filter_by_lua\*|http3 requests are not supported without content-length header/ms
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 35: no ngx.req.socket()
--- config
location /lua {
header_filter_by_lua 'return ngx.req.socket()';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log eval
my $err_log;
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
$err_log = "http v3 not supported yet";
} else {
$err_log = "API disabled in the context of header_filter_by_lua*";
}
$err_log;
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 36: no ngx.socket.tcp()
--- config
location /lua {
header_filter_by_lua 'return ngx.socket.tcp()';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 37: no ngx.socket.connect()
--- config
location /lua {
header_filter_by_lua 'return ngx.socket.connect("127.0.0.1", 80)';
echo ok;
}
--- request
GET /lua
--- ignore_response
--- error_log
API disabled in the context of header_filter_by_lua*
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 38: clear content-length
--- config
location /lua {
content_by_lua '
ngx.header.content_length = 12
ngx.say("hello world")
';
header_filter_by_lua 'ngx.header.content_length = nil';
}
--- request
GET /lua
--- response_headers
!content-length
--- response_body
hello world
=== TEST 39: backtrace
--- config
location /t {
header_filter_by_lua '
local bar
local function foo()
bar()
end
function bar()
error("something bad happened")
end
foo()
';
echo ok;
}
--- request
GET /t
--- ignore_response
--- error_log
something bad happened
stack traceback:
in function 'error'
in function 'bar'
in function 'foo'
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 40: Lua file does not exist
--- config
location /lua {
echo ok;
header_filter_by_lua_file html/test2.lua;
}
--- user_files
>>> test.lua
v = ngx.var["request_uri"]
ngx.print("request_uri: ", v, "\n")
--- request
GET /lua?a=1&b=2
--- ignore_response
--- error_log eval
qr/failed to load external Lua file ".*?test2\.lua": cannot open .*? No such file or directory/
--- curl_error eval
qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 0 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/
=== TEST 41: filter finalize
--- config
error_page 582 = /bar;
location = /t {
echo ok;
header_filter_by_lua '
return ngx.exit(582)
';
}
location = /bar {
echo hi;
header_filter_by_lua '
return ngx.exit(302)
';
}
--- request
GET /t
--- response_body_like: 302 Found
--- error_code: 302
--- no_error_log
[error]
=== TEST 42: syntax error in header_filter_by_lua_block
--- config
location /lua {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(nginx.conf:41):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error
--- curl_error eval
qr/curl: \(56\) Failure when receiving data from the peer/
=== TEST 43: syntax error in second content_by_lua_block
--- config
location /foo {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
location /lua {
header_filter_by_lua_block {
'for end';
}
content_by_lua_block {
ngx.say("Hello world")
}
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(nginx.conf:49):2: unexpected symbol near ''for end''
--- no_error_log
no_such_error
--- curl_error eval
qr/curl: \(56\) Failure when receiving data from the peer/
=== TEST 44: syntax error in /tmp/12345678901234567890123456789012345.conf
--- config
location /lua {
content_by_lua_block {
ngx.say("Hello world")
}
include /tmp/12345678901234567890123456789012345.conf;
}
--- user_files
>>> /tmp/12345678901234567890123456789012345.conf
header_filter_by_lua_block {
'for end';
}
--- request
GET /lua
--- ignore_response
--- error_log
failed to load inlined Lua code: header_filter_by_lua(...901234567890123456789012345.conf:1):2: unexpected symbol near ''for end''
--- no_error_log
[alert]
--- curl_error eval
qr/curl: \(56\) Failure when receiving data from the peer/

View file

@ -1,56 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: short sanity
--- config
location = /test {
content_by_lua '
ngx.say(ngx.crc32_short("hello, world"))
';
}
--- request
GET /test
--- response_body
4289425978
=== TEST 2: long sanity
--- config
location = /test {
content_by_lua '
ngx.say(ngx.crc32_long("hello, world"))
';
}
--- request
GET /test
--- response_body
4289425978
=== TEST 3: long sanity (empty)
--- config
location = /test {
content_by_lua '
ngx.say(ngx.crc32_long(""))
';
}
--- request
GET /test
--- response_body
0

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,292 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 9);
#no_diff();
#no_long_string();
#master_on();
#workers(2);
run_tests();
__DATA__
=== TEST 1: set indexed variables to nil
--- config
location = /test {
set $var 32;
content_by_lua '
ngx.say("old: ", ngx.var.var)
ngx.var.var = nil
ngx.say("new: ", ngx.var.var)
';
}
--- request
GET /test
--- response_body
old: 32
new: nil
=== TEST 2: set variables with set_handler to nil
--- config
location = /test {
content_by_lua '
ngx.say("old: ", ngx.var.args)
ngx.var.args = nil
ngx.say("new: ", ngx.var.args)
';
}
--- request
GET /test?hello=world
--- response_body
old: hello=world
new: nil
=== TEST 3: reference nonexistent variable
--- config
location = /test {
set $var 32;
content_by_lua '
ngx.say("value: ", ngx.var.notfound)
';
}
--- request
GET /test
--- response_body
value: nil
=== TEST 4: no-hash variables
--- config
location = /test {
proxy_pass http://127.0.0.1:$server_port/foo;
header_filter_by_lua '
ngx.header["X-My-Host"] = ngx.var.proxy_host
';
}
location = /foo {
echo foo;
}
--- request
GET /test
--- response_headers
X-My-Host: foo
--- response_body
foo
--- SKIP
=== TEST 5: variable name is caseless
--- config
location = /test {
set $Var 32;
content_by_lua '
ngx.say("value: ", ngx.var.VAR)
';
}
--- request
GET /test
--- response_body
value: 32
=== TEST 6: true $invalid_referer variable value in Lua
github issue #239
--- config
location = /t {
valid_referers www.foo.com;
content_by_lua '
ngx.say("invalid referer: ", ngx.var.invalid_referer)
ngx.exit(200)
';
#echo $invalid_referer;
}
--- request
GET /t
--- more_headers
Referer: http://www.foo.com/
--- response_body
invalid referer:
--- no_error_log
[error]
=== TEST 7: false $invalid_referer variable value in Lua
github issue #239
--- config
location = /t {
valid_referers www.foo.com;
content_by_lua '
ngx.say("invalid referer: ", ngx.var.invalid_referer)
ngx.exit(200)
';
#echo $invalid_referer;
}
--- request
GET /t
--- more_headers
Referer: http://www.bar.com
--- response_body
invalid referer: 1
--- no_error_log
[error]
=== TEST 8: $proxy_host & $proxy_port & $proxy_add_x_forwarded_for
--- config
location = /t {
proxy_pass http://127.0.0.1:$server_port/back;
header_filter_by_lua_block {
ngx.header["Proxy-Host"] = ngx.var.proxy_host
ngx.header["Proxy-Port"] = ngx.var.proxy_port
ngx.header["Proxy-Add-X-Forwarded-For"] = ngx.var.proxy_add_x_forwarded_for
}
}
location = /back {
echo hello;
}
--- request
GET /t
--- raw_response_headers_like eval
my $headers;
if (defined $ENV{TEST_NGINX_USE_HTTP3}) {
$headers =
qr/proxy-host: 127.0.0.1\:\d+\r
proxy-port: \d+\r
proxy-add-x-forwarded-for: 127.0.0.1\r/;
} else {
$headers =
qr/Proxy-Host: 127.0.0.1\:\d+\r
Proxy-Port: \d+\r
Proxy-Add-X-Forwarded-For: 127.0.0.1\r/;
}
$headers;
--- response_body
hello
--- no_error_log
[error]
=== TEST 9: get a bad variable name
--- config
location = /test {
set $true 32;
content_by_lua '
ngx.say("value: ", ngx.var[true])
';
}
--- request
GET /test
--- response_body_like: 500 Internal Server Error
--- error_log
bad variable name
--- error_code: 500
=== TEST 10: set a bad variable name
--- config
location = /test {
set $true 32;
content_by_lua '
ngx.var[true] = 56
';
}
--- request
GET /test
--- response_body_like: 500 Internal Server Error
--- error_log
bad variable name
--- error_code: 500
=== TEST 11: set a variable that is not changeable
--- config
location = /test {
content_by_lua '
ngx.var.query_string = 56
';
}
--- request
GET /test?hello
--- response_body_like: 500 Internal Server Error
--- error_log
variable "query_string" not changeable
--- error_code: 500
=== TEST 12: get a variable in balancer_by_lua_block
--- http_config
upstream balancer {
server 127.0.0.1;
balancer_by_lua_block {
local balancer = require "ngx.balancer"
local host = "127.0.0.1"
local port = ngx.var.port;
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
}
}
server {
# this is the real entry point
listen $TEST_NGINX_RAND_PORT_1;
location / {
content_by_lua_block{
ngx.print("this is backend peer $TEST_NGINX_RAND_PORT_1")
}
}
}
server {
# this is the real entry point
listen $TEST_NGINX_RAND_PORT_2;
location / {
content_by_lua_block{
ngx.print("this is backend peer $TEST_NGINX_RAND_PORT_2")
}
}
}
--- config
location =/balancer {
set $port '';
set_by_lua_block $port {
local args, _ = ngx.req.get_uri_args()
local port = args['port']
return port
}
proxy_pass http://balancer;
}
--- pipelined_requests eval
["GET /balancer?port=\$TEST_NGINX_RAND_PORT_1", "GET /balancer?port=\$TEST_NGINX_RAND_PORT_2"]
--- response_body eval
["this is backend peer \$TEST_NGINX_RAND_PORT_1", "this is backend peer \$TEST_NGINX_RAND_PORT_2"]

View file

@ -1,31 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
#repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /lua {
content_by_lua '
local digest = ngx.hmac_sha1("thisisverysecretstuff", "some string we want to sign")
ngx.say(ngx.encode_base64(digest))
';
}
--- request
GET /lua
--- response_body
R/pvxzHC4NLtj7S+kXFg/NePTmk=

View file

@ -1,242 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 5);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with j
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "j")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 2: not matched with j
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, world", "([0-9]+)", "j")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
not matched!
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 3: matched with jo
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, 1234", "([0-9]+)", "jo")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
1234
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 4: not matched with jo
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello, world", "([0-9]+)", "jo")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
not matched!
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 5: bad pattern
--- config
location /re {
content_by_lua '
local m, err = ngx.re.match("hello\\nworld", "(abc", "j")
if m then
ngx.say(m[0])
else
if err then
ngx.say("error: ", err)
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 6: just hit match limit
--- http_config
lua_regex_match_limit 2940;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 21)
local start = ngx.now()
local res, err = ngx.re.match(s, re, "jo")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if not res then
if err then
ngx.say("error: ", err)
return
end
ngx.say("failed to match")
return
end
--- request
GET /re
--- response_body eval
# lua_regex_match_limit uses pcre_extra->match_limit in the PCRE,
# but PCRE2 replaces this with pcre2_set_match_limit interface,
# which has different effects.
$Test::Nginx::Util::PcreVersion == 2 ?
# PCRE2_ERROR_MATCHLIMIT (-47)
"error: pcre_exec() failed: -47\n"
:
"error: pcre_exec() failed: -8\n"
=== TEST 7: just not hit match limit
--- http_config
lua_regex_match_limit 2950;
--- config
location /re {
content_by_lua_file html/a.lua;
}
--- user_files
>>> a.lua
local re = [==[(?i:([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´\(\)]*)?\2|([\s'\"`´\(\)]*)?([\d\w]+)([\s'\"`´\(\)]*)?(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´\(\)]*)?(?!\6)([\d\w]+))]==]
local s = string.rep([[ABCDEFG]], 21)
local start = ngx.now()
local res, err = ngx.re.match(s, re, "jo")
--[[
ngx.update_time()
local elapsed = ngx.now() - start
ngx.say(elapsed, " sec elapsed.")
]]
if not res then
if err then
ngx.say("error: ", err)
return
end
ngx.say("failed to match")
return
end
--- request
GET /re
--- response_body
failed to match

View file

@ -1,247 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 4);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with d
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello", "(he|hell)", "d")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hell
nil
nil
=== TEST 2: matched with d + o
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello", "(he|hell)", "do")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hell
nil
nil
=== TEST 3: matched with d + j
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello", "(he|hell)", "jd")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hell
=== TEST 4: not matched with j
--- config
location /re {
content_by_lua '
local m = ngx.re.match("world", "(he|hell)", "d")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
not matched!
=== TEST 5: matched with do
--- config
location /re {
content_by_lua '
local m = ngx.re.match("hello", "he|hell", "do")
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
hell
nil
nil
=== TEST 6: not matched with do
--- config
location /re {
content_by_lua '
local m = ngx.re.match("world", "([0-9]+)", "do")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- request
GET /re
--- response_body
not matched!
=== TEST 7: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local m = ngx.re.match("你好", ".", "Ud")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
--- request
GET /re
--- response_body
--- no_error_log
[error]
=== TEST 8: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local m = ngx.re.match("你好", ".", "ud")
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
--- request
GET /re
--- response_body
--- 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

View file

@ -1,267 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 9);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: gmatch matched
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, world", "[a-z]+", "j") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hello
world
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 2: fail to match
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[0-9]", "j")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
nil
nil
nil
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 3: gmatch matched but no iterate
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "j")
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 4: gmatch matched but only iterate once and still matches remain
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "j")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /re
--- response_body
hello
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 5: gmatch matched + o
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, world", "[a-z]+", "jo") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hello
world
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 6: fail to match + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[0-9]", "jo")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
nil
nil
nil
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 7: gmatch matched but no iterate + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "jo")
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 8: gmatch matched but only iterate once and still matches remain + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "jo")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /re
--- response_body
hello
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 9: bad pattern
--- config
location /re {
content_by_lua '
local m, err = ngx.re.gmatch("hello\\nworld", "(abc", "j")
if not m then
ngx.say("error: ", err)
return
end
ngx.say("success")
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]

View file

@ -1,341 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 5);
#no_diff();
#no_long_string();
run_tests();
__DATA__
=== TEST 1: gmatch matched
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, halo", "h[a-z]|h[a-z][a-z]", "d") do
if m then
ngx.say(m[0])
ngx.say(m[1])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hel
nil
hal
nil
=== TEST 2: d + j
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, halo", "h[a-z]|h[a-z][a-z]", "dj") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hel
hal
=== TEST 3: fail to match
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[0-9]", "d")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
nil
nil
nil
=== TEST 4: gmatch matched but no iterate
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "d")
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
=== TEST 5: gmatch matched but only iterate once and still matches remain
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "d")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /re
--- response_body
hello
=== TEST 6: gmatch matched + o
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello, world", "[a-z]+", "do") do
if m then
ngx.say(m[0])
else
ngx.say("not matched: ", m)
end
end
';
}
--- request
GET /re
--- response_body
hello
world
=== TEST 7: fail to match + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[0-9]", "do")
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
local m = it()
if m then ngx.say(m[0]) else ngx.say(m) end
';
}
--- request
GET /re
--- response_body
nil
nil
nil
=== TEST 8: gmatch matched but no iterate + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "do")
ngx.say("done")
';
}
--- request
GET /re
--- response_body
done
=== TEST 9: gmatch matched but only iterate once and still matches remain + o
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("hello, world", "[a-z]+", "do")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched")
end
';
}
--- request
GET /re
--- response_body
hello
=== TEST 10: bad pattern
--- config
location /re {
content_by_lua '
local it, err = ngx.re.gmatch("hello\\nworld", "(abc", "d")
if not it then
ngx.say("error: ", err)
return
end
ngx.say("success")
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 11: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("你好", ".", "Ud")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
--- request
GET /re
--- response_body
--- no_error_log
[error]
=== TEST 12: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local it = ngx.re.gmatch("你好", ".", "ud")
local m = it()
if m then
ngx.say(m[0])
else
ngx.say("not matched!")
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
--- request
GET /re
--- response_body
--- no_error_log
[error]
=== TEST 13: gmatched with submatch captures
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello", "(he|hell)", "d") do
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
end
';
}
--- request
GET /re
--- response_body
hell
nil
nil
=== TEST 14: gmatched with submatch captures (compile once)
--- config
location /re {
content_by_lua '
for m in ngx.re.gmatch("hello", "(he|hell)", "od") do
if m then
ngx.say(m[0])
ngx.say(m[1])
ngx.say(m[2])
else
ngx.say("not matched!")
end
end
';
}
--- request
GET /re
--- response_body
hell
nil
nil

View file

@ -1,173 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 6);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with j
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234 5678", "([0-9]+)", "world", "j")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world 5678: 1
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 2: not matched with j
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[0-9]+", "hiya", "j")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 3: matched with jo
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234 5678", "([0-9]+)", "world", "jo")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world 5678: 1
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 4: not matched with jo
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[0-9]+", "hiya", "jo")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 5: bad pattern
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("hello\\nworld", "(abc", "world", "j")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 6: bad pattern + o
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub( "hello\\nworld", "(abc", "world", "jo")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]

View file

@ -1,241 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 8);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234 5678", "[0-9]|[0-9][0-9]", "world", "d")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world34 5678: 1
=== TEST 2: not matched with d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[0-9]+", "hiya", "d")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
=== TEST 3: matched with do
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, 1234 5678", "[0-9]|[0-9][0-9]", "world", "do")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world34 5678: 1
=== TEST 4: not matched with do
--- config
location /re {
content_by_lua '
local s, n = ngx.re.sub("hello, world", "[0-9]+", "hiya", "do")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
=== TEST 5: bad pattern
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("hello\\nworld", "(abc", "world", "j")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 6: bad pattern + o
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("hello\\nworld", "(abc", "world", "jo")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 7: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("你好", ".", "a", "Ud")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
--- request
GET /re
--- response_body
s: a好
--- no_error_log
[error]
=== TEST 8: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.sub("你好", ".", "a", "ud")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
--- request
GET /re
--- response_body
s: a好
--- no_error_log
[error]
=== TEST 9: sub with d
--- config
location /re {
content_by_lua '
ngx.say(ngx.re.sub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "d"))
';
}
--- request
GET /re
--- response_body
hell
nil
xo1
--- no_error_log
[error]
=== TEST 10: sub with d + o
--- config
location /re {
content_by_lua '
ngx.say(ngx.re.sub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "do"))
';
}
--- request
GET /re
--- response_body
hell
nil
xo1
--- no_error_log
[error]

View file

@ -1,173 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 6);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with j
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, 1234 5678", "([0-9]+)", "world", "j")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world world: 2
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 2: not matched with j
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[0-9]+", "hiya", "j")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
--- error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully\n"
:
"pcre JIT compiling result: 1\n"
=== TEST 3: matched with jo
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, 1234 5678", "([0-9]+)", "world", "jo")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world world: 2
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 4: not matched with jo
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[0-9]+", "hiya", "jo")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
--- grep_error_log eval
$Test::Nginx::Util::PcreVersion == 2 ?
"pcre2 JIT compiled successfully"
:
"pcre JIT compiling result: 1"
--- grep_error_log_out eval
$Test::Nginx::Util::PcreVersion == 2 ?
["pcre2 JIT compiled successfully\n", ""]
:
["pcre JIT compiling result: 1\n", ""]
=== TEST 5: bad pattern
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("hello\\nworld", "(abc", "world", "j")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 6: bad pattern + o
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("hello\\nworld", "(abc", "world", "jo")
if s then
ngx.say(s, ": ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]

View file

@ -1,242 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 7);
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: matched with d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, 1234 5678", "[0-9]|[0-9][0-9]", "world", "d")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, worldworld worldworld: 4
=== TEST 2: not matched with d
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[0-9]+", "hiya", "d")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
=== TEST 3: matched with do
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, 1234 5678", "[0-9]|[0-9][0-9]", "world", "do")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, worldworld worldworld: 4
=== TEST 4: not matched with do
--- config
location /re {
content_by_lua '
local s, n = ngx.re.gsub("hello, world", "[0-9]+", "hiya", "do")
if n then
ngx.say(s, ": ", n)
else
ngx.say(s)
end
';
}
--- request
GET /re
--- response_body
hello, world: 0
=== TEST 5: bad pattern
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("hello\\nworld", "(abc", "world", "j")
if s then
ngx.say("gsub: ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
=== TEST 6: bad pattern + o
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("hello\\nworld", "(abc", "world", "jo")
if s then
ngx.say("gsub: ", n)
else
ngx.say("error: ", err)
end
';
}
--- request
GET /re
--- response_body eval
$Test::Nginx::Util::PcreVersion == 2 ?
"error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n"
:
"error: pcre_compile() failed: missing ) in \"(abc\"\n"
--- no_error_log
[error]
=== TEST 7: UTF-8 mode without UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("你好", ".", "a", "Ud")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 2000
exec opts: 2000
exec opts: 2000
--- request
GET /re
--- response_body
s: aa
--- no_error_log
[error]
=== TEST 8: UTF-8 mode with UTF-8 sequence checks
--- config
location /re {
content_by_lua '
local s, n, err = ngx.re.gsub("你好", ".", "a", "ud")
if s then
ngx.say("s: ", s)
end
';
}
--- stap
probe process("$LIBPCRE_PATH").function("pcre_compile") {
printf("compile opts: %x\n", $options)
}
probe process("$LIBPCRE_PATH").function("pcre_dfa_exec") {
printf("exec opts: %x\n", $options)
}
--- stap_out
compile opts: 800
exec opts: 0
exec opts: 0
exec opts: 0
--- request
GET /re
--- response_body
s: aa
--- no_error_log
[error]
=== TEST 9: gsub with d
--- config
location /re {
content_by_lua '
ngx.say(ngx.re.gsub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "d"))
';
}
--- request
GET /re
--- response_body
hell
nil
xo1
--- no_error_log
[error]
=== TEST 10: gsub with d + o
--- config
location /re {
content_by_lua '
ngx.say(ngx.re.gsub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "do"))
';
}
--- request
GET /re
--- response_body
hell
nil
xo1
--- no_error_log
[error]

View file

@ -1,338 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 5);
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: set non-existent variables via "vars" option
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { dog = "hello", cat = 32 }});
ngx.print(res.body)
';
}
--- stap2
global delta = " "
F(ngx_http_finalize_request) {
uri = ngx_http_req_uri($r)
printf("finalize req %s: %d\n", uri, $rc)
if ($rc == 500) {
print_ubacktrace()
}
}
F(ngx_http_lua_run_thread) {
uri = ngx_http_req_uri($r)
printf("lua run thread %s\n", uri)
}
M(http-subrequest-start) {
r = $arg1
n = ngx_http_subreq_depth(r)
pr = ngx_http_req_parent(r)
printf("%sbegin %s -> %s (%d)\n", ngx_indent(n, delta),
ngx_http_req_uri(pr),
ngx_http_req_uri(r),
n)
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_log eval
qr/variable "(dog|cat)" cannot be assigned a value \(maybe you forgot to define it first\?\)/
--- error_code: 500
=== TEST 2: set non-existent variables via "vars" option
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
set $dog '';
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { dog = "hello", cat = 32 }});
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_log chop
variable "cat" cannot be assigned a value (maybe you forgot to define it first?)
--- error_code: 500
=== TEST 3: good "vars" option: user variables
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
set $dog '';
set $cat '';
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { dog = "hello", cat = 32 }});
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body
dog = hello
cat = 32
=== TEST 4: bad "vars" option value
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
set $dog '';
set $cat '';
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = "hello" });
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log chop
Bad vars option value
=== TEST 5: bad "vars" option value value
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
set $dog '';
set $cat '';
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { cat = true } });
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log chop
attempt to use bad variable value type boolean
=== TEST 6: good "vars" option: builtin variables
--- config
location /other {
echo "args: $args";
}
location /lua {
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { args = "a=hello&b=32" }});
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body
args: a=hello&b=32
=== TEST 7: setting non-changeable vars
--- config
location /other {
echo "query string: $query_string";
}
location /lua {
content_by_lua '
res = ngx.location.capture("/other",
{ vars = { query_string = "hello" } });
ngx.print(res.body)
';
}
--- request
GET /lua
--- response_body_like: 500 Internal Server Error
--- error_code: 500
--- error_log chop
variable "query_string" not changeable
=== TEST 8: copy all vars
--- config
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua '
local res = ngx.location.capture("/other",
{ copy_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
';
}
--- request
GET /lua
--- response_body
/other dog: hello world
/lua: hello
=== TEST 9: share all vars
--- config
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua '
local res = ngx.location.capture("/other",
{ share_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
';
}
--- request
GET /lua
--- response_body
/other dog: hello world
/lua: hello world
=== TEST 10: vars takes priority over copy_all_vars
--- config
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua '
local res = ngx.location.capture("/other",
{ vars = { dog = "hiya" }, copy_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
';
}
--- request
GET /lua
--- response_body
/other dog: hiya world
/lua: hello
=== TEST 11: capture_multi: good "vars" option: user variables
--- config
location /other {
content_by_lua '
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
';
}
location /lua {
set $dog 'blah';
set $cat 'foo';
content_by_lua '
local res1, res2 = ngx.location.capture_multi{
{"/other/1",
{ vars = { dog = "hello", cat = 32 }}
},
{"/other/2",
{ vars = { dog = "hiya", cat = 56 }}
}
};
ngx.print(res1.body)
ngx.print(res2.body)
ngx.say("parent dog: ", ngx.var.dog)
ngx.say("parent cat: ", ngx.var.cat)
';
}
--- request
GET /lua
--- response_body
dog = hello
cat = 32
dog = hiya
cat = 56
parent dog: blah
parent cat: foo

View file

@ -1,532 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
BEGIN {
$ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1;
}
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * 60;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: flush wait - content
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
--- no_error_log
[error]
--- error_log
lua reuse free buf chain, but reallocate memory because 5 >= 0
=== TEST 2: flush no wait - content
--- config
send_timeout 500ms;
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 3: flush wait - rewrite
--- config
location /test {
rewrite_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
';
content_by_lua return;
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 4: flush no wait - rewrite
--- config
location /test {
rewrite_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
';
content_by_lua return;
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 5: http 1.0 (sync)
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- timeout: 5
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 6: http 1.0 (async)
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.WARN, "1: failed to flush: ", err)
end
ngx.say("hiya")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.WARN, "2: failed to flush: ", err)
end
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
1: failed to flush: buffering
2: failed to flush: buffering
--- timeout: 5
=== TEST 7: flush wait - big data
--- config
location /test {
content_by_lua '
ngx.say(string.rep("a", 1024 * 64))
ngx.flush(true)
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
--- SKIP
=== TEST 8: flush wait - content
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.flush(true)
';
}
location /sub {
echo sub;
}
--- request
GET /test
--- response_body
hello, world
sub
=== TEST 9: http 1.0 (sync + buffering off)
--- config
lua_http10_buffering off;
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
!Content-Length
--- timeout: 5
--- no_error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 10: http 1.0 (async)
--- config
lua_http10_buffering on;
location /test {
lua_http10_buffering off;
content_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
ngx.flush(false)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
!Content-Length
--- no_error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
--- timeout: 5
=== TEST 11: http 1.0 (sync) - buffering explicitly off
--- config
location /test {
lua_http10_buffering on;
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- timeout: 5
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 12: http 1.0 (async) - buffering explicitly off
--- config
location /test {
lua_http10_buffering on;
content_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
ngx.flush(false)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
--- timeout: 5
=== TEST 13: flush wait in a user coroutine
--- config
location /test {
content_by_lua '
local function f()
ngx.say("hello, world")
ngx.flush(true)
coroutine.yield()
ngx.say("hiya")
end
local c = coroutine.create(f)
ngx.say(coroutine.resume(c))
ngx.say(coroutine.resume(c))
';
}
--- request
GET /test
--- stap2
F(ngx_http_lua_wev_handler) {
printf("wev handler: wev:%d\n", $r->connection->write->ready)
}
global ids, cur
function gen_id(k) {
if (ids[k]) return ids[k]
ids[k] = ++cur
return cur
}
F(ngx_http_handler) {
delete ids
cur = 0
}
/*
F(ngx_http_lua_run_thread) {
id = gen_id($ctx->cur_co)
printf("run thread %d\n", id)
}
probe process("/usr/local/openresty-debug/luajit/lib/libluajit-5.1.so.2").function("lua_resume") {
id = gen_id($L)
printf("lua resume %d\n", id)
}
*/
M(http-lua-user-coroutine-resume) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("resume %x in %x\n", c, p)
}
M(http-lua-entry-coroutine-yield) {
println("entry coroutine yield")
}
/*
F(ngx_http_lua_coroutine_yield) {
printf("yield %x\n", gen_id($L))
}
*/
M(http-lua-user-coroutine-yield) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("yield %x in %x\n", c, p)
}
F(ngx_http_lua_atpanic) {
printf("lua atpanic(%d):", gen_id($L))
print_ubacktrace();
}
M(http-lua-user-coroutine-create) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("create %x in %x\n", c, p)
}
F(ngx_http_lua_ngx_exec) { println("exec") }
F(ngx_http_lua_ngx_exit) { println("exit") }
F(ngx_http_writer) { println("http writer") }
--- response_body
hello, world
true
hiya
true
--- error_log
lua reuse free buf memory 13 >= 5
=== TEST 14: flush before sending out the header
--- config
location /test {
content_by_lua '
ngx.flush()
ngx.status = 404
ngx.say("not found")
';
}
--- request
GET /test
--- response_body
not found
--- error_code: 404
--- no_error_log
[error]
=== TEST 15: flush wait - gzip
--- config
gzip on;
gzip_min_length 1;
gzip_types text/plain;
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- more_headers
Accept-Encoding: gzip
--- response_body_like: .{15}
--- response_headers
Content-Encoding: gzip
--- no_error_log
[error]
=== TEST 16: flush wait - gunzip
--- config
location /test {
gunzip on;
content_by_lua '
local f, err = io.open(ngx.var.document_root .. "/gzip.bin", "r")
if not f then
ngx.say("failed to open file: ", err)
return
end
local data = f:read(100)
ngx.header.content_encoding = "gzip"
ngx.print(data)
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
data = f:read("*a")
ngx.print(data)
';
}
--- user_files eval
">>> gzip.bin
\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x62\x64\x62\x62\x61\x62\x64\x63\x61\xe4\xe0\xe2\xe6\xe4\x61\xe4\xe4\xe7\x63\x12\xe4\xe1\xe0\x60\x14\x12\xe3\x91\xe4\xe4\xe4\x13\x60\xe3\x95\x12\x90\x15\xe0\x11\x50\x92\xd1\x16\x17\xe2\xd3\x17\x14\x11\x95\x95\x57\x96\x63\x37\xd2\x36\xd6\x51\x34\xb1\xe6\x62\x17\x95\xb0\x77\x60\xe3\x96\x33\x95\xb6\x91\x75\x97\x30\xe4\x66\x0c\xd0\xe3\xe0\xb5\xd3\x33\xf6\x90\x16\xb2\x90\x77\x56\x31\xe7\x55\x32\x11\x74\xe0\x02\x00\x00\x00\xff\xff\xcb\xc8\xac\x4c\xe4\x02\x00\x19\x15\xa9\x77\x6a\x00\x00\x00"
--- request
GET /test
--- ignore_response
--- no_error_log
[error]
=== TEST 17: limit_rate
--- quic_max_idle_timeout: 2
--- config
location /test {
limit_rate 150;
content_by_lua '
local begin = ngx.now()
for i = 1, 2 do
ngx.print(string.rep("a", 100))
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "failed to flush: ", err)
end
end
local elapsed = ngx.now() - begin
ngx.log(ngx.WARN, "lua writes elapsed ", elapsed, " sec")
';
}
--- request
GET /test
--- response_body eval
"a" x 200
--- error_log eval
my @errlog;
if (defined $ENV{TEST_NGINX_USE_HTTP2}) {
@errlog = [
qr/lua writes elapsed 0\.[7-9]\d+ sec/,
qr/lua flush requires waiting: buffered 0x[0-9a-f]+, delayed:1/,
];
} else {
@errlog = [
qr/lua writes elapsed [12](?:\.\d+)? sec/,
qr/lua flush requires waiting: buffered 0x[0-9a-f]+, delayed:1/,
];
}
@errlog;
--- no_error_log
[error]
--- timeout: 4

View file

@ -1,325 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
BEGIN {
if (!defined $ENV{LD_PRELOAD}) {
$ENV{LD_PRELOAD} = '';
}
if ($ENV{LD_PRELOAD} !~ /\bmockeagain\.so\b/) {
$ENV{LD_PRELOAD} = "mockeagain.so $ENV{LD_PRELOAD}";
}
if ($ENV{MOCKEAGAIN} eq 'r') {
$ENV{MOCKEAGAIN} = 'rw';
} else {
$ENV{MOCKEAGAIN} = 'w';
}
$ENV{TEST_NGINX_EVENT_TYPE} = 'poll';
$ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'hello, world';
$ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1;
delete($ENV{TEST_NGINX_USE_HTTP2});
if ($ENV{TEST_NGINX_USE_HTTP3}) {
$SkipReason = "HTTP3 does not support mockeagain";
}
}
use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : ();
use t::StapThread;
our $GCScript = $t::StapThread::GCScript;
our $StapScript = $t::StapThread::StapScript;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * 17;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: flush wait - timeout
--- config
send_timeout 100ms;
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
';
}
--- request
GET /test
--- ignore_response
--- error_log eval
qr/client timed out \(\d+: .*?timed out\)/
--- no_error_log
[error]
=== TEST 2: send timeout timer got removed in time
--- config
send_timeout 1234ms;
location /test {
content_by_lua '
ngx.say(string.rep("blah blah blah", 10))
-- ngx.flush(true)
ngx.eof()
for i = 1, 20 do
ngx.sleep(0.1)
end
';
}
--- request
GET /test
--- stap
global evtime
F(ngx_http_handler) {
delete evtime
}
M(timer-add) {
if ($arg2 == 1234) {
printf("add timer %d\n", $arg2)
evtime[$arg1] = $arg2
}
}
M(timer-del) {
time = evtime[$arg1]
if (time == 1234) {
printf("del timer %d\n", time)
}
}
M(timer-expire) {
time = evtime[$arg1]
if (time == 1234) {
printf("expire timer %d\n", time)
#print_ubacktrace()
}
}
/*
probe syscall.writev.return {
if (pid() == target()) {
printf("writev: %s\n", retstr)
}
}
*/
--- stap_out
add timer 1234
del timer 1234
--- ignore_response
--- no_error_log
[error]
--- timeout: 3
=== TEST 3: exit in user thread (entry thread is still pending on ngx.flush)
--- config
send_timeout 200ms;
location /lua {
content_by_lua '
local function f()
ngx.say("hello in thread")
ngx.sleep(0.1)
ngx.exit(0)
end
ngx.say("before")
ngx.thread.spawn(f)
ngx.say("after")
ngx.say("hello, world!")
ngx.flush(true)
ngx.say("end")
';
}
--- request
GET /lua
--- stap2 eval: $::StapScript
--- stap eval
<<'_EOC_' . $::GCScript;
global timers
F(ngx_http_free_request) {
println("free request")
}
M(timer-add) {
if ($arg2 == 200 || $arg2 == 100) {
timers[$arg1] = $arg2
printf("add timer %d\n", $arg2)
}
}
M(timer-del) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("delete timer %d\n", tm)
delete timers[$arg1]
}
}
M(timer-expire) {
tm = timers[$arg1]
if (tm == 200 || tm == 100) {
printf("expire timer %d\n", timers[$arg1])
delete timers[$arg1]
}
}
F(ngx_http_lua_coctx_cleanup) {
println("lua tcp socket cleanup")
}
/*
F(ngx_http_finalize_request) {
printf("finalize request: c:%d, a:%d, cb:%d, rb:%d\n", $r->main->count,
$r == $r->connection->data, $r->connection->buffered, $r->buffered)
}
F(ngx_http_set_write_handler) {
println("set write handler")
}
*/
F(ngx_http_lua_flush_cleanup) {
println("lua flush cleanup")
}
_EOC_
--- stap_out
create 2 in 1
spawn user thread 2 in 1
add timer 100
add timer 200
expire timer 100
terminate 2: ok
delete thread 2
lua flush cleanup
delete timer 200
delete thread 1
add timer 200
expire timer 200
free request
--- ignore_response
--- no_error_log
[error]
=== TEST 4: flush wait - return "timeout" error
--- config
send_timeout 100ms;
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "failed to flush: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- ignore_response
--- error_log eval
[
qr/client timed out \(\d+: .*?timed out\)/,
'failed to flush: timeout',
]
--- no_error_log
[alert]
=== TEST 5: flush wait in multiple user threads - return "timeout" error
--- config
send_timeout 100ms;
location /test {
content_by_lua '
ngx.say("hello, world")
local function run(tag)
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "thread ", tag, ": failed to flush: ", err)
return
end
ngx.say("hiya")
end
local function new_thread(tag)
local ok, err = ngx.thread.spawn(run, tag)
if not ok then
return error("failed to spawn thread: ", err)
end
end
new_thread("A")
new_thread("B")
run("main")
';
}
--- request
GET /test
--- ignore_response
--- error_log eval
[
qr/client timed out \(\d+: .*?timed out\)/,
'thread main: failed to flush: timeout',
'thread A: failed to flush: timeout',
'thread B: failed to flush: timeout',
]
--- no_error_log
[alert]
=== TEST 6: flush wait - client abort connection prematurely
--- config
#send_timeout 100ms;
location /test {
limit_rate 2;
content_by_lua '
ngx.say("hello, lua")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "failed to flush: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- ignore_response
--- error_log eval
[
qr/writev\(\) failed .*? Broken pipe/i,
qr/failed to flush: client aborted/,
]
--- no_error_log
[alert]
--- timeout: 0.2
--- abort
--- wait: 1

File diff suppressed because it is too large Load diff

View file

@ -1,339 +0,0 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * (blocks() * 2 + 1);
$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();
no_long_string();
#no_shuffle();
run_tests();
__DATA__
=== TEST 1: connection refused (unix domain socket)
--- config
location /test {
content_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/tmp/nosuchfile.sock")
ngx.say("connect: ", ok, " ", err)
local bytes
bytes, err = sock:send("hello")
ngx.say("send: ", bytes, " ", err)
local line
line, err = sock:receive()
ngx.say("receive: ", line, " ", err)
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
}
--- request
GET /test
--- response_body
connect: nil no such file or directory
send: nil closed
receive: nil closed
close: nil closed
--- error_log eval
qr{\[crit\] .*? connect\(\) to unix:/tmp/nosuchfile\.sock failed}
=== TEST 2: invalid host argument
--- config
location /test {
content_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("/tmp/test-nginx.sock")
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
';
}
--- request
GET /test
--- response_body
failed to connect: missing the port number
=== TEST 3: sanity
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua 'ngx.say("foo")';
more_clear_headers Date;
}
}
--- config
location /test {
content_by_lua '
local sock = ngx.socket.tcp()
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 req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
print("calling receive")
local line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err)
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
}
--- request
GET /test
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed
close: 1 nil
=== TEST 4: ngx.socket.stream
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua_block { ngx.say("foo") }
more_clear_headers Date;
}
}
--- config
location /test {
content_by_lua_block {
local sock = ngx.socket.stream()
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 req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
print("calling receive")
local line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err)
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
}
}
--- request
GET /test
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed
close: 1 nil
=== TEST 5: port will be ignored
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua 'ngx.say("foo")';
more_clear_headers Date;
}
}
--- config
location /test {
content_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock", 80)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
print("calling receive")
local line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err)
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
}
--- request
GET /test
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed
close: 1 nil
=== TEST 6: second parameter is nil
--- http_config
server {
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock;
default_type 'text/plain';
server_tokens off;
location /foo {
content_by_lua 'ngx.say("foo")';
more_clear_headers Date;
}
}
--- config
location /test {
content_by_lua '
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock", nil)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected: ", ok)
local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
ngx.say("request sent: ", bytes)
while true do
print("calling receive")
local line, err = sock:receive()
if line then
ngx.say("received: ", line)
else
ngx.say("failed to receive a line: ", err)
break
end
end
ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
';
}
--- request
GET /test
--- response_body
connected: 1
request sent: 57
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 4
received: Connection: close
received:
received: foo
failed to receive a line: closed
close: 1 nil

Some files were not shown because too many files have changed in this diff Show more