From 51a7b8be9380c035f2de1a6885709a1d562b7165 Mon Sep 17 00:00:00 2001 From: Ryan Pandya Date: Tue, 30 Aug 2022 11:24:56 -0700 Subject: [PATCH] Start building out model; query all journals and pages from filesystem --- .gitignore | 1 + logsrv_api/.gitignore | 3 ++ logsrv_api/config/config.exs | 5 +++ logsrv_api/config/dev.env.exs | 4 +++ logsrv_api/config/prod.env.exs | 3 ++ logsrv_api/config/test.env.exs | 3 ++ logsrv_api/lib/logsrv.ex | 28 +++++++++------ logsrv_api/lib/logsrv/application.ex | 9 +++++ logsrv_api/lib/logsrv/router.ex | 52 ++++++++++++++++++++++++++++ logsrv_api/mix.exs | 2 ++ logsrv_api/mix.lock | 12 +++++++ logsrv_api/test/logsrv_test.exs | 37 ++++++++++++++++++++ 12 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 logsrv_api/config/config.exs create mode 100644 logsrv_api/config/dev.env.exs create mode 100644 logsrv_api/config/prod.env.exs create mode 100644 logsrv_api/config/test.env.exs create mode 100644 logsrv_api/lib/logsrv/router.ex create mode 100644 logsrv_api/mix.lock diff --git a/.gitignore b/.gitignore index fc5d8e3..3877f3c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ erl_crash.dump /config/*.secret.exs .elixir_ls/ +Notes/ \ No newline at end of file diff --git a/logsrv_api/.gitignore b/logsrv_api/.gitignore index 7ca54af..41c8958 100644 --- a/logsrv_api/.gitignore +++ b/logsrv_api/.gitignore @@ -1,3 +1,6 @@ +# Notes for dev mode. +/Notes/ + # The directory Mix will write compiled artifacts to. /_build/ diff --git a/logsrv_api/config/config.exs b/logsrv_api/config/config.exs new file mode 100644 index 0000000..f88b5ba --- /dev/null +++ b/logsrv_api/config/config.exs @@ -0,0 +1,5 @@ +import Config + +# Import environment specific config. This must remain at the bottom +# of this file so it overrides the configuration defined above. +import_config "#{config_env()}.env.exs" diff --git a/logsrv_api/config/dev.env.exs b/logsrv_api/config/dev.env.exs new file mode 100644 index 0000000..26314aa --- /dev/null +++ b/logsrv_api/config/dev.env.exs @@ -0,0 +1,4 @@ +import Config + +config :logsrv, port: 8080 +config :logsrv, dir: "../Notes" diff --git a/logsrv_api/config/prod.env.exs b/logsrv_api/config/prod.env.exs new file mode 100644 index 0000000..6252867 --- /dev/null +++ b/logsrv_api/config/prod.env.exs @@ -0,0 +1,3 @@ +import Config + +config :logsrv, port: 12545 diff --git a/logsrv_api/config/test.env.exs b/logsrv_api/config/test.env.exs new file mode 100644 index 0000000..eae5753 --- /dev/null +++ b/logsrv_api/config/test.env.exs @@ -0,0 +1,3 @@ +import Config + +config :logsrv, port: 8081 diff --git a/logsrv_api/lib/logsrv.ex b/logsrv_api/lib/logsrv.ex index 11f3709..22960c2 100644 --- a/logsrv_api/lib/logsrv.ex +++ b/logsrv_api/lib/logsrv.ex @@ -3,16 +3,22 @@ defmodule Logsrv do Documentation for `Logsrv`. """ - @doc """ - Hello world. - - ## Examples - - iex> Logsrv.hello() - :world - - """ - def hello do - :world + def dir do + Application.get_env(:logsrv, :dir) end + + def dir(subdir) do + "#{dir()}/#{subdir}" + end + + def journals do + dir(:journals) + |> File.ls! + end + + def pages do + dir(:pages) + |> File.ls! + end + end diff --git a/logsrv_api/lib/logsrv/application.ex b/logsrv_api/lib/logsrv/application.ex index 50570c8..8a9a428 100644 --- a/logsrv_api/lib/logsrv/application.ex +++ b/logsrv_api/lib/logsrv/application.ex @@ -10,6 +10,15 @@ defmodule Logsrv.Application do children = [ # Starts a worker by calling: Logsrv.Worker.start_link(arg) # {Logsrv.Worker, arg} + { + Plug.Cowboy, + scheme: :http, + plug: Logsrv.Router, + options: + [ + port: Application.get_env(:logsrv, :port) + ] + } ] # See https://hexdocs.pm/elixir/Supervisor.html diff --git a/logsrv_api/lib/logsrv/router.ex b/logsrv_api/lib/logsrv/router.ex new file mode 100644 index 0000000..0ec0e25 --- /dev/null +++ b/logsrv_api/lib/logsrv/router.ex @@ -0,0 +1,52 @@ +defmodule Logsrv.Router do + # Bring Plug.Router module into scope + use Plug.Router + + # Attach the Logger to log incoming requests + plug(Plug.Logger) + + # Tell Plug to match the incoming request with the defined endpoints + plug(:match) + + # Once there is a match, parse the response body if the content-type + # is application/json. The order is important here, as we only want to + # parse the body if there is a matching route.(Using the Jayson parser) + plug(Plug.Parsers, + parsers: [:json], + pass: ["application/json"], + json_decoder: Jason + ) + + # Dispatch the connection to the matched handler + plug(:dispatch) + + # Handler for GET request with "/" path + get "/" do + send_resp(conn, 200, "OK") + end + + get "/journals" do + journals = + Logsrv.journals + |> Jason.encode!() # Encode the list to a JSON string + + conn + |> put_resp_content_type("application/json") + |> send_resp(200, journals) # Send a 200 OK response with the posts in the body + end + + get "/pages" do + pages = + Logsrv.pages + |> Jason.encode!() # Encode the list to a JSON string + + conn + |> put_resp_content_type("application/json") + |> send_resp(200, pages) # Send a 200 OK response with the posts in the body + end + + # Fallback handler when there was no match + match _ do + send_resp(conn, 404, "Not Found") + end +end diff --git a/logsrv_api/mix.exs b/logsrv_api/mix.exs index d6879bc..eb434ff 100644 --- a/logsrv_api/mix.exs +++ b/logsrv_api/mix.exs @@ -22,6 +22,8 @@ defmodule Logsrv.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:plug_cowboy, "~> 2.5"}, + {:jason, "~> 1.3"} # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} ] diff --git a/logsrv_api/mix.lock b/logsrv_api/mix.lock new file mode 100644 index 0000000..c8a79d8 --- /dev/null +++ b/logsrv_api/mix.lock @@ -0,0 +1,12 @@ +%{ + "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, + "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, + "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, + "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, + "plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, + "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, + "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, + "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, +} diff --git a/logsrv_api/test/logsrv_test.exs b/logsrv_api/test/logsrv_test.exs index 4e55790..58126a9 100644 --- a/logsrv_api/test/logsrv_test.exs +++ b/logsrv_api/test/logsrv_test.exs @@ -6,3 +6,40 @@ defmodule LogsrvTest do assert Logsrv.hello() == :world end end + +defmodule LogsrvTest.Router do + # Bringing ExUnit's case module to scope and configure it to run + # tests in this module concurrently with tests in other modules + # https://hexdocs.pm/ex_unit/ExUnit.Case.html + use ExUnit.Case, async: true + + # This makes the conn object avaiable in the scope of the tests, + # which can be used to make the HTTP request + # https://hexdocs.pm/plug/Plug.Test.html + use Plug.Test + + # We call the Plug init/1 function with the options then store + # returned options in a Module attribute opts. + # Note: @ is module attribute unary operator + # https://hexdocs.pm/elixir/main/Kernel.html#@/1 + # https://hexdocs.pm/plug/Plug.html#c:init/1 + @opts Logsrv.Router.init([]) + + + # Create a test with the name "return ok" + test "return ok" do + # Build a connection which is GET request on / url + conn = conn(:get, "/") + + # Then call Plug.call/2 with the connection and options + # https://hexdocs.pm/plug/Plug.html#c:call/2 + conn = Logsrv.Router.call(conn, @opts) + + # Finally we are using the assert/2 function to check for the + # correctness of the response + # https://hexdocs.pm/ex_unit/ExUnit.Assertions.html#assert/2 + assert conn.state == :sent + assert conn.status == 200 + assert conn.resp_body == "OK" + end +end