Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Support ws and wss scheme in http_connect.lua #256

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/resty/http.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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
Expand Down
18 changes: 11 additions & 7 deletions lib/resty/http_connect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions t/01-basic.t
Original file line number Diff line number Diff line change
Expand Up @@ -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]
39 changes: 39 additions & 0 deletions t/09-ssl.t
Original file line number Diff line number Diff line change
Expand Up @@ -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]