Skip to content

Commit

Permalink
Support ALPN over HTTP1 pools
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Nov 14, 2023
1 parent 6b96517 commit 258281e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 92 deletions.
3 changes: 3 additions & 0 deletions lib/finch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ defmodule Finch do
since HTTP2 is able to multiplex requests through a single connection. In \
other words, for HTTP2, the size is always 1 and the `:count` should be \
configured in order to increase capacity.
For HTTP1 pools, the pool will force HTTP1 connections by default but you \
can perform ALPN over HTTP1 pools by setting the `:protocols` option.
""",
default: @default_pool_size
],
Expand Down
34 changes: 19 additions & 15 deletions lib/finch/http1/conn.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
defmodule Finch.Conn do
@moduledoc false

alias Finch.MintHTTP1
alias Finch.SSL
alias Finch.Telemetry

Expand Down Expand Up @@ -38,11 +37,16 @@ defmodule Finch.Conn do

start_time = Telemetry.start(:connect, meta)

# We have to use Mint's top-level connect function or else proxying won't work. So we
# force the connection to use http1 and call it in this roundabout way.
conn_opts = Keyword.merge(conn.opts, mode: :passive, protocols: [:http1])
# By default we force HTTP1, but we allow someone to set
# custom protocols in case they don't know if a connection
# is HTTP1/HTTP2, but they are fine as treating HTTP2
# connections has HTTP2.
conn_opts =
conn.opts
|> Keyword.put(:mode, :passive)
|> Keyword.put_new(:protocols, [:http1])

case MintHTTP1.connect(conn.scheme, conn.host, conn.port, conn_opts) do
case Mint.HTTP.connect(conn.scheme, conn.host, conn.port, conn_opts) do
{:ok, mint} ->
Telemetry.stop(:connect, start_time, meta)
SSL.maybe_log_secrets(conn.scheme, conn_opts, mint)
Expand All @@ -56,16 +60,16 @@ defmodule Finch.Conn do
end

def transfer(conn, pid) do
case MintHTTP1.controlling_process(conn.mint, pid) do
# MintHTTP1.controlling_process causes a side-effect, but it doesn't actually
case Mint.HTTP.controlling_process(conn.mint, pid) do
# Mint.HTTP.controlling_process causes a side-effect, but it doesn't actually
# change the conn, so we can ignore the value returned above.
{:ok, _} -> {:ok, conn}
{:error, error} -> {:error, conn, error}
end
end

def open?(%{mint: nil}), do: false
def open?(%{mint: mint}), do: MintHTTP1.open?(mint)
def open?(%{mint: mint}), do: Mint.HTTP.open?(mint)

def idle_time(conn, unit \\ :native) do
idle_time = System.monotonic_time() - conn.last_checkin
Expand All @@ -77,7 +81,7 @@ defmodule Finch.Conn do
def reusable?(%{max_idle_time: max_idle_time}, idle_time), do: idle_time <= max_idle_time

def set_mode(conn, mode) when mode in [:active, :passive] do
case MintHTTP1.set_mode(conn.mint, mode) do
case Mint.HTTP.set_mode(conn.mint, mode) do
{:ok, mint} -> {:ok, %{conn | mint: mint}}
_ -> {:error, "Connection is dead"}
end
Expand All @@ -86,7 +90,7 @@ defmodule Finch.Conn do
def discard(%{mint: nil}, _), do: :unknown

def discard(conn, message) do
case MintHTTP1.stream(conn.mint, message) do
case Mint.HTTP.stream(conn.mint, message) do
{:ok, mint, _responses} -> {:ok, %{conn | mint: mint}}
{:error, _, reason, _} -> {:error, reason}
:unknown -> :unknown
Expand All @@ -105,7 +109,7 @@ defmodule Finch.Conn do
start_time = Telemetry.start(:send, metadata, extra_measurements)

try do
case MintHTTP1.request(
case Mint.HTTP.request(
conn.mint,
req.method,
full_path,
Expand Down Expand Up @@ -167,23 +171,23 @@ defmodule Finch.Conn do

defp maybe_stream_request_body(mint, ref, {:stream, stream}) do
with {:ok, mint} <- stream_request_body(mint, ref, stream) do
MintHTTP1.stream_request_body(mint, ref, :eof)
Mint.HTTP.stream_request_body(mint, ref, :eof)
end
end

defp maybe_stream_request_body(mint, _, _), do: {:ok, mint}

defp stream_request_body(mint, ref, stream) do
Enum.reduce_while(stream, {:ok, mint}, fn
chunk, {:ok, mint} -> {:cont, MintHTTP1.stream_request_body(mint, ref, chunk)}
chunk, {:ok, mint} -> {:cont, Mint.HTTP.stream_request_body(mint, ref, chunk)}
_chunk, error -> {:halt, error}
end)
end

def close(%{mint: nil} = conn), do: conn

def close(conn) do
{:ok, mint} = MintHTTP1.close(conn.mint)
{:ok, mint} = Mint.HTTP.close(conn.mint)
%{conn | mint: mint}
end

Expand Down Expand Up @@ -252,7 +256,7 @@ defmodule Finch.Conn do
) do
start_time = System.monotonic_time(:millisecond)

case MintHTTP1.recv(mint, 0, timeouts.receive_timeout) do
case Mint.HTTP.recv(mint, 0, timeouts.receive_timeout) do
{:ok, mint, entries} ->
timeouts =
if is_integer(timeouts.request_timeout) do
Expand Down
77 changes: 0 additions & 77 deletions lib/finch/http1/mint_http1.ex

This file was deleted.

0 comments on commit 258281e

Please sign in to comment.