Skip to content

Instantly share code, notes, and snippets.

@sb8244
Created July 17, 2024 04:03
Show Gist options
  • Save sb8244/0cea9b7ace4a65dd316245c38261c584 to your computer and use it in GitHub Desktop.
Save sb8244/0cea9b7ace4a65dd316245c38261c584 to your computer and use it in GitHub Desktop.
defmodule SuperWeb.Plug.AssetNotFound do
import Plug.Conn
alias Plug.Conn
def init(opts) do
%{
at: Keyword.fetch!(opts, :at) |> Plug.Router.Utils.split(),
only: {Keyword.fetch!(opts, :only), []}
}
end
def call(conn = %Conn{}, %{at: at, only: only_rules}) do
segments = subset(at, conn.path_info)
asset_path? = allowed?(only_rules, segments)
if asset_path? do
# Give a second for servers to boot and hopefully help timeline
Process.sleep(Process.get({__MODULE__, :delay}, 1000))
conn
|> maybe_replay()
|> send_resp(404, "Asset not found")
|> halt()
else
conn
end
end
defp maybe_replay(conn) do
case get_next_replay_amount(conn) do
:do_not_replay -> conn
num -> put_resp_header(conn, "fly-replay", "elsewhere=true;state=replays_#{num}")
end
end
# Taken from Plug.Static
defp subset([h | expected], [h | actual]), do: subset(expected, actual)
defp subset([], actual), do: actual
defp subset(_, _), do: []
# Taken from Plug.Static, `:only` option needs put into this tuple format even though not used now
defp allowed?(_only_rules, []), do: false
defp allowed?({[], []}, _list), do: true
defp allowed?({full, prefix}, [h | _]) do
h in full or (prefix != [] and match?({0, _}, :binary.match(h, prefix)))
end
defp get_next_replay_amount(conn) do
next_num =
with [header] <- get_req_header(conn, "fly-replay-src"),
[_, "replays_" <> str_num] <- Regex.run(~r/(?:^|;)state=([^;]*)/, header),
{num, ""} <- Integer.parse(str_num) do
num + 1
else
_ -> 1
end
# Number of replays starts at 0 (header not included), so < is used
if next_num < number_of_machines() do
next_num
else
:do_not_replay
end
end
defp number_of_machines do
query = Application.get_env(:super, :dns_cluster_query)
if query do
length(:inet_res.lookup(~c"#{query}", :in, :aaaa))
else
Process.get({__MODULE__, :number_of_machines}, 0)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment