Packages
phoenix_echo
0.1.0
Forward browser console logs and errors to Phoenix server logs via WebSocket
Current section
Files
Jump to
Current section
Files
lib/phoenix_echo/plug.ex
defmodule PhoenixEcho.Plug do
@moduledoc """
Plug to inject browser logger JavaScript into HTML responses.
## Usage
Add to your endpoint or router:
plug PhoenixEcho.Plug
## Options
- `:only_dev` - Only inject in dev environment (default: `true`)
"""
@behaviour Plug
require Logger
@impl true
def init(opts), do: opts
@impl true
def call(conn, opts) do
if should_inject?(opts) do
Logger.debug("[PhoenixEcho.Plug] Registering script injection")
Plug.Conn.register_before_send(conn, &inject_script/1)
else
Logger.debug("[PhoenixEcho.Plug] Skipping injection - enabled: #{PhoenixEcho.enabled?()}")
conn
end
end
defp should_inject?(opts) do
only_dev = Keyword.get(opts, :only_dev, true)
if only_dev do
PhoenixEcho.enabled?() and Mix.env() == :dev
else
PhoenixEcho.enabled?()
end
end
defp inject_script(conn) do
if html_response?(conn) do
body = inject_into_body(conn.resp_body)
%{conn | resp_body: body}
else
conn
end
end
defp html_response?(conn) do
case Plug.Conn.get_resp_header(conn, "content-type") do
[content_type | _] -> String.contains?(content_type, "text/html")
_ -> false
end
end
defp inject_into_body(body) when is_binary(body) do
script = PhoenixEcho.script_tag()
cond do
String.contains?(body, "</head>") ->
String.replace(body, "</head>", "#{script}</head>", global: false)
String.contains?(body, "<body>") ->
String.replace(body, "<body>", "<body>#{script}", global: false)
true ->
script <> body
end
end
defp inject_into_body(body) when is_list(body) do
body
|> IO.iodata_to_binary()
|> inject_into_body()
end
end