test workflowModule VersionHex DocsTotal DownloadLicenseLast UpdatedContributor Covenant

Tesla.Middleware.DynamicHeaders

Middleware for the Tesla HTTP client that sets value for HTTP headers dynamically at runtime from the application environment.

For example:

plug Tesla.Middleware.DynamicHeaders, [
    # Set header to Application.get_env(:my_app, :foo_token)
    {"X-Foo-Token", {:my_app, :foo_token}},
    # Set header to Application.get_env(:my_app, :foo_token, "default")
    {"X-Bar-Token", {:my_app, :bar_token, "default"}},
    # Set value in a function
    {"Authorization", &get_authorization/1},
    # Set a static value
    {"content/type", "application/json"}
  ]

defp get_authorization(header_name) do
  "token: " <> Application.get_env(@app, :auth_token)
end

This is most useful to handle secrets such as auth tokens. If you set secrets at compile time, then they are hard coded into the release file, a security risk. Similarly, if you build your code in a CI system, then you have to make the secrets available there.

Installation

Add tesla_middleware_dynamic_headers to the list of dependencies in mix.exs:

def deps do
  [
    {:tesla_middleware_dynamic_headers, "~> 0.7.0"}
  ]
end

Configuration

Add plug Tesla.Middleware.DynamicHeaders to the client and specify a list of headers.

The plug takes a single argument, either a list of tuples or a function. The first element of the tuple is the header name. Other values are as follows:

If the argument is a zero-arity function, it is called to generate a list of {header_name, value} tuples.

Examples

The following example shows configuration via a list of headers:

defmodule FooClient do
  use Tesla

  @app :foo_client

  plug Tesla.Middleware.BaseUrl, "https://example.com/"

  plug Tesla.Middleware.DynamicHeaders, [
    {"X-Foo-Token", {@app, :foo_token}},
    {"X-Bar-Token", {@app, :bar_token, "default"}},
    {"Authorization", &get_authorization/1},
    {"content/type", "application/json"}
    ]

  plug Tesla.Middleware.Logger

  defp get_authorization(header_name) do
    "token: " <> Application.get_env(@app, :auth_token)
  end
end

The following example uses a custom function to generate all the headers:

defmodule FooClient do
  use Tesla

  @app :foo_client

  plug Tesla.Middleware.DynamicHeaders, &get_dynamic_headers/0

  defp get_dynamic_headers do
    Application.get_env(@app, :headers)
  end
end

The app configuration in config/test.exs might look like:

config :foo_client,
  foo_token: "footoken",
  bar_token: "bartoken",
  auth_token: "authtoken"

config :foo_client,
  headers: [
    {"Authorization", "token: authtoken"}
  ]

In production, you would normally set environment variables with the tokens then read them in config/runtime.exs:

config :foo_client,
  foo_token: System.get_env("FOO_TOKEN") || raise "missing environment variable FOO_TOKEN"

Documentation is here: https://hexdocs.pm/tesla_middleware_dynamic_headers

This project uses the Contributor Covenant version 2.1. Check CODE_OF_CONDUCT.md for more information.

Contacts

I am jakemorrison on on the Elixir Slack and Discord, reachfh on Freenode #elixir-lang IRC channel. Happy to chat or help with your projects.