Skip to content

Commit

Permalink
http/{h1_stream,request}: new stream property indicating if absolute …
Browse files Browse the repository at this point in the history
…form is desired
  • Loading branch information
daurnimator committed Mar 13, 2019
1 parent 91e69b5 commit 139b676
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
27 changes: 26 additions & 1 deletion http/h1_stream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ local function new_stream(connection)

req_method = nil; -- string
peer_version = nil; -- 1.0 or 1.1
use_absolute_target = nil; -- tristate boolean
has_main_headers = false;
headers_in_progress = nil;
headers_fifo = new_fifo();
Expand Down Expand Up @@ -648,8 +649,32 @@ function stream_methods:write_headers(headers, end_stream, timeout)
assert(not headers:has(":path"), "CONNECT requests should not have a path")
else
-- RFC 7230 Section 5.4: A client MUST send a Host header field in all HTTP/1.1 request messages.
assert(self.connection.version < 1.1 or headers:has(":authority"), "missing authority")
local has_authority = headers:has(":authority")
assert(has_authority or self.connection.version < 1.1, "missing authority")
target = assert(headers:get(":path"), "missing path")

local use_absolute_target = self.use_absolute_target
if use_absolute_target then
assert(has_authority, "request-target absolute-form requires an authority")
elseif use_absolute_target == nil then
use_absolute_target = has_authority
end
if use_absolute_target then
-- RFC 7230 Section 5.3.2
-- When making a request to a proxy, other than a CONNECT or server-wide
-- OPTIONS request (as detailed below), a client MUST send the target
-- URI in absolute-form as the request-target.
-- ...
-- To allow for transition to the absolute-form for all requests in some
-- future version of HTTP, a server MUST accept the absolute-form in
-- requests, even though HTTP/1.1 clients will only send them in
-- requests to proxies.
if target == "*" then
target = headers:get(":scheme") .. "://" .. headers:get(":authority")
else
target = headers:get(":scheme") .. "://" .. headers:get(":authority") .. target
end
end
end
if self.connection.req_locked then
-- Wait until previous request has been fully written
Expand Down
18 changes: 10 additions & 8 deletions http/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ function request_methods:go(timeout)
local port = self.port
local tls = self.tls
local version = self.version
local use_absolute_target

-- RFC 6797 Section 8.3
if not tls and self.hsts and self.hsts:check(host) then
Expand Down Expand Up @@ -456,17 +457,14 @@ function request_methods:go(timeout)
if request_headers:get(":method") == "CONNECT" then
error("cannot use HTTP Proxy with CONNECT method")
end
-- TODO: Check if :path already has authority?
local old_url = self:to_uri(false)
host = assert(proxy.host, "proxy is missing host")
port = proxy.port or http_util.scheme_to_port[proxy.scheme]
-- proxy requests get a uri that includes host as their path
if not cloned_headers then
request_headers = request_headers:clone()
cloned_headers = true -- luacheck: ignore 311
end
request_headers:upsert(":path", old_url)
use_absolute_target = true
if proxy.userinfo then
if not cloned_headers then
request_headers = request_headers:clone()
cloned_headers = true -- luacheck: ignore 311
end
request_headers:upsert("proxy-authorization", "basic " .. basexx.to_base64(proxy.userinfo), true)
end
end
Expand Down Expand Up @@ -520,6 +518,10 @@ function request_methods:go(timeout)
end
end

if use_absolute_target and connection.version < 2 then
stream.use_absolute_target = use_absolute_target
end

local body = self.body
do -- Write outgoing headers
local ok, err, errno = stream:write_headers(request_headers, body == nil, deadline and deadline-monotime())
Expand Down

0 comments on commit 139b676

Please sign in to comment.