| # vim:set ft= ts=4 sw=4 et fdm=marker: |
| |
| use lib 'lib'; |
| 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() * 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) |
| --- 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) |
| --- 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 |
| --- 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 ' |
| 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] |
| |