diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c index 964774041e..10aa7e9678 100644 --- a/src/ngx_http_lua_socket_tcp.c +++ b/src/ngx_http_lua_socket_tcp.c @@ -970,8 +970,16 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) n--; } - if (n == 3) { - port = luaL_checkinteger(L, 3); + /* most popular suit: host:port */ + if (n == 3 && lua_isnumber(L, 3)) { + + /* Hit the following parameter combination: + * sock:connect("127.0.0.1", port) + * sock:connect("127.0.0.1", port, opts) + * sock:connect("unix:/path", port) + * sock:connect("unix:/path", port, opts) */ + + port = (int) lua_tointeger(L, 3); if (port < 0 || port > 65535) { lua_pushnil(L); @@ -987,8 +995,27 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) dd("socket key: %s", lua_tostring(L, -1)); - } else { /* n == 2 */ + } else if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { + + /* Hit the following parameter combination: + * sock:connect("unix:/path") + * sock:connect("unix:/path", nil) + * sock:connect("unix:/path", opts) + * sock:connect("unix:/path", nil, opts) */ + port = 0; + + } else { + + /* Ban the following parameter combination: + * sock:connect("127.0.0.1") + * sock:connect("127.0.0.1", nil) + * sock:connect("127.0.0.1", opts) + * sock:connect("127.0.0.1", nil, opts) */ + + lua_pushnil(L); + lua_pushfstring(L, "missing the port number"); + return 2; } if (!custom_pool) { diff --git a/t/023-rewrite/unix-socket.t b/t/023-rewrite/unix-socket.t index 8a5f00019b..91826fc3eb 100644 --- a/t/023-rewrite/unix-socket.t +++ b/t/023-rewrite/unix-socket.t @@ -79,7 +79,7 @@ qr{\[crit\] .*? connect\(\) to unix:/tmp/nosuchfile\.sock failed} --- request GET /test --- response_body -failed to connect: failed to parse host name "/tmp/test-nginx.sock": invalid host +failed to connect: missing the port number diff --git a/t/058-tcp-socket.t b/t/058-tcp-socket.t index cac464d830..593e49461f 100644 --- a/t/058-tcp-socket.t +++ b/t/058-tcp-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 228; +plan tests => repeat_each() * 231; our $HtmlDir = html_dir; @@ -3029,7 +3029,7 @@ qr/runtime error: content_by_lua\(nginx\.conf:\d+\):16: bad request/ --- user_files >>> myfoo.lua local sock = ngx.socket.tcp() -local ok, err = sock:connect("agentzh.org") +local ok, err = sock:connect("agentzh.org", 12345) if not ok then ngx.log(ngx.ERR, "failed to connect: ", err) return @@ -3059,7 +3059,7 @@ runtime error: attempt to yield across C-call boundary end local function err() local sock = ngx.socket.tcp() - local ok, err = sock:connect("agentzh.org") + local ok, err = sock:connect("agentzh.org", 12345) if not ok then ngx.log(ngx.ERR, "failed to connect: ", err) return @@ -4327,3 +4327,43 @@ failed to receive a line: closed [] close: 1 nil --- no_error_log [error] + + + +=== TEST 72: port is not number +--- config + server_tokens off; + location = /t { + set $port $TEST_NGINX_SERVER_PORT; + content_by_lua_block { + local sock = ngx.socket.tcp() + sock:settimeout(500) + + local ok, err = sock:connect("127.0.0.1") + if not ok then + ngx.say("connect failed: ", err) + end + + local ok, err = sock:connect("127.0.0.1", nil) + if not ok then + ngx.say("connect failed: ", err) + end + + local ok, err = sock:connect("127.0.0.1", {}) + if not ok then + ngx.say("connect failed: ", err) + end + + ngx.say("finish") + } + } + +--- request +GET /t +--- response_body +connect failed: missing the port number +connect failed: missing the port number +connect failed: missing the port number +finish +--- no_error_log +[error] diff --git a/t/059-unix-socket.t b/t/059-unix-socket.t index b06ba6e2ee..bd83006baf 100644 --- a/t/059-unix-socket.t +++ b/t/059-unix-socket.t @@ -64,7 +64,7 @@ qr{\[crit\] .*? connect\(\) to unix:/tmp/nosuchfile\.sock failed} --- request GET /test --- response_body -failed to connect: failed to parse host name "/tmp/test-nginx.sock": invalid host +failed to connect: missing the port number @@ -201,3 +201,139 @@ received: received: foo failed to receive a line: closed close: 1 nil + + + +=== TEST 5: port will be ignored +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock; + default_type 'text/plain'; + + server_tokens off; + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + } +--- config + location /test { + content_by_lua ' + local sock = ngx.socket.tcp() + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock", 80) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n" + -- req = "OK" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + print("calling receive") + local line, err = sock:receive() + if line then + ngx.say("received: ", line) + + else + ngx.say("failed to receive a line: ", err) + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + '; + } +--- request + GET /test +--- response_body +connected: 1 +request sent: 57 +received: HTTP/1.1 200 OK +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +failed to receive a line: closed +close: 1 nil + + + +=== TEST 6: second parameter is nil +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock; + default_type 'text/plain'; + + server_tokens off; + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + } +--- config + location /test { + content_by_lua ' + local sock = ngx.socket.tcp() + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock", nil) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n" + -- req = "OK" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + print("calling receive") + local line, err = sock:receive() + if line then + ngx.say("received: ", line) + + else + ngx.say("failed to receive a line: ", err) + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + '; + } +--- request + GET /test +--- response_body +connected: 1 +request sent: 57 +received: HTTP/1.1 200 OK +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +failed to receive a line: closed +close: 1 nil diff --git a/t/068-socket-keepalive.t b/t/068-socket-keepalive.t index e4c698887b..d67da3bd1e 100644 --- a/t/068-socket-keepalive.t +++ b/t/068-socket-keepalive.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; #repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 31); +plan tests => repeat_each() * (blocks() * 4 + 34); our $HtmlDir = html_dir; @@ -2956,3 +2956,63 @@ GET /t lua tcp socket abort queueing --- response_body ok + + + +=== TEST 53: custom pools in third parameters for unix domain socket +--- http_config eval +" + lua_package_path '$::HtmlDir/?.lua;./?.lua;;'; + server { + listen unix:$::HtmlDir/nginx.sock; + default_type 'text/plain'; + + server_tokens off; + location /foo { + echo foo; + more_clear_headers Date; + } + } +" +--- config + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + content_by_lua ' + local test = require "test" + local path = "$TEST_NGINX_HTML_DIR/nginx.sock"; + test.go(path, "A") + test.go(path, "B") + '; + } +--- user_files +>>> test.lua +module("test", package.seeall) + +function go(path, pool) + local sock = ngx.socket.tcp() + local ok, err = sock:connect("unix:" .. path, nil, {pool = pool}) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok, ", reused: ", sock:getreusedtimes()) + + local ok, err = sock:setkeepalive() + if not ok then + ngx.say("failed to set reusable: ", err) + end +end +--- request +GET /t +--- response_body +connected: 1, reused: 0 +connected: 1, reused: 0 +--- no_error_log eval +["[error]", +"lua tcp socket keepalive: free connection pool for ", +"lua tcp socket get keepalive peer: using connection" +] +--- error_log +lua tcp socket keepalive create connection pool for key "A" +lua tcp socket keepalive create connection pool for key "B"