Current section
Files
Jump to
Current section
Files
lib/reverse_proxy_plug/http_client/adapters/tesla.ex
if Code.ensure_loaded?(Tesla) do
defmodule ReverseProxyPlug.HTTPClient.Adapters.Tesla do
@moduledoc """
Tesla adapter for the `ReverseProxyPlug.HTTPClient` behaviour
Buffer response mode is supported for all Tesla versions.
Stream response mode is supported for Tesla 1.9.0 and up when using
the Finch adapter.
## Options
* `:tesla_client` - mandatory definition for the `Tesla.Client`
to be used.
"""
alias ReverseProxyPlug.HTTPClient
@behaviour HTTPClient
@minimum_tesla_version_for_stream Version.parse!("1.9.0")
@tesla_version Application.spec(:tesla, :vsn) |> to_string() |> Version.parse!()
@impl HTTPClient
def request(%HTTPClient.Request{options: options} = request) do
{client, opts} = Keyword.pop(options, :tesla_client)
unless client do
raise ":tesla_client option is required"
end
query =
if is_map(request.query_params),
do: Map.to_list(request.query_params),
else: request.query_params
tesla_opts =
request
|> Map.take([:url, :method, :body, :headers])
|> Map.put(:query, query)
|> Map.put(:opts, opts)
|> Enum.reject(fn {_k, v} -> is_nil(v) end)
case Tesla.request(client, tesla_opts) do
{:ok, %Tesla.Env{} = env} ->
{:ok,
%HTTPClient.Response{
status_code: env.status,
body: env.body,
headers: env.headers,
request_url: env.url,
request: request
}}
{:error, error} ->
{:error, %HTTPClient.Error{reason: error}}
end
end
if Version.compare(@tesla_version, @minimum_tesla_version_for_stream) in [:gt, :eq] do
@impl HTTPClient
def request_stream(%HTTPClient.Request{options: options} = req) do
case request(%{req | options: Keyword.merge(options, adapter: [response: :stream])}) do
{:ok, %HTTPClient.Response{status_code: status_code, headers: headers, body: body}} ->
{:ok,
Stream.concat(
[
{:status, status_code},
{:headers, headers}
],
Stream.map(body, &{:chunk, &1})
)}
{:error, _} = error ->
error
end
end
end
end
end