zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

unsafe_proxy.ex (5966B)


      1 defmodule Mint.UnsafeProxy do
      2   @moduledoc false
      3 
      4   alias Mint.{Types, UnsafeProxy}
      5 
      6   @behaviour Mint.Core.Conn
      7 
      8   defstruct [
      9     :hostname,
     10     :port,
     11     :scheme,
     12     :module,
     13     :proxy_headers,
     14     :state
     15   ]
     16 
     17   @opaque t() :: %UnsafeProxy{}
     18 
     19   @type host_triple() :: {Types.scheme(), address :: Types.address(), :inet.port_number()}
     20 
     21   @spec connect(host_triple(), host_triple(), opts :: keyword()) ::
     22           {:ok, t()} | {:error, Types.error()}
     23   def connect(proxy, host, opts \\ []) do
     24     {proxy_scheme, proxy_address, proxy_port} = proxy
     25     {scheme, address, port} = host
     26     hostname = Mint.Core.Util.hostname(opts, address)
     27 
     28     with {:ok, state} <- Mint.HTTP1.connect(proxy_scheme, proxy_address, proxy_port, opts) do
     29       conn = %UnsafeProxy{
     30         scheme: scheme,
     31         hostname: hostname,
     32         port: port,
     33         module: Mint.HTTP1,
     34         proxy_headers: Keyword.get(opts, :proxy_headers, []),
     35         state: state
     36       }
     37 
     38       {:ok, conn}
     39     end
     40   end
     41 
     42   @impl true
     43   @spec initiate(
     44           module(),
     45           Mint.Types.socket(),
     46           String.t(),
     47           :inet.port_number(),
     48           keyword()
     49         ) :: no_return()
     50   def initiate(_transport, _transport_state, _hostname, _port, _opts) do
     51     raise "initiate/5 does not apply for #{inspect(__MODULE__)}"
     52   end
     53 
     54   @impl true
     55   @spec close(t()) :: {:ok, t()}
     56   def close(%UnsafeProxy{module: module, state: state} = _conn) do
     57     module.close(state)
     58   end
     59 
     60   @impl true
     61   @spec open?(t(), :read | :write | :read_write) :: boolean()
     62   def open?(%UnsafeProxy{module: module, state: state}, type \\ :read_write) do
     63     module.open?(state, type)
     64   end
     65 
     66   @impl true
     67   @spec request(
     68           t(),
     69           method :: String.t(),
     70           path :: String.t(),
     71           Types.headers(),
     72           body :: iodata() | nil | :stream
     73         ) ::
     74           {:ok, t(), Types.request_ref()}
     75           | {:error, t(), Types.error()}
     76   def request(
     77         %UnsafeProxy{module: module, state: state} = conn,
     78         method,
     79         path,
     80         headers,
     81         body \\ nil
     82       ) do
     83     path = request_line(conn, path)
     84     headers = headers ++ conn.proxy_headers
     85 
     86     case module.request(state, method, path, headers, body) do
     87       {:ok, state, request} -> {:ok, %{conn | state: state}, request}
     88       {:error, state, reason} -> {:error, %{conn | state: state}, reason}
     89     end
     90   end
     91 
     92   @impl true
     93   @spec stream_request_body(
     94           t(),
     95           Types.request_ref(),
     96           iodata() | :eof | {:eof, trailing_headers :: Types.headers()}
     97         ) ::
     98           {:ok, t()} | {:error, t(), Types.error()}
     99   def stream_request_body(%UnsafeProxy{module: module, state: state} = conn, ref, body) do
    100     case module.stream_request_body(state, ref, body) do
    101       {:ok, state} -> {:ok, %{conn | state: state}}
    102       {:error, state, reason} -> {:error, %{conn | state: state}, reason}
    103     end
    104   end
    105 
    106   @impl true
    107   @spec stream(t(), term()) ::
    108           {:ok, t(), [Types.response()]}
    109           | {:error, t(), Types.error(), [Types.response()]}
    110           | :unknown
    111   def stream(%UnsafeProxy{module: module, state: state} = conn, message) do
    112     case module.stream(state, message) do
    113       {:ok, state, responses} -> {:ok, %{conn | state: state}, responses}
    114       {:error, state, reason, responses} -> {:error, %{conn | state: state}, reason, responses}
    115       :unknown -> :unknown
    116     end
    117   end
    118 
    119   @impl true
    120   @spec open_request_count(t()) :: non_neg_integer()
    121   def open_request_count(%UnsafeProxy{module: module, state: state} = _conn) do
    122     module.open_request_count(state)
    123   end
    124 
    125   @impl true
    126   @spec recv(t(), non_neg_integer(), timeout()) ::
    127           {:ok, t(), [Types.response()]}
    128           | {:error, t(), Types.error(), [Types.response()]}
    129   def recv(%UnsafeProxy{module: module, state: state} = conn, byte_count, timeout) do
    130     case module.recv(state, byte_count, timeout) do
    131       {:ok, state, responses} -> {:ok, %{conn | state: state}, responses}
    132       {:error, state, reason, responses} -> {:error, %{conn | state: state}, reason, responses}
    133     end
    134   end
    135 
    136   @impl true
    137   @spec set_mode(t(), :active | :passive) :: {:ok, t()} | {:error, Types.error()}
    138   def set_mode(%UnsafeProxy{module: module, state: state} = conn, mode) do
    139     with {:ok, state} <- module.set_mode(state, mode) do
    140       {:ok, %{conn | state: state}}
    141     end
    142   end
    143 
    144   @impl true
    145   @spec controlling_process(t(), pid()) :: {:ok, t()} | {:error, Types.error()}
    146   def controlling_process(%UnsafeProxy{module: module, state: state} = conn, new_pid) do
    147     with {:ok, _} <- module.controlling_process(state, new_pid) do
    148       {:ok, conn}
    149     end
    150   end
    151 
    152   @impl true
    153   @spec put_private(t(), atom(), term()) :: t()
    154   def put_private(%UnsafeProxy{module: module, state: state} = conn, key, value) do
    155     state = module.put_private(state, key, value)
    156     %{conn | state: state}
    157   end
    158 
    159   @impl true
    160   @spec get_private(t(), atom(), term()) :: term()
    161   def get_private(%UnsafeProxy{module: module, state: state}, key, default \\ nil) do
    162     module.get_private(state, key, default)
    163   end
    164 
    165   @impl true
    166   @spec delete_private(t(), atom()) :: t()
    167   def delete_private(%UnsafeProxy{module: module, state: state} = conn, key) do
    168     state = module.delete_private(state, key)
    169     %{conn | state: state}
    170   end
    171 
    172   defp request_line(%UnsafeProxy{scheme: scheme, hostname: hostname, port: port}, path) do
    173     %URI{scheme: Atom.to_string(scheme), host: hostname, port: port, path: path}
    174     |> URI.to_string()
    175   end
    176 
    177   @impl true
    178   @spec get_socket(t()) :: Mint.Types.socket()
    179   def get_socket(%UnsafeProxy{module: module, state: state}) do
    180     module.get_socket(state)
    181   end
    182 
    183   # The `%__MODULE__{proxy_headers: value}` here is the request headers,
    184   # not the proxy response ones. Unsafe proxy mixes its headers (if any)
    185   # with the regular response headers, so you can get them there.
    186   @impl true
    187   @spec get_proxy_headers(t()) :: Mint.Types.headers()
    188   def get_proxy_headers(%__MODULE__{}), do: []
    189 end