defmodule MicrowavepropWeb.Plugs.RemoteIp do @moduledoc """ Extracts the client IP from X-Forwarded-For (set by nginx/dokku proxy) and assigns it to conn.remote_ip and Logger metadata. """ @behaviour Plug @impl true def init(opts), do: opts @impl true def call(conn, _opts) do ip = case Plug.Conn.get_req_header(conn, "x-forwarded-for") do [forwarded | _] -> forwarded |> String.split(",") |> hd() |> String.trim() |> parse_ip() _ -> nil end conn = if ip do %{conn | remote_ip: ip} else conn end Logger.metadata(remote_ip: format_ip(conn.remote_ip)) conn end defp parse_ip(str) do case :inet.parse_address(String.to_charlist(str)) do {:ok, ip} -> ip _ -> nil end end defp format_ip({a, b, c, d}), do: "#{a}.#{b}.#{c}.#{d}" defp format_ip({a, b, c, d, e, f, g, h}), do: "#{a}:#{b}:#{c}:#{d}:#{e}:#{f}:#{g}:#{h}" defp format_ip(_), do: "unknown" end