defmodule BerrypodWeb.Plugs.BrokenUrlTracker do @moduledoc """ Wraps the router to record 404s in the broken URLs table. Works in dev mode too — Plug.Debugger intercepts exceptions before error templates render, so we catch NoRouteError here, record it, then re-raise so the normal error handling continues. """ @behaviour Plug def init(opts) do router = Keyword.fetch!(opts, :router) router_opts = router.init([]) {router, router_opts} end def call(conn, {router, router_opts}) do router.call(conn, router_opts) rescue e in Phoenix.Router.NoRouteError -> unless static_path?(conn.request_path) do prior_hits = Berrypod.Analytics.count_pageviews_for_path(conn.request_path) Berrypod.Redirects.record_broken_url(conn.request_path, prior_hits) if prior_hits > 0 do Berrypod.Redirects.attempt_auto_resolve(conn.request_path) end end reraise e, __STACKTRACE__ end defp static_path?(path) do String.starts_with?(path, "/assets/") or String.starts_with?(path, "/images/") or String.starts_with?(path, "/image_cache/") or String.starts_with?(path, "/favicon") end end