# vim:set ft= ts=4 sw=4 et: use Test::Nginx::Socket::Lua; use Cwd qw(cwd); use Protocol::WebSocket::Frame; repeat_each(2); plan tests => repeat_each() * (blocks() * 4 + 1); my $pwd = cwd(); our $HttpConfig = qq{ lua_package_path "$pwd/lib/?.lua;;"; lua_package_cpath "/usr/local/openresty-debug/lualib/?.so;/usr/local/openresty/lualib/?.so;;"; }; $ENV{TEST_NGINX_RESOLVER} = '8.8.8.8'; $ENV{TEST_NGINX_REDIS_PORT} ||= 6379; check_accum_error_log(); no_long_string(); #no_diff(); sub read_file { my $infile = shift; open my $in, $infile or die "cannot open $infile for reading: $!"; my $cert = do { local $/; <$in> }; close $in; $cert; } run_tests(); __DATA__ === TEST 1: text frame --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end ngx.say("1: received: ", data, " (", typ, ")") local bytes, err = wb:send_text("copy: " .. data) if not bytes then ngx.say("failed to send frame: ", err) return end data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("2: received: ", data, " (", typ, ")") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end '; } --- request GET /c --- response_body 1: received: 你好, WebSocket! (text) 2: received: copy: 你好, WebSocket! (text) --- no_error_log [error] [warn] --- error_log recv_frame: mask bit: 0 recv_frame: mask bit: 1 === TEST 2: binary frame --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end ngx.say("1: received: ", data, " (", typ, ")") local bytes, err = wb:send_binary("copy: " .. data) if not bytes then ngx.say("failed to send frame: ", err) return end data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("2: received: ", data, " (", typ, ")") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local bytes, err = wb:send_binary("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! bytes, err = wb:send_binary(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end '; } --- request GET /c --- response_body 1: received: 你好, WebSocket! (binary) 2: received: copy: 你好, WebSocket! (binary) --- no_error_log [error] [warn] === TEST 3: close frame (without msg body) --- http_config eval: $::HttpConfig --- config lingering_close always; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_close() if not bytes then ngx.say("failed to send frame: ", err) return end wb:recv_frame() -- receive the close frame '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_close() if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) wb:send_close() '; } --- request GET /c --- response_body received close: : nil --- error_log received: close: : nil --- no_error_log [error] === TEST 4: close frame (with msg body) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_close(1000, "server, let\'s close!") if not bytes then ngx.say("failed to send frame: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_close(1001, "client, let\'s close!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received close: client, let's close!: 1001 --- error_log received: close: server, let's close!: 1000 --- no_error_log [error] === TEST 5: ping frame (without msg body) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_ping() if not bytes then ngx.say("failed to send frame: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_ping() if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received ping: : nil --- error_log received: ping: : nil --- no_error_log [error] === TEST 6: ping frame (with msg body) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_ping("hey, server?") if not bytes then ngx.say("failed to send frame: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_ping("hey, client?") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received ping: hey, client?: nil --- error_log received: ping: hey, server?: nil --- no_error_log [error] === TEST 7: pong frame (without msg body) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_pong() if not bytes then ngx.say("failed to send frame: ", err) return end wb:recv_frame() -- receive the close frame '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_pong() if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) wb:send_close() '; } --- request GET /c --- response_body received pong: : nil --- error_log received: pong: : nil --- no_error_log [error] === TEST 8: pong frame (with msg body) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_pong("halo, server!") if not bytes then ngx.say("failed to send frame: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_pong("halo, client!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received pong: halo, client!: nil --- error_log received: pong: halo, server!: nil --- no_error_log [error] === TEST 9: client recv timeout (set_timeout) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end wb:set_timeout(1) local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) else ngx.say("1: received: ", data, " (", typ, ")") end wb:set_timeout(1000) data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) else ngx.say("2: received: ", data, " (", typ, ")") end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.sleep(0.2) local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end '; } --- request GET /c --- response_body failed to receive 1st frame: failed to receive the first 2 bytes: timeout 2: received: 你好, WebSocket! (text) --- error_log lua tcp socket read timed out --- no_error_log [warn] === TEST 10: client recv timeout (timeout option) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new{ timeout = 100 } local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) else ngx.say("1: received: ", data, " (", typ, ")") end wb:set_timeout(1000) data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) else ngx.say("2: received: ", data, " (", typ, ")") end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.sleep(0.2) local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end '; } --- request GET /c --- response_body failed to receive 1st frame: failed to receive the first 2 bytes: timeout 2: received: 你好, WebSocket! (text) --- error_log lua tcp socket read timed out --- no_error_log [warn] === TEST 11: server recv timeout (set_timeout) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end ngx.sleep(0.2) local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.say("failed to send the 1st text: ", err) return ngx.exit(444) end ngx.say("ok") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end wb:set_timeout(1) local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive 1st frame: ", err) else ngx.log(ngx.WARN, "1: received: ", data, " (", typ, ")") end wb:set_timeout(1000) data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive 2nd frame: ", err) else ngx.log(ngx.WARN, "2: received: ", data, " (", typ, ")") end '; } --- request GET /c --- response_body ok --- error_log failed to receive 1st frame: failed to receive the first 2 bytes: timeout 2: received: 你好, WebSocket! (text) lua tcp socket read timed out === TEST 12: server recv timeout (in constructor) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end ngx.sleep(0.2) local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.say("failed to send the 1st text: ", err) return ngx.exit(444) end ngx.say("ok") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new{ timeout = 1 } if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive 1st frame: ", err) else ngx.log(ngx.WARN, "1: received: ", data, " (", typ, ")") end wb:set_timeout(1000) data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive 2nd frame: ", err) else ngx.log(ngx.WARN, "2: received: ", data, " (", typ, ")") end '; } --- request GET /c --- response_body ok --- error_log failed to receive 1st frame: failed to receive the first 2 bytes: timeout 2: received: 你好, WebSocket! (text) lua tcp socket read timed out --- timeout: 6 === TEST 13: reused upstream websocket connections (set_keepalive) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local connect_opts = { -- choose a unique keepalive pool name to ensure our first -- connection is not reused pool = ngx.var.request_id, } for i = 1, 3 do local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err, res = wb:connect(uri, connect_opts) if not ok then ngx.say("failed to connect: " .. err) return end if res == "connection reused" then ngx.say(res) else ngx.say("new connection") end local data = "hello " .. i local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:set_keepalive() if not ok then ngx.say("failed to recycle conn: ", err) return end end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end while true do local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end end '; } --- request GET /c --- response_body new connection received: hello 1 (text) connection reused received: hello 2 (text) connection reused received: hello 3 (text) --- no_error_log [error] [warn] --- error_log recv_frame: mask bit: 0 recv_frame: mask bit: 1 === TEST 14: pool option --- http_config eval: $::HttpConfig --- config lua_socket_log_errors off; location = /c2 { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s2" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri, { pool = "my_conn_pool" }) if not ok then ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end end local data, typ, err = wb:send_text("hello websocket") if not data then ngx.say("failed to receive 2nd frame: ", err) return end data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:set_keepalive() if not ok then ngx.say("failed to set keepalive: ", err) return end '; } location = /s2 { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end while true do local data, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to recv text: ", err) return ngx.exit(444) end local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end end '; } --- request GET /c2 --- response_body received: hello websocket (text) --- stap F(ngx_http_lua_socket_tcp_setkeepalive) { println("socket tcp set keepalive") } --- stap_out socket tcp set keepalive --- error_log lua tcp socket keepalive create connection pool for key "my_conn_pool" --- no_error_log [error] [warn] === TEST 15: text frame (send masked frames on the server side) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end ngx.say("1: received: ", data, " (", typ, ")") local bytes, err = wb:send_text("copy: " .. data) if not bytes then ngx.say("failed to send frame: ", err) return end data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("2: received: ", data, " (", typ, ")") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new{ send_masked = true } if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end ngx.sleep(0.001) -- lingering close '; } --- request GET /c --- response_body 1: received: 你好, WebSocket! (text) 2: received: copy: 你好, WebSocket! (text) --- no_error_log [error] [warn] recv_frame: mask bit: 0 --- error_log recv_frame: mask bit: 1 --- timeout: 6 === TEST 16: text frame (send unmasked frames on the client side) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new{ send_unmasked = true } local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end ngx.say("1: received: ", data, " (", typ, ")") local bytes, err = wb:send_text("copy: " .. data) if not bytes then ngx.say("failed to send frame: ", err) return end data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("2: received: ", data, " (", typ, ")") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local bytes, err = wb:send_text("你好, WebSocket!") if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end ngx.sleep(0.001) -- lingering close '; } --- request GET /c --- response_body_like eval qr/^1: received: 你好, WebSocket! \(text\) (?:failed to receive 2nd frame: failed to receive the first 2 bytes: (?:closed|connection reset by peer) |failed to send frame: failed to send frame: broken pipe)$/ --- no_error_log [warn] --- error_log recv_frame: mask bit: 0 failed to receive a frame: frame unmasked === TEST 17: close frame (without msg body) + close() --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local bytes, err = wb:send_close() if not bytes then ngx.say("failed to send frame: ", err) return end local ok, err = wb:close() if not ok then ngx.say("failed to close: ", err) return end ngx.say("successfully closed the TCP connection") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_close() if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received close: : nil successfully closed the TCP connection --- error_log received: close: : nil sending the close frame --- no_error_log [error] === TEST 18: directly calling close() without sending the close frame ourselves --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end -- print("c: receiving frame") local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 1st frame: ", err) return end -- print("c: received frame") ngx.say("received ", typ, ": ", data, ": ", err) local ok, err = wb:close() if not ok then ngx.say("failed to close: ", err) return end ngx.say("successfully closed the TCP connection") '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end -- print("s: sending close") local bytes, err = wb:send_close() if not bytes then ngx.log(ngx.ERR, "failed to send the 1st text: ", err) return ngx.exit(444) end -- print("s: sent close") local data, typ, err = wb:recv_frame() if not data then ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end ngx.log(ngx.WARN, "received: ", typ, ": ", data, ": ", err) '; } --- request GET /c --- response_body received close: : nil successfully closed the TCP connection --- error_log received: close: : nil sending the close frame --- no_error_log [error] === TEST 19: client handshake (scalar protocols) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" math.randomseed(0) local wb, err = client:new() local uri = "ws://127.0.0.1:7986/" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri, { protocols = "json" }) if not ok then ngx.say("failed to connect: " .. err) return end '; } --- request GET /c --- tcp_listen: 7986 --- tcp_query eval "GET / HTTP/1.1\r Upgrade: websocket\r Host: 127.0.0.1:7986\r Sec-WebSocket-Key: y7KXwBSpVrxtkR0O+bQt+Q==\r Sec-WebSocket-Protocol: json\r Sec-WebSocket-Version: 13\r Connection: Upgrade\r \r " --- tcp_reply: blah --- response_body failed to connect: failed to receive response header: closed --- no_error_log [error] [warn] === TEST 20: client handshake (table protocols) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" math.randomseed(0) local wb, err = client:new() local uri = "ws://127.0.0.1:7986/" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri, { protocols = {"xml", "json"} }) if not ok then ngx.say("failed to connect: " .. err) return end '; } --- request GET /c --- tcp_listen: 7986 --- tcp_query eval "GET / HTTP/1.1\r Upgrade: websocket\r Host: 127.0.0.1:7986\r Sec-WebSocket-Key: y7KXwBSpVrxtkR0O+bQt+Q==\r Sec-WebSocket-Protocol: xml,json\r Sec-WebSocket-Version: 13\r Connection: Upgrade\r \r " --- tcp_reply: blah --- response_body failed to connect: failed to receive response header: closed --- no_error_log [error] [warn] === TEST 21: client handshake (origin) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua ' local client = require "resty.websocket.client" math.randomseed(0) local wb, err = client:new() local uri = "ws://127.0.0.1:7986/" -- ngx.say("uri: ", uri) local ok, err = wb:connect(uri, { origin = "test.com" }) if not ok then ngx.say("failed to connect: " .. err) return end '; } --- request GET /c --- tcp_listen: 7986 --- tcp_query eval "GET / HTTP/1.1\r Upgrade: websocket\r Host: 127.0.0.1:7986\r Sec-WebSocket-Key: y7KXwBSpVrxtkR0O+bQt+Q==\r Sec-WebSocket-Version: 13\r Origin: test.com\r Connection: Upgrade\r \r " --- tcp_reply: blah --- response_body failed to connect: failed to receive response header: closed --- no_error_log [error] [warn] === TEST 22: SSL with keepalive --- no_check_leak --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() for i = 1, 3 do local uri = "wss://127.0.0.1:12345/s" local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data = "hello " .. i local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:set_keepalive() if not ok then ngx.say("failed to recycle conn: ", err) return end end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end while true do local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end end '; } --- request GET /c --- response_body received: hello 1 (text) received: hello 2 (text) received: hello 3 (text) --- no_error_log [error] [warn] --- timeout: 10 === TEST 23: SSL without keepalive --- no_check_leak --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://127.0.0.1:12345/s" local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data = "hello" local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:close() if not ok then ngx.say("failed to close conn: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end '; } --- request GET /c --- response_body received: hello (text) --- no_error_log [error] [warn] --- timeout: 10 === TEST 24: SSL with ssl_verify --- no_check_leak --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; resolver 127.0.0.1:1953 ipv6=off; resolver_timeout 1s; lua_ssl_trusted_certificate ../../cert/test.crt; lua_ssl_verify_depth 1; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://test.com:12345/s" local ok, err = wb:connect(uri, {ssl_verify = true}) if not ok then ngx.say("failed to connect: " .. err) return end local data = "hello" local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:close() if not ok then ngx.say("failed to close conn: ", err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end '; } --- udp_listen: 1953 --- udp_reply eval sub { # Get DNS request ID from passed UDP datagram my $dns_id = unpack("n", shift); # Set name and encode it my $name = "test.com"; $name =~ s/([^.]+)\.?/chr(length($1)) . $1/ge; $name .= "\0"; my $s = ''; $s .= pack("n", $dns_id); # DNS response flags, hardcoded my $flags = (1 << 15) + (0 << 11) + (0 << 10) + (0 << 9) + (1 << 8) + (1 << 7) + 0; $flags = pack("n", $flags); $s .= $flags; $s .= pack("nnnn", 1, 1, 0, 0); $s .= $name; $s .= pack("nn", 1, 1); # Set response address and pack it my @addr = split /\./, "127.0.0.1"; my $data = pack("CCCC", @addr); $s .= $name. pack("nnNn", 1, 1, 1, 4) . $data; return $s; } --- request GET /c --- response_body received: hello (text) --- no_error_log [error] [warn] --- timeout: 10 === TEST 25: SSL with ssl_verify (handshake failed) --- no_check_leak --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; resolver 127.0.0.1:1953 ipv6=off; resolver_timeout 1s; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://test.com:12345/s" local ok, err = wb:connect(uri, {ssl_verify = true}) if not ok then ngx.say("failed to connect: " .. err) return end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end '; } --- udp_listen: 1953 --- udp_reply eval sub { # Get DNS request ID from passed UDP datagram my $dns_id = unpack("n", shift); # Set name and encode it my $name = "test.com"; $name =~ s/([^.]+)\.?/chr(length($1)) . $1/ge; $name .= "\0"; my $s = ''; $s .= pack("n", $dns_id); # DNS response flags, hardcoded my $flags = (1 << 15) + (0 << 11) + (0 << 10) + (0 << 9) + (1 << 8) + (1 << 7) + 0; $flags = pack("n", $flags); $s .= $flags; $s .= pack("nnnn", 1, 1, 0, 0); $s .= $name; $s .= pack("nn", 1, 1); # Set response address and pack it my @addr = split /\./, "127.0.0.1"; my $data = pack("CCCC", @addr); $s .= $name. pack("nnNn", 1, 1, 1, 4) . $data; return $s; } --- request GET /c --- error_log lua ssl certificate verify error: (18: self signed certificate) --- timeout: 10 === TEST 26: SSL without ssl_verify --- no_check_leak --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua ' local client = require "resty.websocket.client" local wb, err = client:new() for i = 1, 3 do local uri = "wss://127.0.0.1:12345/s" local ok, err = wb:connect(uri, {ssl_verify = false}) if not ok then ngx.say("failed to connect: " .. err) return end local data = "hello " .. i local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:set_keepalive() if not ok then ngx.say("failed to close conn: ", err) return end end '; } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end while true do local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end end '; } --- request GET /c --- response_body received: hello 1 (text) received: hello 2 (text) received: hello 3 (text) --- no_error_log [error] [warn] --- timeout: 10 === TEST 27: handhake with custom headers --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local headers = { "a-header: a header value", "another-header: another header value", "yet-another-header: yet another header value" } local ok, err = wb:connect(uri, {headers = headers}) if not ok then ngx.say("failed to connect: " .. err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end for k, v in pairs(ngx.req.get_headers()) do print(string.format("%s = %s", k, v)) end } } --- request GET /c --- error_log a-header = a header value another-header = another header value yet-another-header = yet another header value === TEST 28: send invalid close status code --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: " .. err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive: ", err) return end ngx.say("received ", typ, ": ", data, ": ", err) } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local bytes, err = wb:send_close(0xf000, "client, let\'s close!") if not bytes then ngx.log(ngx.ERR, "failed to send close: ", err) return ngx.exit(444) end } } --- request GET /c --- response_body failed to receive: failed to receive the first 2 bytes: closed --- error_log failed to send close: bad status code === TEST 29: mutual TLS with client certs --- no_check_leak --- http_config eval: $::HttpConfig --- config listen $TEST_NGINX_RAND_PORT_1 ssl; server_name test.com; ssl_certificate ../../cert/mtls_server.crt; ssl_certificate_key ../../cert/mtls_server.key; ssl_client_certificate ../../cert/mtls_ca.crt; ssl_verify_client on; server_tokens off; resolver 127.0.0.1:1953 ipv6=off; resolver_timeout 1s; lua_ssl_trusted_certificate ../../cert/mtls_ca.crt; lua_ssl_verify_depth 2; location = /c { content_by_lua_block { local ssl = require "ngx.ssl" local f = assert(io.open('t/cert/mtls_client.crt')) local cert_data = f:read("*a") f:close() f = assert(io.open('t/cert/mtls_client.key')) local key_data = f:read("*a") f:close() local chain = assert(ssl.parse_pem_cert(cert_data)) local priv = assert(ssl.parse_pem_priv_key(key_data)) local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://test.com:$TEST_NGINX_RAND_PORT_1/s" local ok, err = wb:connect(uri, {ssl_verify = true, client_cert = chain, client_priv_key = priv}) if not ok then ngx.say("failed to connect: " .. err) return end local data = "hello" local bytes, err = wb:send_text(data) if not bytes then ngx.say("failed to send frame: ", err) return end local typ data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive 2nd frame: ", err) return end ngx.say("received: ", data, " (", typ, ")") local ok, err = wb:close() if not ok then ngx.say("failed to close conn: ", err) return end } } location = /s { content_by_lua ' local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end local data, typ, err = wb:recv_frame() if not data then -- ngx.log(ngx.ERR, "failed to receive a frame: ", err) return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send the 2nd text: ", err) return ngx.exit(444) end '; } --- udp_listen: 1953 --- udp_reply eval sub { # Get DNS request ID from passed UDP datagram my $dns_id = unpack("n", shift); # Set name and encode it my $name = "test.com"; $name =~ s/([^.]+)\.?/chr(length($1)) . $1/ge; $name .= "\0"; my $s = ''; $s .= pack("n", $dns_id); # DNS response flags, hardcoded my $flags = (1 << 15) + (0 << 11) + (0 << 10) + (0 << 9) + (1 << 8) + (1 << 7) + 0; $flags = pack("n", $flags); $s .= $flags; $s .= pack("nnnn", 1, 1, 0, 0); $s .= $name; $s .= pack("nn", 1, 1); # Set response address and pack it my @addr = split /\./, "127.0.0.1"; my $data = pack("CCCC", @addr); $s .= $name. pack("nnNn", 1, 1, 1, 4) . $data; return $s; } --- request GET /c --- response_body received: hello (text) --- no_error_log [error] [warn] --- timeout: 10 === TEST 30: handshake with default host header --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local ok, err = wb:connect(uri) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") } } --- request GET /c --- error_log eval qr/host: <127.0.0.1:\d+>/ === TEST 31: handshake with custom host header (without port number) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local ok, err = wb:connect(uri, { host = "client.test" }) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") } } --- request GET /c --- error_log host: === TEST 32: handshake with custom host header (with port number) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local ok, err = wb:connect(uri, { host = "client.test:8080" }) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") } } --- request GET /c --- error_log host: === TEST 33: SNI derived from custom host header (without port number) --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://127.0.0.1:12345/s" local opts = { host = "test.com", ssl_verify = false, } local ok, err = wb:connect(uri, opts) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") ngx.log(ngx.INFO, "SSL server name: <", ngx.var.ssl_server_name, ">") } } --- request GET /c --- error_log host: SSL server name: === TEST 34: SNI derived from custom host header (with port number) --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://127.0.0.1:12345/s" local opts = { host = "test.com:8443", ssl_verify = false, } local ok, err = wb:connect(uri, opts) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") ngx.log(ngx.INFO, "SSL server name: <", ngx.var.ssl_server_name, ">") } } --- request GET /c --- error_log host: SSL server name: === TEST 35: custom SNI --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com client.test; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://127.0.0.1:12345/s" local opts = { server_name = "test.com", ssl_verify = false, } local ok, err = wb:connect(uri, opts) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") ngx.log(ngx.INFO, "SSL server name: <", ngx.var.ssl_server_name, ">") } } --- request GET /c --- error_log eval [ qr/host: <127.0.0.1:\d+>/, "SSL server name: ", ] === TEST 36: custom SNI and host --- http_config eval: $::HttpConfig --- config listen 12345 ssl; server_name test.com client.test; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "wss://127.0.0.1:12345/s" local opts = { host = "client.test", server_name = "test.com", ssl_verify = false, } local ok, err = wb:connect(uri, opts) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "host: <", ngx.var.http_host, ">") ngx.log(ngx.INFO, "SSL server name: <", ngx.var.ssl_server_name, ">") } } --- request GET /c --- error_log host: SSL server name: === TEST 37: overriding the Sec-WebSocket-Key header --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local opts = { key = "y7KXwBSpVrxtkR0O+bQt+Q==", } local ok, err = wb:connect(uri, opts) if not ok then ngx.say("failed to connect: ", err) return end } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end ngx.log(ngx.INFO, "key: ", ngx.var.http_sec_websocket_key) } } --- request GET /c --- error_log key: y7KXwBSpVrxtkR0O+bQt+Q== === TEST 38: server handshake response string --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local ok, err, res = wb:connect(uri) if not ok then ngx.say("failed to connect: ", err) return end if not res then ngx.say("no response string") return end ngx.say(res) } } location = /s { content_by_lua_block { ngx.header["X-My-Custom-Header"] = "test" local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end } } --- request GET /c --- response_body_like ^HTTP\/1\.1 101 Switching Protocols.*X-My-Custom-Header: test.* --- no_error_log [error] [warn] === TEST 39: server handshake response string (reused connection) --- http_config eval: $::HttpConfig --- config location = /c { content_by_lua_block { local client = require "resty.websocket.client" local wb, err = client:new() local uri = "ws://127.0.0.1:" .. ngx.var.server_port .. "/s" local connect_opts = { -- choose a unique keepalive pool name to ensure our first -- connection is not reused pool = ngx.var.request_id, } local ok, err, res = wb:connect(uri, connect_opts) if not ok then ngx.say("failed to connect: ", err) return end if not res then ngx.say("no response string") return end if not res:match("^HTTP/1%.1 101 Switching Protocols\r\n") then ngx.say("invalid response string") return end ok, err = wb:send_text("first connection") if not ok then ngx.say("failed to send message: ", err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive message: ", err) return end ngx.say("received ", typ, " frame: ", data) ok, err = wb:set_keepalive() if not ok then ngx.say("failed to enable keepalive: ", err) return end wb = client:new() ok, err, res = wb:connect(uri, connect_opts) if not ok then ngx.say("second connect failed: ", err) return end if res ~= "connection reused" then ngx.say("expected 'connection reused' response string") return end ok, err = wb:send_text("reused connection") if not ok then ngx.say("failed to send message: ", err) return end local data, typ, err = wb:recv_frame() if not data then ngx.say("failed to receive message: ", err) return end ngx.say("received ", typ, " frame: ", data) } } location = /s { content_by_lua_block { local server = require "resty.websocket.server" local wb, err = server:new() if not wb then ngx.log(ngx.ERR, "failed to new websocket: ", err) return ngx.exit(444) end while true do local data, typ, err = wb:recv_frame() if not data then return ngx.exit(444) end -- send it back! local bytes, err = wb:send_text(data) if not bytes then ngx.log(ngx.ERR, "failed to send text frame: ", err) return ngx.exit(444) end end } } --- request GET /c --- response_body received text frame: first connection received text frame: reused connection --- no_error_log [error] [warn]