zf

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

rewrite_on.ex (2439B)


      1 defmodule Plug.RewriteOn do
      2   @moduledoc """
      3   A plug to rewrite the request's host/port/protocol from `x-forwarded-*` headers.
      4 
      5   If your Plug application is behind a proxy that handles HTTPS, you may
      6   need to tell Plug to parse the proper protocol from the `x-forwarded-*`
      7   header.
      8 
      9       plug Plug.RewriteOn, [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]
     10 
     11   The supported values are:
     12 
     13     * `:x_forwarded_host` - to override the host based on on the "x-forwarded-host" header
     14     * `:x_forwarded_port` - to override the port based on on the "x-forwarded-port" header
     15     * `:x_forwarded_proto` - to override the protocol based on on the "x-forwarded-proto" header
     16 
     17   Since rewriting the scheme based on `x-forwarded-*` headers can open up
     18   security vulnerabilities, only use this plug if:
     19 
     20     * your app is behind a proxy
     21     * your proxy strips the given `x-forwarded-*` headers from all incoming requests
     22     * your proxy sets the `x-forwarded-*` headers and sends it to Plug
     23   """
     24   @behaviour Plug
     25 
     26   import Plug.Conn, only: [get_req_header: 2]
     27 
     28   @impl true
     29   def init(header), do: List.wrap(header)
     30 
     31   @impl true
     32   def call(conn, [:x_forwarded_proto | rewrite_on]) do
     33     conn
     34     |> put_scheme(get_req_header(conn, "x-forwarded-proto"))
     35     |> call(rewrite_on)
     36   end
     37 
     38   def call(conn, [:x_forwarded_port | rewrite_on]) do
     39     conn
     40     |> put_port(get_req_header(conn, "x-forwarded-port"))
     41     |> call(rewrite_on)
     42   end
     43 
     44   def call(conn, [:x_forwarded_host | rewrite_on]) do
     45     conn
     46     |> put_host(get_req_header(conn, "x-forwarded-host"))
     47     |> call(rewrite_on)
     48   end
     49 
     50   def call(_conn, [other | _rewrite_on]) do
     51     raise "unknown rewrite: #{inspect(other)}"
     52   end
     53 
     54   def call(conn, []) do
     55     conn
     56   end
     57 
     58   defp put_scheme(%{scheme: :http, port: 80} = conn, ["https"]),
     59     do: %{conn | scheme: :https, port: 443}
     60 
     61   defp put_scheme(conn, ["https"]),
     62     do: %{conn | scheme: :https}
     63 
     64   defp put_scheme(%{scheme: :https, port: 443} = conn, ["http"]),
     65     do: %{conn | scheme: :http, port: 80}
     66 
     67   defp put_scheme(conn, ["http"]),
     68     do: %{conn | scheme: :http}
     69 
     70   defp put_scheme(conn, _scheme),
     71     do: conn
     72 
     73   defp put_host(conn, [proper_host]),
     74     do: %{conn | host: proper_host}
     75 
     76   defp put_host(conn, _),
     77     do: conn
     78 
     79   defp put_port(conn, headers) do
     80     with [header] <- headers,
     81          {port, ""} <- Integer.parse(header) do
     82       %{conn | port: port}
     83     else
     84       _ -> conn
     85     end
     86   end
     87 end