defmodule Proxy do import Plug.Conn def init(options) do options end def call(conn, options) do conn |> put_forward_for |> call_upstream(options) |> handle_response(conn) end defp call_upstream(conn, options) do method = ProxyRequest.method(conn) url = ProxyRequest.url(options.upstream, conn) body = ProxyRequest.body(conn) headers = ProxyRequest.headers(conn) Upstream.request(method, url, body, headers, timeout: options.timeout) end defp handle_response({:error, response}, conn) do conn |> Plug.Conn.send_resp(502, "Bad Gateway") end defp handle_response({_, response}, conn) do conn |> put_resp_headers(response.headers) |> Plug.Conn.send_resp(response.status_code, response.body) end defp put_forward_for(conn) do ip = conn.remote_ip |> ProxyRequest.ipToString Plug.Conn.put_req_header(conn, "x-forwarded-for", ip) end defp put_resp_headers(conn, []), do: conn defp put_resp_headers(conn, [{header, value} | tail]) do conn |> Plug.Conn.put_resp_header(header |> String.downcase, value) |> put_resp_headers(tail) end end