Skip to content
Merged
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
11 changes: 8 additions & 3 deletions http/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,16 @@ function request_methods:go(timeout)
if proxy then
if type(proxy) == "string" then
proxy = assert(uri_patt:match(proxy), "invalid proxy URI")
proxy.path = nil -- ignore proxy.path component
else
assert(type(proxy) == "table" and getmetatable(proxy) == nil and proxy.scheme, "invalid proxy URI")
proxy = {
scheme = proxy.scheme;
userinfo = proxy.userinfo;
host = proxy.host;
port = proxy.port;
-- ignore proxy.path component
}
end
if proxy.scheme == "http" or proxy.scheme == "https" then
if tls then
Expand Down Expand Up @@ -423,9 +431,6 @@ function request_methods:go(timeout)
if request_headers:get(":method") == "CONNECT" then
error("cannot use HTTP Proxy with CONNECT method")
end
if proxy.path ~= nil and proxy.path ~= "" then
error("an HTTP proxy cannot have a path component")
end
-- TODO: Check if :path already has authority?
local old_url = self:to_uri(false)
host = assert(proxy.host, "proxy is missing host")
Expand Down
52 changes: 52 additions & 0 deletions spec/request_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,30 @@ describe("http.request module", function()
stream:shutdown()
end)
end)
it("works with a proxy server with a path component", function()
test(function(stream)
local h = assert(stream:get_headers())
local _, host, port = stream:localname()
local authority = http_util.to_authority(host, port, "http")
assert.same(authority, h:get ":authority")
assert.same("http://" .. authority .. "/", h:get(":path"))
local resp_headers = new_headers()
resp_headers:append(":status", "200")
assert(stream:write_headers(resp_headers, false))
assert(stream:write_chunk("hello world", true))
end, function(req)
req.proxy = {
scheme = "http";
host = req.host;
port = req.port;
path = "/path";
}
local headers, stream = assert(req:go())
assert.same("200", headers:get(":status"))
assert.same("hello world", assert(stream:get_body_as_string()))
stream:shutdown()
end)
end)
it("works with http proxies on OPTIONS requests", function()
test(function(stream)
local h = assert(stream:get_headers())
Expand Down Expand Up @@ -716,6 +740,34 @@ describe("http.request module", function()
stream:shutdown()
end)
end)
it("CONNECT proxy with path component", function()
test(function(stream, s)
local h = assert(stream:get_headers())
local resp_headers = new_headers()
resp_headers:append(":status", "200")
assert(stream:write_headers(resp_headers, false))
if h:get(":method") == "CONNECT" then
assert(stream.connection.version < 2)
local sock = assert(stream.connection:take_socket())
s:add_socket(sock)
return true
else
assert(stream:write_chunk("hello world", true))
end
end, function(req)
req.tls = true
req.proxy = {
scheme = "http";
host = req.host;
port = req.port;
path = "/path";
}
local headers, stream = assert(req:go())
assert.same("200", headers:get(":status"))
assert.same("hello world", assert(stream:get_body_as_string()))
stream:shutdown()
end)
end)
it("fails correctly on non CONNECT proxy", function()
test(function(stream)
local h = assert(stream:get_headers())
Expand Down