diff options
author | William Carroll <wpcarro@gmail.com> | 2020-12-12T02·43+0000 |
---|---|---|
committer | William Carroll <wpcarro@gmail.com> | 2020-12-12T02·43+0000 |
commit | 8c5e4e77edacf082b5ab2d8aede49aa0ddfb9b5e (patch) | |
tree | b216303b8755d7d945a35a2a3d12d77b3828ceeb /assessments/semiprimes/server/lib/router.ex | |
parent | 45877a8b9cbe728e2dd66c361b3d6625810b31a0 (diff) |
Expose functions at API layer
Creating a simple HTTP RESTful API for exposing our `Server.semiprime` function. It supports some help messages, primitive parsing and error handling, and singular vs. batch processing of arguments. For more sophisticated parsing and error-checking, I prefer to use Haskell's Servant library.
Diffstat (limited to 'assessments/semiprimes/server/lib/router.ex')
-rw-r--r-- | assessments/semiprimes/server/lib/router.ex | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/assessments/semiprimes/server/lib/router.ex b/assessments/semiprimes/server/lib/router.ex new file mode 100644 index 000000000000..cb55520920de --- /dev/null +++ b/assessments/semiprimes/server/lib/router.ex @@ -0,0 +1,86 @@ +defmodule Router do + use Plug.Router + use Plug.Debugger + require Logger + + plug(Plug.Logger, log: :debug) + plug(Plug.Parsers, parsers: [:urlencoded]) + plug(:match) + plug(:dispatch) + + @usage """ + Usage: Try querying some of the following endpoints... + GET / + GET /help + GET /semiprime?number=<integer> + GET /semiprimes?numbers=<comma-separated-integers> + """ + + get "/" do + send_resp(conn, 200, "Welcome to Semiprimes Service!\n\n#{@usage}") + end + + get "/help" do + send_resp(conn, 200, @usage) + end + + get "/semiprime" do + case conn |> Map.get(:query_params) |> Map.get("number") do + nil -> + send_resp(conn, 400, "You must pass an integer as a query parameter. #{@usage}") + + val -> + case Integer.parse(val) do + {n, ""} -> + send_resp(conn, 200, semiprime_response(n)) + + _ -> + send_resp(conn, 400, "We could not parse the number you provided.\n\n#{@usage}") + end + end + end + + get "/semiprimes" do + case conn |> Map.get(:query_params) |> Map.get("numbers") do + nil -> + send_resp( + conn, + 400, + "You must pass a comma-separated list of integers as a query parameter.\n\n#{@usage}" + ) + + xs -> + response = + xs + |> String.split(",") + |> Stream.map(&Integer.parse/1) + |> Stream.filter(fn + {n, ""} -> true + _ -> false + end) + |> Stream.map(fn {n, ""} -> semiprime_response(n) end) + |> Enum.join("\n") + + send_resp(conn, 200, response) + end + end + + match _ do + send_resp(conn, 404, "Not found.") + end + + ################################################################################ + # Utils + ################################################################################ + + defp semiprime_response(n) do + case Server.semiprime(n) do + nil -> + "#{n} is not a semiprime. Try another number!" + + {hit_or_miss, factors} -> + response = "#{n} is a semiprime! Its factors are #{Enum.join(factors, " and ")}." + "Cache #{Atom.to_string(hit_or_miss)} - #{response}" + end + end +end |