From 65c98e7447fc8779ed678e8222c08beb9f4bfc98 Mon Sep 17 00:00:00 2001 From: Guy Lewin Date: Fri, 22 Oct 2021 11:15:41 -0400 Subject: [PATCH 1/4] feat: support ws and wss scheme in http_connect.lua --- lib/resty/http_connect.lua | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/resty/http_connect.lua b/lib/resty/http_connect.lua index cbb102a..1afeecf 100644 --- a/lib/resty/http_connect.lua +++ b/lib/resty/http_connect.lua @@ -47,14 +47,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_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_server_name = options.ssl_server_name ssl_send_status_req = options.ssl_send_status_req @@ -69,7 +73,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 @@ -156,9 +160,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 @@ -224,8 +228,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 From d7b16e0f4911c7aa1a07a68553604c258e7df2f3 Mon Sep 17 00:00:00 2001 From: Guy Lewin Date: Wed, 24 Nov 2021 11:41:13 -0500 Subject: [PATCH 2/4] feat: add ws and wss support in parse_uri --- lib/resty/http.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 7f2abca0e78eec7c67c5379f544edb0d538a6e85 Mon Sep 17 00:00:00 2001 From: Guy Lewin Date: Wed, 24 Nov 2021 11:41:39 -0500 Subject: [PATCH 3/4] test: add tests for ws and wss parse_uri, and connection establishment using ws scheme --- t/01-basic.t | 41 +++++++++++++++++++++++++++++++++++++++++ t/09-ssl.t | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/t/01-basic.t b/t/01-basic.t index f3c413d..03dd9ee 100644 --- a/t/01-basic.t +++ b/t/01-basic.t @@ -389,3 +389,44 @@ 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 +OK +--- 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] From 18de9f6cd59d69bc5d4f5bb5e69f3fc229761bbc Mon Sep 17 00:00:00 2001 From: Guy Lewin Date: Wed, 24 Nov 2021 11:44:22 -0500 Subject: [PATCH 4/4] fix: test 15 in 01-basic.t expecting wrong response --- t/01-basic.t | 1 - 1 file changed, 1 deletion(-) diff --git a/t/01-basic.t b/t/01-basic.t index 03dd9ee..aedf778 100644 --- a/t/01-basic.t +++ b/t/01-basic.t @@ -425,7 +425,6 @@ GET /a GET /a --- response_body Switching Protocols -OK --- error_code: 101 --- no_error_log [error]