Skip to content

Commit

Permalink
Pull header sending specifics into HTTP2 stream
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrudel committed Jan 27, 2024
1 parent e331223 commit 8a5ab3f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 17 deletions.
18 changes: 2 additions & 16 deletions lib/bandit/http2/adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,7 @@ defmodule Bandit.HTTP2.Adapter do
@impl Plug.Conn.Adapter
def inform(adapter, status, headers) do
validate_calling_process!(adapter)
headers = split_cookies(headers)
headers = [{":status", to_string(status)} | headers]
stream = Bandit.HTTP2.Stream.send_headers(adapter.stream, headers, false)
stream = Bandit.HTTP2.Stream.send_headers(adapter.stream, status, headers, false)
{:ok, %{adapter | stream: stream}}
end

Expand Down Expand Up @@ -262,8 +260,7 @@ defmodule Bandit.HTTP2.Adapter do
headers
end

headers = [{":status", to_string(status)} | split_cookies(headers)]
stream = Bandit.HTTP2.Stream.send_headers(adapter.stream, headers, end_stream)
stream = Bandit.HTTP2.Stream.send_headers(adapter.stream, status, headers, end_stream)
%{adapter | stream: stream, metrics: metrics}
end

Expand All @@ -274,17 +271,6 @@ defmodule Bandit.HTTP2.Adapter do
%{adapter | stream: stream, metrics: metrics}
end

defp split_cookies(headers) do
headers
|> Enum.flat_map(fn
{"cookie", cookie} ->
cookie |> String.split("; ") |> Enum.map(fn crumb -> {"cookie", crumb} end)

{header, value} ->
[{header, value}]
end)
end

defp validate_calling_process!(%{owner_pid: owner}) when owner == self(), do: :ok
defp validate_calling_process!(_), do: raise("Adapter functions must be called by stream owner")
end
15 changes: 14 additions & 1 deletion lib/bandit/http2/stream.ex
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,25 @@ defmodule Bandit.HTTP2.Stream do

# Stream API - Sending

def send_headers(%__MODULE__{state: state} = stream, headers, end_stream)
def send_headers(%__MODULE__{state: state} = stream, status, headers, end_stream)
when state in [:open, :remote_closed] do
headers = [{":status", to_string(status)} | split_cookies(headers)]
do_send(stream, {:send_headers, headers, end_stream})
set_state_on_send_end_stream(stream, end_stream)
end

# RFC9113§8.2.3 - cookie headers may be split during transmission
defp split_cookies(headers) do
headers
|> Enum.flat_map(fn
{"cookie", cookie} ->
cookie |> String.split("; ") |> Enum.map(fn crumb -> {"cookie", crumb} end)

{header, value} ->
[{header, value}]
end)
end

def send_data(%__MODULE__{state: state} = stream, data, end_stream)
when state in [:open, :remote_closed] do
stream =
Expand Down

0 comments on commit 8a5ab3f

Please sign in to comment.