create backend
This commit is contained in:
158
lib/mound_hunters_web/router.ex
Normal file
158
lib/mound_hunters_web/router.ex
Normal file
@@ -0,0 +1,158 @@
|
||||
defmodule MoundHuntersWeb.Router do
|
||||
@moduledoc """
|
||||
Main HTTP router for Hopewell Road application.
|
||||
"""
|
||||
use Plug.Router
|
||||
require Logger
|
||||
|
||||
# Request logging (must be first to capture timing)
|
||||
plug(MoundHuntersWeb.Plugs.RequestLogger)
|
||||
|
||||
# Parse query params and request body
|
||||
plug(Plug.Parsers,
|
||||
parsers: [:urlencoded, :json],
|
||||
json_decoder: Jason
|
||||
)
|
||||
|
||||
# Bounds checking for Ohio coordinates
|
||||
plug(MoundHuntersWeb.Plugs.BoundsCheck)
|
||||
|
||||
# Match routes
|
||||
plug(:match)
|
||||
|
||||
# Dispatch to matched route
|
||||
plug(:dispatch)
|
||||
|
||||
# Tile endpoints
|
||||
get "/tiles/request" do
|
||||
MoundHuntersWeb.TileController.request(conn)
|
||||
end
|
||||
|
||||
match "/tiles/:format/:tile_id", via: [:get, :head] do
|
||||
conn = put_private(conn, :path_params, %{"tile_id" => tile_id, "format" => format})
|
||||
MoundHuntersWeb.TileController.serve(conn)
|
||||
end
|
||||
|
||||
# Geometry sharing API
|
||||
post "/api/share" do
|
||||
MoundHuntersWeb.ApiController.create_share(conn)
|
||||
end
|
||||
|
||||
get "/api/share/:id" do
|
||||
conn = put_private(conn, :path_params, %{"id" => id})
|
||||
MoundHuntersWeb.ApiController.get_share(conn)
|
||||
end
|
||||
|
||||
# Health check
|
||||
get "/health" do
|
||||
send_resp(conn, 200, Jason.encode!(%{status: "ok"}))
|
||||
end
|
||||
|
||||
get "/" do
|
||||
static_dir = Application.app_dir(:mound_hunters, "priv/static")
|
||||
index_path = Path.join(static_dir, "index.html")
|
||||
|
||||
if File.exists?(index_path) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "text/html; charset=utf-8")
|
||||
|> put_resp_header("cache-control", "no-cache")
|
||||
|> send_file(200, index_path)
|
||||
else
|
||||
send_resp(conn, 404, "Not found")
|
||||
end
|
||||
end
|
||||
|
||||
# Static files (with cache busting support via manifest)
|
||||
get "/*path" do
|
||||
serve_static(conn, path)
|
||||
end
|
||||
|
||||
# 404 handler
|
||||
match _ do
|
||||
send_resp(conn, 404, Jason.encode!(%{error: "Not found"}))
|
||||
end
|
||||
|
||||
# Serve static files from priv/static
|
||||
defp serve_static(conn, path) do
|
||||
static_dir = Application.app_dir(:mound_hunters, "priv/static")
|
||||
file_path = resolve_static_path(path, static_dir)
|
||||
|
||||
cond do
|
||||
file_path && File.regular?(file_path) ->
|
||||
# Determine content type
|
||||
content_type = MIME.from_path(file_path)
|
||||
|
||||
# Set cache headers (immutable for hashed files)
|
||||
cache_control =
|
||||
if String.contains?(file_path, "-") do
|
||||
"public, max-age=31536000, immutable"
|
||||
else
|
||||
"public, max-age=3600"
|
||||
end
|
||||
|
||||
conn
|
||||
|> put_resp_header("content-type", content_type)
|
||||
|> put_resp_header("cache-control", cache_control)
|
||||
|> send_file(200, file_path)
|
||||
|
||||
path == [] or path == [""] ->
|
||||
# Serve index.html for root
|
||||
index_path = Path.join(static_dir, "index.html")
|
||||
|
||||
if File.exists?(index_path) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "text/html")
|
||||
|> put_resp_header("cache-control", "no-cache")
|
||||
|> send_file(200, index_path)
|
||||
else
|
||||
send_resp(conn, 404, "Not found")
|
||||
end
|
||||
|
||||
true ->
|
||||
send_resp(conn, 404, "Not found")
|
||||
end
|
||||
end
|
||||
|
||||
# Resolve static file path, checking manifest for hashed versions
|
||||
defp resolve_static_path(path, static_dir) do
|
||||
requested = Path.join(path)
|
||||
direct_path = Path.join(static_dir, requested)
|
||||
|
||||
cond do
|
||||
File.regular?(direct_path) ->
|
||||
direct_path
|
||||
|
||||
# Check manifest for hashed version
|
||||
manifest_path = Path.join(static_dir, "manifest.json") ->
|
||||
case load_manifest(manifest_path) do
|
||||
{:ok, manifest} ->
|
||||
hashed = Map.get(manifest, requested)
|
||||
|
||||
if hashed do
|
||||
hashed_path = Path.join(static_dir, hashed)
|
||||
if File.regular?(hashed_path), do: hashed_path, else: nil
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Load and cache manifest
|
||||
defp load_manifest(path) do
|
||||
if File.exists?(path) do
|
||||
case File.read(path) do
|
||||
{:ok, content} -> Jason.decode(content)
|
||||
_ -> {:error, :read_failed}
|
||||
end
|
||||
else
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user