Artifact [6721aca7f2]

Artifact 6721aca7f27f1a681a12b5542e98af3aa2538207:


defmodule Plug.RequestId do
  @moduledoc """
  A plug for generating a unique request id for each request. A generated
  request id will in the format "uq8hs30oafhj5vve8ji5pmp7mtopc08f".

  If a request id already exists as the "x-request-id" HTTP request header,
  then that value will be used assuming it is between 20 and 200 characters.
  If it is not, a new request id will be generated.

  The request id is added to the Logger metadata as `:request_id` and the response as
  the "x-request-id" HTTP header. To see the request id in your log output,
  configure your logger backends to include the `:request_id` metadata:

      config :logger, :console, metadata: [:request_id]

  It is recommended to include this metadata configuration in your production
  configuration file.

  To use it, just plug it into the desired module:

      plug Plug.RequestId

  ## Options

    * `:http_header` - The name of the HTTP *request* header to check for
    existing request ids. This is also the HTTP *response* header that will be
    set with the request id. Default value is "x-request-id"

        plug Plug.RequestId, http_header: "custom-request-id"
  """

  require Logger
  alias Plug.Conn
  @behaviour Plug

  def init(opts) do
    Keyword.get(opts, :http_header, "x-request-id")
  end

  def call(conn, req_id_header) do
    conn
    |> get_request_id(req_id_header)
    |> set_request_id(req_id_header)
  end

  defp get_request_id(conn, header) do
    case Conn.get_req_header(conn, header) do
      []      -> {conn, generate_request_id}
      [val|_] -> if valid_request_id?(val), do: {conn, val}, else: {conn, generate_request_id}
    end
  end

  defp set_request_id({conn, request_id}, header) do
    Logger.metadata(request_id: request_id)
    conn |> Conn.put_resp_header(header, request_id)
  end

  defp generate_request_id do
    :crypto.rand_bytes(20) |> Base.hex_encode32(case: :lower)
  end

  defp valid_request_id?(s), do: byte_size(s) in 20..200
end