WEB: Implemented terrible routing control.
This commit is contained in:
commit
07d553ab92
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
rl_repo-*.tar
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
36
README.md
Normal file
36
README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# RlRepo
|
||||
|
||||
## API Usage
|
||||
/<repo_name>/<?sub_repo_name>/<pkg_name>/download
|
||||
|
||||
### Repo management
|
||||
/repo/<action>
|
||||
|
||||
#### Repo Creation
|
||||
/repo/create
|
||||
|
||||
|
||||
#### Repo deletion
|
||||
/repo/delete
|
||||
|
||||
### Sub-repo management
|
||||
/<repo_name>/create
|
||||
/<repo_name>/delete
|
||||
|
||||
|
||||
### Package management
|
||||
/<repo_name>/<action>
|
||||
|
||||
#### Create
|
||||
/<repo_name>/create
|
||||
|
||||
#### Delete
|
||||
/<repo_name>/delete
|
||||
|
||||
|
||||
|
||||
### Package Info
|
||||
/<repo_name>/<pkg_name>/<action>
|
||||
|
||||
|
||||
|
89
lib/client_handler.ex
Normal file
89
lib/client_handler.ex
Normal file
|
@ -0,0 +1,89 @@
|
|||
defmodule RlRepo.ClientHandler do
|
||||
require Logger
|
||||
@moduledoc """
|
||||
"""
|
||||
|
||||
def process_request(client_socket) do
|
||||
Logger.info("Processing client request.")
|
||||
|
||||
client_socket
|
||||
|> read_request
|
||||
|> create_response()
|
||||
|> create_response_header()
|
||||
|> write_response(client_socket)
|
||||
|
||||
end
|
||||
|
||||
def read_request(client_socket) do
|
||||
Logger.info("Reading request.")
|
||||
{:ok, request} = :gen_tcp.recv(client_socket, 0)
|
||||
Logger.info("Request recieved.")
|
||||
request
|
||||
end
|
||||
|
||||
def create_response(request) do
|
||||
Logger.info("Building body.")
|
||||
|
||||
# NOTE: Reliability testing.
|
||||
if String.match?(request, ~r{GET /error}) do
|
||||
raise(request)
|
||||
end
|
||||
|
||||
# TODO: Handle routing here.
|
||||
a = String.split(request, "\n\r");
|
||||
Logger.info a
|
||||
[get_line | rest] = a
|
||||
|
||||
b = String.split(get_line, " ");
|
||||
[request_type | rest] = b
|
||||
[path | rest] = rest
|
||||
Logger.info "#{request_type} #{path}"
|
||||
|
||||
# Parse path
|
||||
split_path = String.split(path, "/");
|
||||
# Ignore the first slash.
|
||||
[_ | rest ] = split_path
|
||||
|
||||
split_path_length = length(rest)
|
||||
Logger.info split_path_length
|
||||
|
||||
ret = case split_path_length do
|
||||
3 ->
|
||||
RlRepo.Router.parse_3_segment_path(rest)
|
||||
|> RlRepo.Router.route_3(request_type)
|
||||
4 ->
|
||||
RlRepo.Router.parse_4_segment_path(rest)
|
||||
|> RlRepo.Router.route_4(request_type)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def create_return_code_string(return_code) do
|
||||
case return_code do
|
||||
200 -> "200 OK"
|
||||
404 -> "404 Not Found"
|
||||
end
|
||||
end
|
||||
|
||||
def create_response_header(body) do
|
||||
{return_code, content_type, body} = body
|
||||
|
||||
"""
|
||||
HTTP/1.1 #{create_return_code_string(return_code)}\r
|
||||
Content-Type: #{content_type}\r
|
||||
Content-Length: #{byte_size(body)}\r
|
||||
\r
|
||||
#{body}
|
||||
"""
|
||||
end
|
||||
|
||||
|
||||
def write_response(response, client_socket) do
|
||||
:ok = :gen_tcp.send(client_socket, response)
|
||||
|
||||
# Logger.info("Response:\n\n#{response}")
|
||||
|
||||
:gen_tcp.close(client_socket)
|
||||
end
|
||||
end
|
8
lib/json.ex
Normal file
8
lib/json.ex
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule RlRepo.Json do
|
||||
require Logger
|
||||
@moduledoc """
|
||||
"""
|
||||
def fmt_json(a) do
|
||||
"{\"pkg_names\": 10}"
|
||||
end
|
||||
end
|
31
lib/rl_repo.ex
Normal file
31
lib/rl_repo.ex
Normal file
|
@ -0,0 +1,31 @@
|
|||
defmodule RlRepo do
|
||||
require Logger
|
||||
@moduledoc """
|
||||
"""
|
||||
|
||||
@doc """
|
||||
"""
|
||||
def start(port) do
|
||||
{:ok, listener_socket} = :gen_tcp.listen(port, [:binary, packet: :raw, active: false, reuseaddr: true])
|
||||
|
||||
Logger.info("Listening on port #{port}")
|
||||
|
||||
loop_acceptor(listener_socket)
|
||||
end
|
||||
|
||||
|
||||
def loop_acceptor(listener_socket) do
|
||||
Logger.debug "Waiting for connection."
|
||||
|
||||
{:ok, client_socket} = :gen_tcp.accept(listener_socket)
|
||||
|
||||
Logger.info "Client Connected."
|
||||
|
||||
process_pid = spawn(fn -> RlRepo.ClientHandler.process_request(client_socket) end)
|
||||
Logger.info "Handling client connection at PID #{inspect(process_pid)}"
|
||||
Logger.info "Handing over socket control."
|
||||
:ok = :gen_tcp.controlling_process(client_socket, process_pid)
|
||||
|
||||
loop_acceptor(listener_socket)
|
||||
end
|
||||
end
|
23
lib/rl_repo/application.ex
Normal file
23
lib/rl_repo/application.ex
Normal file
|
@ -0,0 +1,23 @@
|
|||
defmodule RlRepo.Application do
|
||||
# See https://hexdocs.pm/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
@moduledoc false
|
||||
|
||||
use Application
|
||||
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
port = String.to_integer(System.get_env("PORT") || "10002")
|
||||
|
||||
children = [
|
||||
# Starts a worker by calling: RlRepo.Worker.start_link(arg)
|
||||
# {RlRepo.Worker, arg}
|
||||
Supervisor.child_spec({Task, fn -> RlRepo.start(port) end}, restart: :permanent)
|
||||
]
|
||||
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: RlRepo.Supervisor]
|
||||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
end
|
45
lib/routing.ex
Normal file
45
lib/routing.ex
Normal file
|
@ -0,0 +1,45 @@
|
|||
defmodule RlRepo.Router do
|
||||
require Logger
|
||||
@moduledoc """
|
||||
|
||||
"""
|
||||
def route_3( path, request_type) do
|
||||
Logger.info "#{request_type}"
|
||||
{repo_name, pkg_name, action} = path
|
||||
|
||||
if action == "info" do
|
||||
Logger.info "fetching json"
|
||||
end
|
||||
|
||||
{200, "application/json", "{\"pkg_name\": \"#{pkg_name}\"}"}
|
||||
end
|
||||
|
||||
def route_4(path, request_type) do
|
||||
Logger.info "#{request_type}"
|
||||
{repo_name, sub_repo_name, pkg_name, action} = path
|
||||
{200, "text/html", "<p>Hi</p>"}
|
||||
end
|
||||
|
||||
|
||||
def parse_3_segment_path(path) do
|
||||
[repo_name | rest ] = path
|
||||
[pkg_name | rest] = rest
|
||||
[action | _ ] = rest
|
||||
|
||||
Logger.info "REPO #{repo_name} PKG #{pkg_name} ACTION #{action}"
|
||||
|
||||
{repo_name, pkg_name, action}
|
||||
end
|
||||
|
||||
|
||||
def parse_4_segment_path(path) do
|
||||
[repo_name | rest ] = path
|
||||
[sub_repo_name | rest] = rest
|
||||
[pkg_name | rest] = rest
|
||||
[action | _ ] = rest
|
||||
|
||||
Logger.info "REPO #{repo_name} SUB_REPO #{sub_repo_name} PKG #{pkg_name} ACTION #{action}"
|
||||
|
||||
{repo_name, sub_repo_name, pkg_name, action}
|
||||
end
|
||||
end
|
29
mix.exs
Normal file
29
mix.exs
Normal file
|
@ -0,0 +1,29 @@
|
|||
defmodule RlRepo.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :rl_repo,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.12",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger],
|
||||
mod: {RlRepo.Application, []}
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
8
test/rl_repo_test.exs
Normal file
8
test/rl_repo_test.exs
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule RlRepoTest do
|
||||
use ExUnit.Case
|
||||
doctest RlRepo
|
||||
|
||||
test "greets the world" do
|
||||
# assert RlRepo.hello() == :world
|
||||
end
|
||||
end
|
1
test/test_helper.exs
Normal file
1
test/test_helper.exs
Normal file
|
@ -0,0 +1 @@
|
|||
ExUnit.start()
|
Loading…
Reference in a new issue