Packages
honeybadger
0.21.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
0.19.0
0.18.1
0.18.0
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.7.0-beta
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.1
0.3.0
0.2.0
0.1.2
0.1.1
0.1.0
Elixir client, Plug and error_logger for integrating with the Honeybadger.io exception tracker"
Current section
Files
Jump to
Current section
Files
lib/honeybadger/plug_data.ex
if Code.ensure_loaded?(Plug) do
defmodule Honeybadger.PlugData do
@moduledoc false
alias Plug.Conn
@type plug_env :: %{
action: binary(),
cgi_data: map(),
component: binary(),
params: map(),
session: map(),
url: binary()
}
@type metadata :: %{
context: any(),
plug_env: plug_env()
}
@doc """
Generate notification metadata from a `Plug.Conn`.
The map that is returned contains the current context and environmental
data.
"""
@spec metadata(Conn.t(), module()) :: metadata()
def metadata(conn, module) do
%{context: Honeybadger.context(), plug_env: build_plug_env(conn, module)}
end
@doc false
@spec build_plug_env(Conn.t(), module()) :: plug_env()
def build_plug_env(%Conn{} = conn, module) do
conn = Conn.fetch_query_params(conn)
%{
params: conn.params,
session: %{},
url: conn.request_path,
action: action(conn),
component: component(conn, module),
cgi_data: build_cgi_data(conn)
}
end
@doc false
@spec build_cgi_data(Conn.t()) :: map()
def build_cgi_data(%Conn{} = conn) do
cgi_data = %{
"REQUEST_METHOD" => conn.method,
"PATH_INFO" => Enum.join(conn.path_info, "/"),
"QUERY_STRING" => conn.query_string,
"SCRIPT_NAME" => Enum.join(conn.script_name, "/"),
"REMOTE_ADDR" => remote_addr(conn),
"REMOTE_PORT" => remote_port(conn),
"SERVER_ADDR" => "127.0.0.1",
"SERVER_NAME" => Honeybadger.get_env(:hostname),
"SERVER_PORT" => conn.port,
"CONTENT_LENGTH" => Conn.get_req_header(conn, "content-length"),
"ORIGINAL_FULLPATH" => conn.request_path
}
headers = rack_format_headers(conn)
Map.merge(cgi_data, headers)
end
# Helpers
defp component(%Conn{private: private}, module) do
import Honeybadger.Utils, only: [module_to_string: 1]
case private do
%{phoenix_controller: controller} -> module_to_string(controller)
_ -> module_to_string(module)
end
end
defp action(%Conn{private: private}) do
case private do
%{phoenix_action: action_name} -> to_string(action_name)
_ -> ""
end
end
defp rack_format_headers(%Conn{req_headers: req_headers}) do
Enum.reduce(req_headers, %{}, fn {header, value}, acc ->
header = ("HTTP_" <> String.upcase(header)) |> String.replace("-", "_")
Map.put(acc, header, value)
end)
end
defp remote_addr(%Conn{remote_ip: remote_ip}) do
case :inet.ntoa(remote_ip) do
{:error, :einval} ->
to_string(remote_ip)
charlist ->
List.to_string(charlist)
end
end
defp remote_port(conn) do
cond do
function_exported?(Conn, :get_peer_data, 1) ->
conn
|> Conn.get_peer_data()
|> Map.get(:port)
Map.has_key?(conn, :peer) ->
conn
|> Map.get(:peer)
|> elem(1)
true ->
nil
end
end
end
end