Skip to content

Commit ed3eb4f

Browse files
committed
http/{h1_stream,request}: new stream property indicating if absolute form is desired
1 parent 91e69b5 commit ed3eb4f

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

http/h1_stream.lua

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ local function new_stream(connection)
7777

7878
req_method = nil; -- string
7979
peer_version = nil; -- 1.0 or 1.1
80+
use_absolute_target = nil; -- tristate boolean
8081
has_main_headers = false;
8182
headers_in_progress = nil;
8283
headers_fifo = new_fifo();
@@ -648,8 +649,27 @@ function stream_methods:write_headers(headers, end_stream, timeout)
648649
assert(not headers:has(":path"), "CONNECT requests should not have a path")
649650
else
650651
-- RFC 7230 Section 5.4: A client MUST send a Host header field in all HTTP/1.1 request messages.
651-
assert(self.connection.version < 1.1 or headers:has(":authority"), "missing authority")
652+
local has_authority = headers:has(":authority")
653+
assert(has_authority or self.connection.version < 1.1, "missing authority")
652654
target = assert(headers:get(":path"), "missing path")
655+
656+
if self.use_absolute_target ~= false then
657+
-- RFC 7230 Section 5.3.2
658+
-- When making a request to a proxy, other than a CONNECT or server-wide
659+
-- OPTIONS request (as detailed below), a client MUST send the target
660+
-- URI in absolute-form as the request-target.
661+
-- ...
662+
-- To allow for transition to the absolute-form for all requests in some
663+
-- future version of HTTP, a server MUST accept the absolute-form in
664+
-- requests, even though HTTP/1.1 clients will only send them in
665+
-- requests to proxies.
666+
assert(has_authority, "absolute-form requires an authority")
667+
if target ~= "*" then
668+
target = headers:get(":scheme") .. "://" .. headers:get(":authority") .. target
669+
else
670+
target = headers:get(":scheme") .. "://" .. headers:get(":authority")
671+
end
672+
end
653673
end
654674
if self.connection.req_locked then
655675
-- Wait until previous request has been fully written

http/request.lua

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ function request_methods:go(timeout)
358358
local port = self.port
359359
local tls = self.tls
360360
local version = self.version
361+
local use_absolute_target
361362

362363
-- RFC 6797 Section 8.3
363364
if not tls and self.hsts and self.hsts:check(host) then
@@ -456,17 +457,14 @@ function request_methods:go(timeout)
456457
if request_headers:get(":method") == "CONNECT" then
457458
error("cannot use HTTP Proxy with CONNECT method")
458459
end
459-
-- TODO: Check if :path already has authority?
460-
local old_url = self:to_uri(false)
461460
host = assert(proxy.host, "proxy is missing host")
462461
port = proxy.port or http_util.scheme_to_port[proxy.scheme]
463-
-- proxy requests get a uri that includes host as their path
464-
if not cloned_headers then
465-
request_headers = request_headers:clone()
466-
cloned_headers = true -- luacheck: ignore 311
467-
end
468-
request_headers:upsert(":path", old_url)
462+
use_absolute_target = true
469463
if proxy.userinfo then
464+
if not cloned_headers then
465+
request_headers = request_headers:clone()
466+
cloned_headers = true -- luacheck: ignore 311
467+
end
470468
request_headers:upsert("proxy-authorization", "basic " .. basexx.to_base64(proxy.userinfo), true)
471469
end
472470
end
@@ -520,6 +518,10 @@ function request_methods:go(timeout)
520518
end
521519
end
522520

521+
if use_absolute_target and connection.version < 2 then
522+
stream.use_absolute_target = use_absolute_target
523+
end
524+
523525
local body = self.body
524526
do -- Write outgoing headers
525527
local ok, err, errno = stream:write_headers(request_headers, body == nil, deadline and deadline-monotime())

0 commit comments

Comments
 (0)