commit b291aa607fc3e8b52957105d157bd7f45a39f007 from: mtmn date: Sun Jun 7 09:26:14 2026 UTC fix: safer queries, formatter, http codes commit - 8339a06b1df1dc87134c1f08d8c35bd1bdfb5c01 commit + b291aa607fc3e8b52957105d157bd7f45a39f007 blob - /dev/null blob + d304ff320a5298fb750d0f991c3b5d33a1475d31 (mode 644) --- /dev/null +++ .formatter.exs @@ -0,0 +1,3 @@ +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] blob - 519ad59acb7c5c68bc62286661866a8e1bf013fd blob + 8ff9a8a44696d65fa44e018d298f8819ed48536f --- config/runtime.exs +++ config/runtime.exs @@ -2,7 +2,7 @@ import Config if config_env() == :prod do config :shortener, - port: System.get_env("PORT") |> then(&(if &1, do: String.to_integer(&1), else: 4000)), + port: System.get_env("PORT") |> then(&if &1, do: String.to_integer(&1), else: 4000), host: System.get_env("HOST") || "127.0.0.1", auth_token: System.fetch_env!("AUTH_TOKEN"), db_path: System.get_env("DB_PATH") || "data.db", blob - e0bfd0736b17115e0e00fe1620397d3ee950d088 blob + b97d1f28a4d6a733674ec2078b6e0eafabceb6ec --- lib/shortener/db.ex +++ lib/shortener/db.ex @@ -44,14 +44,21 @@ defmodule Shortener.DB do @impl true def handle_call({:insert, code, url}, _from, conn) do result = - with {:ok, stmt} <- - Exqlite.Sqlite3.prepare(conn, "INSERT INTO shirts (code, url) VALUES (?1, ?2)"), - :ok <- Exqlite.Sqlite3.bind(stmt, [code, url]), - :done <- Exqlite.Sqlite3.step(conn, stmt) do - _ = Exqlite.Sqlite3.release(conn, stmt) - :ok - else - {:error, reason} -> {:error, reason} + case Exqlite.Sqlite3.prepare(conn, "INSERT INTO shirts (code, url) VALUES (?1, ?2)") do + {:ok, stmt} -> + r = + with :ok <- Exqlite.Sqlite3.bind(stmt, [code, url]), + :done <- Exqlite.Sqlite3.step(conn, stmt) do + :ok + else + {:error, reason} -> {:error, reason} + end + + _ = Exqlite.Sqlite3.release(conn, stmt) + r + + {:error, reason} -> + {:error, reason} end {:reply, result, conn} @@ -59,22 +66,29 @@ defmodule Shortener.DB do def handle_call({:lookup, code}, _from, conn) do result = - with {:ok, stmt} <- - Exqlite.Sqlite3.prepare(conn, "SELECT url FROM shirts WHERE code = ?1"), - :ok <- Exqlite.Sqlite3.bind(stmt, [code]), - step_result <- Exqlite.Sqlite3.step(conn, stmt) do - _ = Exqlite.Sqlite3.release(conn, stmt) + case Exqlite.Sqlite3.prepare(conn, "SELECT url FROM shirts WHERE code = ?1") do + {:ok, stmt} -> + r = do_lookup(conn, stmt, code) + _ = Exqlite.Sqlite3.release(conn, stmt) + r - case step_result do - {:row, [url]} -> {:ok, url} - :done -> :not_found - {:error, reason} -> {:error, reason} - end + {:error, reason} -> + {:error, reason} end {:reply, result, conn} end + defp do_lookup(conn, stmt, code) do + with :ok <- Exqlite.Sqlite3.bind(stmt, [code]) do + case Exqlite.Sqlite3.step(conn, stmt) do + {:row, [url]} -> {:ok, url} + :done -> :not_found + {:error, reason} -> {:error, reason} + end + end + end + @impl true def terminate(_reason, conn) do Logger.info("Closing database connection") blob - 1302e3af47c1f13597c1f022cacda1319d1b9673 blob + 8eaad91102aa62b00e48cd8024faee3bdc187d13 --- lib/shortener/router.ex +++ lib/shortener/router.ex @@ -7,10 +7,10 @@ defmodule Shortener.Router do use Plug.Router - plug Plug.Logger - plug :match - plug Plug.Parsers, parsers: [:json], json_decoder: Jason - plug :dispatch + plug(Plug.Logger) + plug(:match) + plug(Plug.Parsers, parsers: [:json], json_decoder: Jason) + plug(:dispatch) # --------------------------------------------------------------------------- # POST /l/curtail @@ -52,7 +52,7 @@ defmodule Shortener.Router do {:ok, url} -> conn |> put_resp_header("location", url) - |> send_resp(301, "") + |> send_resp(302, "") :not_found -> json(conn, 404, %{error: "not found"})