Skip to content
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
5 changes: 3 additions & 2 deletions lib/mint/http2.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2340,12 +2340,13 @@ defmodule Mint.HTTP2 do
# RFC 9113 8.1.1: a response with content is malformed if the sum of the DATA
# frame payload lengths doesn't equal the content-length header value. Responses
# to HEAD and 204 and 304 responses must not have content, whatever their
# content-length header says, and 2xx responses to CONNECT carry tunnel data.
# content-length header says. Any 2xx response to CONNECT, including 204,
# establishes a tunnel (RFC 9110 9.3.6, RFC 9113 8.5) and carries tunnel data.
defp response_content_length(%{method: method}, status, headers) do
cond do
method == "HEAD" -> {:ok, 0}
status in [204, 304] -> {:ok, 0}
method == "CONNECT" and status in 200..299 -> {:ok, nil}
status in [204, 304] -> {:ok, 0}
true -> content_length(headers)
end
end
Expand Down
27 changes: 27 additions & 0 deletions test/mint/http2/conn_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4306,6 +4306,33 @@ defmodule Mint.HTTP2Test do
assert HTTP2.open?(conn)
end

test "a 204 response establishes the tunnel", %{conn: conn} do
assert {:ok, conn, ref} = HTTP2.request(conn, "CONNECT", "example.com:443", [], :stream)

assert_recv_frames [headers(stream_id: stream_id)]

hbf = server_encode_headers([{":status", "204"}])

assert {:ok, %HTTP2{} = conn, responses} =
stream_frames(conn, [
headers(
stream_id: stream_id,
hbf: hbf,
flags: set_flags(:headers, [:end_headers])
),
data(stream_id: stream_id, data: "hello", flags: set_flags(:data, [:end_stream]))
])

assert responses == [
{:status, ref, 204},
{:headers, ref, []},
{:data, ref, "hello"},
{:done, ref}
]

assert HTTP2.open?(conn)
end

test "an END_STREAM from the server closes the whole tunnel", %{conn: conn} do
assert {:ok, conn, ref} = HTTP2.request(conn, "CONNECT", "example.com:443", [], :stream)

Expand Down
Loading