blob: ca3708825b2be7193b08baa4f8805e9de5b4dd03 [file] [log] [blame] [raw]
# vim:set ft= ts=4 sw=4 et fdm=marker:
use lib 'lib';
use Test::Nginx::Socket::Lua;
repeat_each(2);
plan tests => repeat_each() * 36;
our $HtmlDir = html_dir;
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
#log_level 'warn';
log_level 'debug';
#no_long_string();
#no_diff();
run_tests();
__DATA__
=== TEST 1: sanity
--- config
server_tokens off;
location = /t {
#set $port 5000;
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua '
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local req = "GET /mysock HTTP/1.1\\r\\nUpgrade: mysock\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\nhello"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
local reader = sock:receiveuntil("\\r\\n\\r\\n")
local data, err, partial = reader()
if not data then
ngx.say("no response header found")
return
end
local msg, err = sock:receive()
if not msg then
ngx.say("failed to receive: ", err)
return
end
ngx.say("msg: ", msg)
ok, err = sock:close()
if not ok then
ngx.say("failed to close socket: ", err)
return
end
';
}
location = /mysock {
content_by_lua '
ngx.status = 101
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local data, err = sock:receive(5)
if not data then
ngx.log(ngx.ERR, "server: failed to receive: ", err)
return
end
local bytes, err = sock:send("1: received: " .. data .. "\\n")
if not bytes then
ngx.log(ngx.ERR, "server: failed to send: ", err)
return
end
';
more_clear_headers Date;
}
--- request
GET /t
--- response_body
msg: 1: received: hello
--- error_log
lua raw req socket tcp_nodelay
--- no_error_log
[error]
=== TEST 2: header not sent yet
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.status = 101
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local ok, err = sock:send("HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nhello")
if not ok then
ngx.log(ngx.ERR, "failed to send: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.0\r
Host: localhost\r
Content-Length: 5\r
\r
hello"
--- response_headers
Content-Length: 5
--- response_body chop
hello
--- no_error_log
[error]
=== TEST 3: http 1.0 buffering
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.say("hello")
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return ngx.exit(500)
end
';
}
--- raw_request eval
"GET /t HTTP/1.0\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- stap2
F(ngx_http_header_filter) {
println("header filter")
}
F(ngx_http_lua_req_socket) {
println("lua req socket")
}
--- ignore_response
--- error_log
server: failed to get raw req socket: http 1.0 buffering
=== TEST 4: multiple raw req sockets
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.say("hello")
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local sock2, err = ngx.req.socket(true)
if not sock2 then
ngx.log(ngx.ERR, "server: failed to get raw req socket2: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- stap2
F(ngx_http_header_filter) {
println("header filter")
}
F(ngx_http_lua_req_socket) {
println("lua req socket")
}
--- ignore_response
--- error_log
server: failed to get raw req socket2: duplicate call
=== TEST 5: ngx.say after ngx.req.socket(true)
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local ok, err = ngx.say("ok")
if not ok then
ngx.log(ngx.ERR, "failed to say: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- ignore_response
--- error_log
failed to say: raw request socket acquired
=== TEST 6: ngx.print after ngx.req.socket(true)
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local ok, err = ngx.print("ok")
if not ok then
ngx.log(ngx.ERR, "failed to print: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- ignore_response
--- error_log
failed to print: raw request socket acquired
=== TEST 7: ngx.eof after ngx.req.socket(true)
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local ok, err = ngx.eof()
if not ok then
ngx.log(ngx.ERR, "failed to eof: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- ignore_response
--- error_log
failed to eof: raw request socket acquired
=== TEST 8: ngx.flush after ngx.req.socket(true)
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local ok, err = ngx.flush()
if not ok then
ngx.log(ngx.ERR, "failed to flush: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
\r
hello"
--- ignore_response
--- error_log
failed to flush: raw request socket acquired
=== TEST 9: receive timeout
--- config
server_tokens off;
postpone_output 1;
location = /t {
content_by_lua '
ngx.send_headers()
ngx.req.read_body()
ngx.flush(true)
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
sock:settimeout(100)
local data, err, partial = sock:receive(10)
if not data then
ngx.log(ngx.ERR, "server: 1: failed to receive: ", err, ", received: ", partial)
end
data, err, partial = sock:receive(10)
if not data then
ngx.log(ngx.ERR, "server: 2: failed to receive: ", err, ", received: ", partial)
end
ngx.exit(444)
';
}
--- raw_request eval
"GET /t HTTP/1.1\r
Host: localhost\r
Upgrade: mysocket\r
Connection: close\r
\r
ab"
--- ignore_response
--- wait: 0.1
--- error_log
lua tcp socket read timed out
server: 1: failed to receive: timeout, received: ab,
server: 2: failed to receive: timeout, received: ,
--- no_error_log
[alert]
=== TEST 10: on_abort called during ngx.sleep()
--- config
server_tokens off;
lua_check_client_abort on;
location = /t {
#set $port 5000;
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua '
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local req = "GET /mysock HTTP/1.1\\r\\nUpgrade: mysock\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\nhello"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
local reader = sock:receiveuntil("\\r\\n\\r\\n")
local data, err, partial = reader()
if not data then
ngx.say("no response header found")
return
end
local msg, err = sock:receive()
if not msg then
ngx.say("failed to receive: ", err)
return
end
ngx.say("msg: ", msg)
ngx.sleep(0.1)
ok, err = sock:close()
if not ok then
ngx.say("failed to close socket: ", err)
return
end
';
}
location = /mysock {
content_by_lua '
ngx.status = 101
ngx.send_headers()
ngx.flush(true)
local ok, err = ngx.on_abort(function (premature) ngx.log(ngx.WARN, "mysock handler aborted") end)
if not ok then
ngx.log(ngx.ERR, "failed to set on_abort handler: ", err)
return
end
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local data, err = sock:receive(5)
if not data then
ngx.log(ngx.ERR, "server: failed to receive: ", err)
return
end
local bytes, err = sock:send("1: received: " .. data .. "\\n")
if not bytes then
ngx.log(ngx.ERR, "server: failed to send: ", err)
return
end
ngx.sleep(1)
';
more_clear_headers Date;
}
--- request
GET /t
--- response_body
msg: 1: received: hello
--- error_log
mysock handler aborted
--- no_error_log
[error]
--- wait: 1.1
=== TEST 11: on_abort called during sock:receive()
--- config
server_tokens off;
lua_check_client_abort on;
location = /t {
#set $port 5000;
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua '
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local req = "GET /mysock HTTP/1.1\\r\\nUpgrade: mysock\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\nhello"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
local reader = sock:receiveuntil("\\r\\n\\r\\n")
local data, err, partial = reader()
if not data then
ngx.say("no response header found")
return
end
local msg, err = sock:receive()
if not msg then
ngx.say("failed to receive: ", err)
return
end
ngx.say("msg: ", msg)
ngx.sleep(0.1)
ok, err = sock:close()
if not ok then
ngx.say("failed to close socket: ", err)
return
end
';
}
location = /mysock {
content_by_lua '
ngx.status = 101
ngx.send_headers()
ngx.flush(true)
local ok, err = ngx.on_abort(function (premature) ngx.log(ngx.WARN, "mysock handler aborted") end)
if not ok then
ngx.log(ngx.ERR, "failed to set on_abort handler: ", err)
return
end
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local data, err = sock:receive(5)
if not data then
ngx.log(ngx.ERR, "server: failed to receive: ", err)
return
end
local bytes, err = sock:send("1: received: " .. data .. "\\n")
if not bytes then
ngx.log(ngx.ERR, "server: failed to send: ", err)
return
end
local data, err = sock:receive()
if not data then
ngx.log(ngx.WARN, "failed to receive a line: ", err)
return
end
';
more_clear_headers Date;
}
--- request
GET /t
--- response_body
msg: 1: received: hello
--- error_log
failed to receive a line: client aborted
--- no_error_log
[error]
--- wait: 0.1
=== TEST 12: receiveuntil
--- config
server_tokens off;
location = /t {
#set $port 5000;
set $port $TEST_NGINX_SERVER_PORT;
content_by_lua '
local sock = ngx.socket.tcp()
local port = ngx.var.port
local ok, err = sock:connect("127.0.0.1", port)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local req = "GET /mysock HTTP/1.1\\r\\nUpgrade: mysock\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\nhello"
-- req = "OK"
local bytes, err = sock:send(req)
if not bytes then
ngx.say("failed to send request: ", err)
return
end
local bytes, err = sock:send(", ")
if not bytes then
ngx.say("failed to send packet 1: ", err)
return
end
local bytes, err = sock:send("world")
if not bytes then
ngx.say("failed to send packet 2: ", err)
return
end
local reader = sock:receiveuntil("\\r\\n\\r\\n")
local data, err, partial = reader()
if not data then
ngx.say("no response header found")
return
end
local msg, err = sock:receive()
if not msg then
ngx.say("failed to receive: ", err)
return
end
ngx.say("msg: ", msg)
ok, err = sock:close()
if not ok then
ngx.say("failed to close socket: ", err)
return
end
';
}
location = /mysock {
content_by_lua '
ngx.status = 101
ngx.send_headers()
ngx.flush(true)
ngx.req.read_body()
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local reader = sock:receiveuntil("rld")
local data, err = reader()
if not data then
ngx.log(ngx.ERR, "server: failed to receive: ", err)
return
end
local bytes, err = sock:send("1: received: " .. data .. "\\n")
if not bytes then
ngx.log(ngx.ERR, "server: failed to send: ", err)
return
end
';
more_clear_headers Date;
}
--- request
GET /t
--- response_body
msg: 1: received: hello, wo
--- no_error_log
[error]
=== TEST 13: request body not read yet
--- config
server_tokens off;
location = /t {
content_by_lua '
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err)
return
end
local data, err = sock:receive(5)
if not data then
ngx.log(ngx.ERR, "failed to receive: ", err)
return
end
local ok, err = sock:send("HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\n" .. data)
if not ok then
ngx.log(ngx.ERR, "failed to send: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.0\r
Host: localhost\r
Content-Length: 5\r
\r
hello"
--- response_headers
Content-Length: 5
--- response_body chop
hello
--- no_error_log
[error]
=== TEST 14: pending request body reading
--- config
server_tokens off;
location = /t {
content_by_lua '
ngx.thread.spawn(function ()
ngx.req.read_body()
end)
local sock, err = ngx.req.socket(true)
if not sock then
ngx.log(ngx.WARN, "server: failed to get raw req socket: ", err)
return ngx.exit(444)
end
local data, err = sock:receive(5)
if not data then
ngx.log(ngx.ERR, "failed to receive: ", err)
return
end
local ok, err = sock:send("HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\n" .. data)
if not ok then
ngx.log(ngx.ERR, "failed to send: ", err)
return
end
';
}
--- raw_request eval
"GET /t HTTP/1.0\r
Host: localhost\r
Content-Length: 5\r
\r
hell"
--- ignore_response
--- no_error_log
[error]
[alert]
--- error_log
server: failed to get raw req socket: pending request body reading in some other thread