DEV Community

Cover image for Using Plug in Elixir Phoenix to transfer custom request header or params value to HTTP Headers
Ahsan Nabi Dar
Ahsan Nabi Dar

Posted on

Using Plug in Elixir Phoenix to transfer custom request header or params value to HTTP Headers

Elixir's web framework Phoenix makes use of Plugs which are composable module layers through which the HTTP request passes through allowing the incoming request to be manipulated as it is processed. As per Phoenix docs

Plug lives at the heart of Phoenix's HTTP layer, and Phoenix puts Plug front and center. We interact with plugs at every step of the request life-cycle, and the core Phoenix components like endpoints, routers, and controllers are all just plugs internally
Enter fullscreen mode Exit fullscreen mode

Recently building an API (yes Phoenix is now my go to choice for web dev :) ) I decided to use simple_token_authentication hex package instead of hand-rolling out an API Token checker. It has some nice features where it adds service name to the log metadata for the matching token and uses erlang's persistent_term to make some performance gains. Also you should never hand-roll out Auth(n/z) by yourself to avoid missing out on edge cases or introducing loopholes.

The only shortcoming I faced with simple_token_authentication was that it requires that the API token should be sent in Authorization header for e.g Authorization: <API TOKEN>. Now this doesn't seem to be a problem when you are integrating your API with other services that you own (having API keys in mobile and web app are just useless for protection by exposing them publicly). This can be done as intended other than in case the Authorization header is not available or restricted for use and you would need to use a custom header to pass the value. Another case and more prominent one is when integrating your API with 3rd party service or webhook where you can't pass a value in a HTTP header and have to append it to your URL.

So in order to pick your API token from HTTP header X-API-TOKEN or param x_api_token. You can add a plug that sits before SimpleTokenAuthentication Plug in the pipeline and it would transfer the value over to Authorization header.

defmodule MaverickWeb.Plugs.TransferApiTokenToAuthorization do
  @moduledoc """
  The TransferApiTokenToAuthorization Plug.
  """

  import Plug.Conn

  @api_key_header "x-api-key"
  @api_key_param "x_api_key"
  def init(opts), do: opts

  def call(conn, _opts) do
    token = get_token_from_header(conn) || get_token_from_params(conn) || ""
    conn = put_req_header(conn, "authorization", token)
    conn
  end

  defp get_token_from_header(conn) do
    case get_req_header(conn, @api_key_header) do
      [val | _] -> val
      _ -> nil
    end
  end

  defp get_token_from_params(conn), do: Map.get(conn.query_params, @api_key_param)

end
Enter fullscreen mode Exit fullscreen mode

You can use this to transfer values from any intended header or param to any header in your request.

Banner Image : https://blog.logrocket.com/wp-content/uploads/2022/10/phoenix-plugs-web-app-functions.png

Top comments (0)