diff --git a/lib/resty/http.lua b/lib/resty/http.lua index d575344..45e7b71 100644 --- a/lib/resty/http.lua +++ b/lib/resty/http.lua @@ -257,7 +257,7 @@ function _M.parse_uri(_, uri, query_in_path) local m, err = ngx_re_match( uri, - [[^(?:(http[s]?):)?//((?:[^\[\]:/\?]+)|(?:\[.+\]))(?::(\d+))?([^\?]*)\??(.*)]], + [[^(?:((?:http|ws)[s]?):)?\/\/((?:[^\[\]:\/\?]+)|(?:\[.+\]))(?::(\d+))?([^\?]*)\??(.*)]], "jo" ) @@ -289,7 +289,7 @@ function _M.parse_uri(_, uri, query_in_path) if m[3] then m[3] = tonumber(m[3]) else - if m[1] == "https" then + if m[1] == "https" or m[1] == "wss" then m[3] = 443 else m[3] = 80 diff --git a/lib/resty/http_connect.lua b/lib/resty/http_connect.lua index 25c4704..b90339c 100644 --- a/lib/resty/http_connect.lua +++ b/lib/resty/http_connect.lua @@ -48,14 +48,18 @@ local function connect(self, options) local backlog = options.backlog if request_scheme and not request_port then - request_port = (request_scheme == "https" and 443 or 80) + if request_scheme == "https" or request_scheme == "wss" then + request_port = 443 + else + request_port = 80 + end elseif request_port and not request_scheme then return nil, "'scheme' is required when providing a port" end -- ssl settings local ssl, ssl_reused_session, ssl_server_name, ssl_verify, ssl_send_status_req - if request_scheme == "https" then + if request_scheme == "https" or request_scheme == "wss" then ssl = true ssl_reused_session = options.ssl_reused_session ssl_server_name = options.ssl_server_name @@ -71,7 +75,7 @@ local function connect(self, options) proxy = options.proxy_opts or self.proxy_opts if proxy then - if request_scheme == "https" then + if request_scheme == "https" or request_scheme == "wss" then proxy_uri = proxy.https_proxy proxy_authorization = proxy.https_proxy_authorization else @@ -159,9 +163,9 @@ local function connect(self, options) .. ":" .. (ssl_server_name or "") .. ":" .. tostring(ssl_verify) .. ":" .. (proxy_uri or "") - .. ":" .. (request_scheme == "https" and proxy_authorization or "") + .. ":" .. ((request_scheme == "https" or request_scheme == "wss") and proxy_authorization or "") -- in the above we only add the 'proxy_authorization' as part of the poolname - -- when the request is https. Because in that case the CONNECT request (which + -- when the request uses SSL. Because in that case the CONNECT request (which -- carries the authorization header) is part of the connect procedure, whereas -- with a plain http request the authorization is part of the actual request. end @@ -229,8 +233,8 @@ local function connect(self, options) self.port = request_port self.keepalive = true self.ssl = ssl - -- set only for http, https has already been handled - self.http_proxy_auth = request_scheme ~= "https" and proxy_authorization or nil + -- set only for plain connections (http / ws), SSL connections (https / wss) were already handled + self.http_proxy_auth = (request_scheme ~= "https" and request_scheme ~= "wss") and proxy_authorization or nil self.path_prefix = path_prefix return true, nil, ssl_session diff --git a/t/01-basic.t b/t/01-basic.t index f3c413d..aedf778 100644 --- a/t/01-basic.t +++ b/t/01-basic.t @@ -389,3 +389,43 @@ GET /a --- no_error_log [error] [warn] + +=== TEST 15: WebSocket +--- http_config eval: $::HttpConfig +--- config + location = /a { + content_by_lua ' + local http = require "resty.http" + local httpc = http.new() + local ok, err = httpc:connect{ + scheme = "ws", + host = "127.0.0.1", + port = ngx.var.server_port + } + + local res, err = httpc:request{ + path = "/ws" + } + + ngx.status = res.status + ngx.say(res.reason) + ngx.print(res:read_body()) + + httpc:close() + '; + } + location = /ws { + content_by_lua ' + ngx.status = 101 + ngx.header["Upgrade"] = "websocket" + ngx.header["Connection"] = "Upgrade" + '; + } +--- request +GET /a +--- response_body +Switching Protocols +--- error_code: 101 +--- no_error_log +[error] +[warn] diff --git a/t/09-ssl.t b/t/09-ssl.t index 7c1e5da..c401f2c 100644 --- a/t/09-ssl.t +++ b/t/09-ssl.t @@ -62,3 +62,42 @@ GET /a --- no_error_log [error] [warn] + +=== TEST 3: parse_uri returns port 443 for wss URIs +--- http_config eval: $::HttpConfig +--- config + location = /a { + content_by_lua ' + local http = require "resty.http" + local httpc = http.new() + local parsed = httpc:parse_uri("wss://www.google.com/ws") + ngx.say(parsed[3]) + '; + } +--- request +GET /a +--- response_body +443 +--- no_error_log +[error] +[warn] + + +=== TEST 4: parse_uri returns port 80 for ws URIs +--- http_config eval: $::HttpConfig +--- config + location = /a { + content_by_lua ' + local http = require "resty.http" + local httpc = http.new() + local parsed = httpc:parse_uri("ws://www.google.com/ws") + ngx.say(parsed[3]) + '; + } +--- request +GET /a +--- response_body +80 +--- no_error_log +[error] +[warn]