blob: 654c6d5e0e5e749c058a73aa528f365f4673691c [file] [log] [blame] [raw]
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket::Lua;
repeat_each(10);
plan tests => repeat_each() * (blocks() * 2 + 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;
#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 '
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")
ngx.say("rewrite a: " .. res.body)
res = ngx.location.capture("/b")
ngx.say("rewrite b: " .. res.body)
res = ngx.location.capture("/c")
ngx.say("rewrite c: " .. res.body)
';
access_by_lua '
local res = ngx.location.capture("/A")
ngx.say("access A: " .. res.body)
res = ngx.location.capture("/B")
ngx.say("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
rewrite a: a
rewrite b: b
rewrite c: c
access A: A
access B: B
content d: d
content e: e
content f: f
=== 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"},
}
ngx.say("rewrite a: " .. a.body)
ngx.say("rewrite b: " .. b.body)
ngx.say("rewrite c: " .. c.body)
';
access_by_lua '
local A, B = ngx.location.capture_multi{
{"/A"}, {"/B"},
}
ngx.say("access A: " .. A.body)
ngx.say("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
rewrite a: a
rewrite b: b
rewrite c: c
access A: A
access B: B
content d: d
content e: e
content f: f
=== 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://agentzh.org:12345;
proxy_cache_key $proxy_host$uri$args;
proxy_cache_valid any 1s;
#proxy_http_version 1.1;
}
--- request
GET /foo
--- response_body
ok