Compare commits
4 Commits
9c5b332e00
...
3a8c2cf4b0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a8c2cf4b0 | ||
|
|
e6fa8481e8 | ||
|
|
f0725700f0 | ||
|
|
2037444f54 |
242
README.md
242
README.md
@ -563,3 +563,245 @@ start_acceptor(ListenSocket) ->
|
|||||||
- Everything else is boilerplate
|
- Everything else is boilerplate
|
||||||
- So our task is to remove the relay-messages logic, and replace it with http
|
- So our task is to remove the relay-messages logic, and replace it with http
|
||||||
parse/respond logic.
|
parse/respond logic.
|
||||||
|
|
||||||
|
|
||||||
|
### Auto-listening to port `8000`
|
||||||
|
|
||||||
|
- Start commit: `9c5b332e009b88a9400a4e7008f760ce872b810a`
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/gex_httpd/src/gex_httpd.erl b/gex_httpd/src/gex_httpd.erl
|
||||||
|
index 242c82f..3a724b0 100644
|
||||||
|
--- a/gex_httpd/src/gex_httpd.erl
|
||||||
|
+++ b/gex_httpd/src/gex_httpd.erl
|
||||||
|
@@ -9,8 +9,11 @@
|
||||||
|
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
|
||||||
|
|
||||||
|
|
||||||
|
+%% for our edification
|
||||||
|
-export([listen/1, ignore/0]).
|
||||||
|
--export([start/0, start/1]).
|
||||||
|
+-export([start/0]).
|
||||||
|
+
|
||||||
|
+%% erlang expects us to export these functions
|
||||||
|
-export([start/2, stop/1]).
|
||||||
|
|
||||||
|
|
||||||
|
@@ -45,17 +48,17 @@ start() ->
|
||||||
|
io:format("Starting...").
|
||||||
|
|
||||||
|
|
||||||
|
--spec start(PortNum) -> ok
|
||||||
|
- when PortNum :: inet:port_number().
|
||||||
|
-%% @doc
|
||||||
|
-%% Start the server and begin listening immediately. Slightly more convenient when
|
||||||
|
-%% playing around in the shell.
|
||||||
|
-
|
||||||
|
-start(PortNum) ->
|
||||||
|
- ok = start(),
|
||||||
|
- ok = gh_client_man:listen(PortNum),
|
||||||
|
- io:format("Startup complete, listening on ~w~n", [PortNum]).
|
||||||
|
-
|
||||||
|
+%-spec start(PortNum) -> ok
|
||||||
|
+% when PortNum :: inet:port_number().
|
||||||
|
+%%% @doc
|
||||||
|
+%%% Start the server and begin listening immediately. Slightly more convenient when
|
||||||
|
+%%% playing around in the shell.
|
||||||
|
+%
|
||||||
|
+%start(PortNum) ->
|
||||||
|
+% ok = start(),
|
||||||
|
+% ok = gh_client_man:listen(PortNum),
|
||||||
|
+% io:format("Startup complete, listening on ~w~n", [PortNum]).
|
||||||
|
+%
|
||||||
|
|
||||||
|
-spec start(normal, term()) -> {ok, pid()}.
|
||||||
|
%% @private
|
||||||
|
@@ -64,7 +67,10 @@ start(PortNum) ->
|
||||||
|
%% See: http://erlang.org/doc/apps/kernel/application.html
|
||||||
|
|
||||||
|
start(normal, _Args) ->
|
||||||
|
- gh_sup:start_link().
|
||||||
|
+ Result = gh_sup:start_link(),
|
||||||
|
+ % auto-listen to port 8000
|
||||||
|
+ ok = listen(8000),
|
||||||
|
+ Result.
|
||||||
|
|
||||||
|
|
||||||
|
-spec stop(term()) -> ok.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deleting the relay logic
|
||||||
|
|
||||||
|
- Start commit: `2037444f54d8f95a959c7e67673d55782fad5ad3`
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/gex_httpd/src/gh_client.erl b/gex_httpd/src/gh_client.erl
|
||||||
|
index ea5b3ef..44d206d 100644
|
||||||
|
--- a/gex_httpd/src/gh_client.erl
|
||||||
|
+++ b/gex_httpd/src/gh_client.erl
|
||||||
|
@@ -127,22 +127,10 @@ listen(Parent, Debug, ListenSocket) ->
|
||||||
|
loop(Parent, Debug, State = #s{socket = Socket}) ->
|
||||||
|
ok = inet:setopts(Socket, [{active, once}]),
|
||||||
|
receive
|
||||||
|
- {tcp, Socket, <<"bye\r\n">>} ->
|
||||||
|
- ok = io:format("~p Client saying goodbye. Bye!~n", [self()]),
|
||||||
|
- ok = gen_tcp:send(Socket, "Bye!\r\n"),
|
||||||
|
- ok = gen_tcp:shutdown(Socket, read_write),
|
||||||
|
- exit(normal);
|
||||||
|
{tcp, Socket, Message} ->
|
||||||
|
ok = io:format("~p received: ~tp~n", [self(), Message]),
|
||||||
|
ok = gh_client_man:echo(Message),
|
||||||
|
loop(Parent, Debug, State);
|
||||||
|
- {relay, Sender, Message} when Sender == self() ->
|
||||||
|
- ok = gen_tcp:send(Socket, ["Message from YOU: ", Message]),
|
||||||
|
- loop(Parent, Debug, State);
|
||||||
|
- {relay, Sender, Message} ->
|
||||||
|
- From = io_lib:format("Message from ~tp: ", [Sender]),
|
||||||
|
- ok = gen_tcp:send(Socket, [From, Message]),
|
||||||
|
- loop(Parent, Debug, State);
|
||||||
|
{tcp_closed, Socket} ->
|
||||||
|
ok = io:format("~p Socket closed, retiring.~n", [self()]),
|
||||||
|
exit(normal);
|
||||||
|
diff --git a/gex_httpd/src/gh_client_man.erl b/gex_httpd/src/gh_client_man.erl
|
||||||
|
index 9c78921..c913dcc 100644
|
||||||
|
--- a/gex_httpd/src/gh_client_man.erl
|
||||||
|
+++ b/gex_httpd/src/gh_client_man.erl
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
-export([listen/1, ignore/0]).
|
||||||
|
--export([enroll/0, echo/1]).
|
||||||
|
+-export([enroll/0]).
|
||||||
|
-export([start_link/0]).
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
code_change/3, terminate/2]).
|
||||||
|
@@ -74,17 +74,6 @@ enroll() ->
|
||||||
|
gen_server:cast(?MODULE, {enroll, self()}).
|
||||||
|
|
||||||
|
|
||||||
|
--spec echo(Message) -> ok
|
||||||
|
- when Message :: string().
|
||||||
|
-%% @doc
|
||||||
|
-%% The function that tells the manager to broadcast a message to all clients.
|
||||||
|
-%% This can broadcast arbitrary strings to clients from non-clients as well.
|
||||||
|
-
|
||||||
|
-echo(Message) ->
|
||||||
|
- gen_server:cast(?MODULE, {echo, Message, self()}).
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-
|
||||||
|
%%% Startup Functions
|
||||||
|
|
||||||
|
|
||||||
|
@@ -145,9 +134,6 @@ handle_call(Unexpected, From, State) ->
|
||||||
|
handle_cast({enroll, Pid}, State) ->
|
||||||
|
NewState = do_enroll(Pid, State),
|
||||||
|
{noreply, NewState};
|
||||||
|
-handle_cast({echo, Message, Sender}, State) ->
|
||||||
|
- ok = do_echo(Message, Sender, State),
|
||||||
|
- {noreply, State};
|
||||||
|
handle_cast(ignore, State) ->
|
||||||
|
NewState = do_ignore(State),
|
||||||
|
{noreply, NewState};
|
||||||
|
@@ -262,17 +248,6 @@ do_enroll(Pid, State = #s{clients = Clients}) ->
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
--spec do_echo(Message, Sender, State) -> ok
|
||||||
|
- when Message :: string(),
|
||||||
|
- Sender :: pid(),
|
||||||
|
- State :: state().
|
||||||
|
-%% @private
|
||||||
|
-%% The "doer" procedure called when an "echo" message is received.
|
||||||
|
-
|
||||||
|
-do_echo(Message, Sender, #s{clients = Clients}) ->
|
||||||
|
- Send = fun(Client) -> Client ! {relay, Sender, Message} end,
|
||||||
|
- lists:foreach(Send, Clients).
|
||||||
|
-
|
||||||
|
|
||||||
|
-spec handle_down(Mon, Pid, Reason, State) -> NewState
|
||||||
|
when Mon :: reference(),
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding QHL as a dependency
|
||||||
|
|
||||||
|
[QHL](https://git.qpq.swiss/qPQ-AG/qhl) is our own internal parsing library for
|
||||||
|
HTTP/1.1 requests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zx set dep otpr-qhl-0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/gex_httpd/zomp.meta b/gex_httpd/zomp.meta
|
||||||
|
index 7111f2d..09d84c2 100644
|
||||||
|
--- a/gex_httpd/zomp.meta
|
||||||
|
+++ b/gex_httpd/zomp.meta
|
||||||
|
@@ -1,17 +1,17 @@
|
||||||
|
-{a_email,"peterharpending@qpq.swiss"}.
|
||||||
|
+{name,"Gajumaru DEX HTTP Daemon"}.
|
||||||
|
+{type,app}.
|
||||||
|
+{modules,[]}.
|
||||||
|
+{prefix,"gh"}.
|
||||||
|
{author,"Peter Harpending"}.
|
||||||
|
+{desc,"Gajumaru Exchange HTTP Daemon"}.
|
||||||
|
+{package_id,{"otpr","gex_httpd",{0,1,0}}}.
|
||||||
|
+{deps,[{"otpr","qhl",{0,1,0}}]}.
|
||||||
|
+{key_name,none}.
|
||||||
|
+{a_email,"peterharpending@qpq.swiss"}.
|
||||||
|
{c_email,"peterharpending@qpq.swiss"}.
|
||||||
|
{copyright,"Peter Harpending"}.
|
||||||
|
-{deps,[]}.
|
||||||
|
-{desc,"Gajumaru Exchange HTTP Daemon"}.
|
||||||
|
{file_exts,[]}.
|
||||||
|
-{key_name,none}.
|
||||||
|
{license,skip}.
|
||||||
|
-{modules,[]}.
|
||||||
|
-{name,"Gajumaru DEX HTTP Daemon"}.
|
||||||
|
-{package_id,{"otpr","gex_httpd",{0,1,0}}}.
|
||||||
|
-{prefix,"gh"}.
|
||||||
|
{repo_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
||||||
|
{tags,[]}.
|
||||||
|
-{type,app}.
|
||||||
|
{ws_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding the QHL header file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://git.qpq.swiss/QPQ-AG/QHL/raw/branch/master/include/http.hrl -O gex_httpd/include/http.hrl
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/gex_httpd/include/http.hrl b/gex_httpd/include/http.hrl
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..27d24d2
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/gex_httpd/include/http.hrl
|
||||||
|
@@ -0,0 +1,25 @@
|
||||||
|
+-record(request,
|
||||||
|
+ {method = undefined :: undefined | method(),
|
||||||
|
+ path = undefined :: undefined | binary(),
|
||||||
|
+ qargs = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
||||||
|
+ fragment = undefined :: undefined | none | binary(),
|
||||||
|
+ version = undefined :: undefined | http10 | http11 | http20,
|
||||||
|
+ headers = undefined :: undefined | [{Key :: binary(), Value :: binary()}],
|
||||||
|
+ cookies = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
||||||
|
+ enctype = undefined :: undefined | none | urlencoded | multipart(),
|
||||||
|
+ size = undefined :: undefined | none | non_neg_integer(),
|
||||||
|
+ body = undefined :: undefined | none | body()}).
|
||||||
|
+
|
||||||
|
+-record(response,
|
||||||
|
+ {type = page :: page | {data, string()},
|
||||||
|
+ version = http11 :: http11,
|
||||||
|
+ code = 200 :: pos_integer(),
|
||||||
|
+ slogan = "" :: string(),
|
||||||
|
+ headers = [] :: [{Key :: string(), Value :: iolist()}],
|
||||||
|
+ body = "" :: iolist()}).
|
||||||
|
+
|
||||||
|
+-type method() :: get | post | options.
|
||||||
|
+-type multipart() :: {multipart, Boundary :: binary()}.
|
||||||
|
+-type body() :: {partial, binary()} | {multipart, [body_part()]} | binary().
|
||||||
|
+-type body_part() :: {Field :: binary(), Data :: binary()}
|
||||||
|
+ | {Field :: binary(), Name :: binary(), Data :: binary()}.
|
||||||
|
```
|
||||||
|
|||||||
25
gex_httpd/include/http.hrl
Normal file
25
gex_httpd/include/http.hrl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-record(request,
|
||||||
|
{method = undefined :: undefined | method(),
|
||||||
|
path = undefined :: undefined | binary(),
|
||||||
|
qargs = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
||||||
|
fragment = undefined :: undefined | none | binary(),
|
||||||
|
version = undefined :: undefined | http10 | http11 | http20,
|
||||||
|
headers = undefined :: undefined | [{Key :: binary(), Value :: binary()}],
|
||||||
|
cookies = undefined :: undefined | #{Key :: binary() := Value :: binary()},
|
||||||
|
enctype = undefined :: undefined | none | urlencoded | multipart(),
|
||||||
|
size = undefined :: undefined | none | non_neg_integer(),
|
||||||
|
body = undefined :: undefined | none | body()}).
|
||||||
|
|
||||||
|
-record(response,
|
||||||
|
{type = page :: page | {data, string()},
|
||||||
|
version = http11 :: http11,
|
||||||
|
code = 200 :: pos_integer(),
|
||||||
|
slogan = "" :: string(),
|
||||||
|
headers = [] :: [{Key :: string(), Value :: iolist()}],
|
||||||
|
body = "" :: iolist()}).
|
||||||
|
|
||||||
|
-type method() :: get | post | options.
|
||||||
|
-type multipart() :: {multipart, Boundary :: binary()}.
|
||||||
|
-type body() :: {partial, binary()} | {multipart, [body_part()]} | binary().
|
||||||
|
-type body_part() :: {Field :: binary(), Data :: binary()}
|
||||||
|
| {Field :: binary(), Name :: binary(), Data :: binary()}.
|
||||||
@ -9,8 +9,11 @@
|
|||||||
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
|
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
|
||||||
|
|
||||||
|
|
||||||
|
%% for our edification
|
||||||
-export([listen/1, ignore/0]).
|
-export([listen/1, ignore/0]).
|
||||||
-export([start/0, start/1]).
|
-export([start/0]).
|
||||||
|
|
||||||
|
%% erlang expects us to export these functions
|
||||||
-export([start/2, stop/1]).
|
-export([start/2, stop/1]).
|
||||||
|
|
||||||
|
|
||||||
@ -45,17 +48,17 @@ start() ->
|
|||||||
io:format("Starting...").
|
io:format("Starting...").
|
||||||
|
|
||||||
|
|
||||||
-spec start(PortNum) -> ok
|
%-spec start(PortNum) -> ok
|
||||||
when PortNum :: inet:port_number().
|
% when PortNum :: inet:port_number().
|
||||||
%% @doc
|
%%% @doc
|
||||||
%% Start the server and begin listening immediately. Slightly more convenient when
|
%%% Start the server and begin listening immediately. Slightly more convenient when
|
||||||
%% playing around in the shell.
|
%%% playing around in the shell.
|
||||||
|
%
|
||||||
start(PortNum) ->
|
%start(PortNum) ->
|
||||||
ok = start(),
|
% ok = start(),
|
||||||
ok = gh_client_man:listen(PortNum),
|
% ok = gh_client_man:listen(PortNum),
|
||||||
io:format("Startup complete, listening on ~w~n", [PortNum]).
|
% io:format("Startup complete, listening on ~w~n", [PortNum]).
|
||||||
|
%
|
||||||
|
|
||||||
-spec start(normal, term()) -> {ok, pid()}.
|
-spec start(normal, term()) -> {ok, pid()}.
|
||||||
%% @private
|
%% @private
|
||||||
@ -64,7 +67,10 @@ start(PortNum) ->
|
|||||||
%% See: http://erlang.org/doc/apps/kernel/application.html
|
%% See: http://erlang.org/doc/apps/kernel/application.html
|
||||||
|
|
||||||
start(normal, _Args) ->
|
start(normal, _Args) ->
|
||||||
gh_sup:start_link().
|
Result = gh_sup:start_link(),
|
||||||
|
% auto-listen to port 8000
|
||||||
|
ok = listen(8000),
|
||||||
|
Result.
|
||||||
|
|
||||||
|
|
||||||
-spec stop(term()) -> ok.
|
-spec stop(term()) -> ok.
|
||||||
|
|||||||
@ -127,22 +127,10 @@ listen(Parent, Debug, ListenSocket) ->
|
|||||||
loop(Parent, Debug, State = #s{socket = Socket}) ->
|
loop(Parent, Debug, State = #s{socket = Socket}) ->
|
||||||
ok = inet:setopts(Socket, [{active, once}]),
|
ok = inet:setopts(Socket, [{active, once}]),
|
||||||
receive
|
receive
|
||||||
{tcp, Socket, <<"bye\r\n">>} ->
|
|
||||||
ok = io:format("~p Client saying goodbye. Bye!~n", [self()]),
|
|
||||||
ok = gen_tcp:send(Socket, "Bye!\r\n"),
|
|
||||||
ok = gen_tcp:shutdown(Socket, read_write),
|
|
||||||
exit(normal);
|
|
||||||
{tcp, Socket, Message} ->
|
{tcp, Socket, Message} ->
|
||||||
ok = io:format("~p received: ~tp~n", [self(), Message]),
|
ok = io:format("~p received: ~tp~n", [self(), Message]),
|
||||||
ok = gh_client_man:echo(Message),
|
ok = gh_client_man:echo(Message),
|
||||||
loop(Parent, Debug, State);
|
loop(Parent, Debug, State);
|
||||||
{relay, Sender, Message} when Sender == self() ->
|
|
||||||
ok = gen_tcp:send(Socket, ["Message from YOU: ", Message]),
|
|
||||||
loop(Parent, Debug, State);
|
|
||||||
{relay, Sender, Message} ->
|
|
||||||
From = io_lib:format("Message from ~tp: ", [Sender]),
|
|
||||||
ok = gen_tcp:send(Socket, [From, Message]),
|
|
||||||
loop(Parent, Debug, State);
|
|
||||||
{tcp_closed, Socket} ->
|
{tcp_closed, Socket} ->
|
||||||
ok = io:format("~p Socket closed, retiring.~n", [self()]),
|
ok = io:format("~p Socket closed, retiring.~n", [self()]),
|
||||||
exit(normal);
|
exit(normal);
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
|
|
||||||
-export([listen/1, ignore/0]).
|
-export([listen/1, ignore/0]).
|
||||||
-export([enroll/0, echo/1]).
|
-export([enroll/0]).
|
||||||
-export([start_link/0]).
|
-export([start_link/0]).
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
code_change/3, terminate/2]).
|
code_change/3, terminate/2]).
|
||||||
@ -74,17 +74,6 @@ enroll() ->
|
|||||||
gen_server:cast(?MODULE, {enroll, self()}).
|
gen_server:cast(?MODULE, {enroll, self()}).
|
||||||
|
|
||||||
|
|
||||||
-spec echo(Message) -> ok
|
|
||||||
when Message :: string().
|
|
||||||
%% @doc
|
|
||||||
%% The function that tells the manager to broadcast a message to all clients.
|
|
||||||
%% This can broadcast arbitrary strings to clients from non-clients as well.
|
|
||||||
|
|
||||||
echo(Message) ->
|
|
||||||
gen_server:cast(?MODULE, {echo, Message, self()}).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%% Startup Functions
|
%%% Startup Functions
|
||||||
|
|
||||||
|
|
||||||
@ -145,9 +134,6 @@ handle_call(Unexpected, From, State) ->
|
|||||||
handle_cast({enroll, Pid}, State) ->
|
handle_cast({enroll, Pid}, State) ->
|
||||||
NewState = do_enroll(Pid, State),
|
NewState = do_enroll(Pid, State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
handle_cast({echo, Message, Sender}, State) ->
|
|
||||||
ok = do_echo(Message, Sender, State),
|
|
||||||
{noreply, State};
|
|
||||||
handle_cast(ignore, State) ->
|
handle_cast(ignore, State) ->
|
||||||
NewState = do_ignore(State),
|
NewState = do_ignore(State),
|
||||||
{noreply, NewState};
|
{noreply, NewState};
|
||||||
@ -262,17 +248,6 @@ do_enroll(Pid, State = #s{clients = Clients}) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec do_echo(Message, Sender, State) -> ok
|
|
||||||
when Message :: string(),
|
|
||||||
Sender :: pid(),
|
|
||||||
State :: state().
|
|
||||||
%% @private
|
|
||||||
%% The "doer" procedure called when an "echo" message is received.
|
|
||||||
|
|
||||||
do_echo(Message, Sender, #s{clients = Clients}) ->
|
|
||||||
Send = fun(Client) -> Client ! {relay, Sender, Message} end,
|
|
||||||
lists:foreach(Send, Clients).
|
|
||||||
|
|
||||||
|
|
||||||
-spec handle_down(Mon, Pid, Reason, State) -> NewState
|
-spec handle_down(Mon, Pid, Reason, State) -> NewState
|
||||||
when Mon :: reference(),
|
when Mon :: reference(),
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
{a_email,"peterharpending@qpq.swiss"}.
|
{name,"Gajumaru DEX HTTP Daemon"}.
|
||||||
|
{type,app}.
|
||||||
|
{modules,[]}.
|
||||||
|
{prefix,"gh"}.
|
||||||
{author,"Peter Harpending"}.
|
{author,"Peter Harpending"}.
|
||||||
|
{desc,"Gajumaru Exchange HTTP Daemon"}.
|
||||||
|
{package_id,{"otpr","gex_httpd",{0,1,0}}}.
|
||||||
|
{deps,[{"otpr","qhl",{0,1,0}}]}.
|
||||||
|
{key_name,none}.
|
||||||
|
{a_email,"peterharpending@qpq.swiss"}.
|
||||||
{c_email,"peterharpending@qpq.swiss"}.
|
{c_email,"peterharpending@qpq.swiss"}.
|
||||||
{copyright,"Peter Harpending"}.
|
{copyright,"Peter Harpending"}.
|
||||||
{deps,[]}.
|
|
||||||
{desc,"Gajumaru Exchange HTTP Daemon"}.
|
|
||||||
{file_exts,[]}.
|
{file_exts,[]}.
|
||||||
{key_name,none}.
|
|
||||||
{license,skip}.
|
{license,skip}.
|
||||||
{modules,[]}.
|
|
||||||
{name,"Gajumaru DEX HTTP Daemon"}.
|
|
||||||
{package_id,{"otpr","gex_httpd",{0,1,0}}}.
|
|
||||||
{prefix,"gh"}.
|
|
||||||
{repo_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
{repo_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
||||||
{tags,[]}.
|
{tags,[]}.
|
||||||
{type,app}.
|
|
||||||
{ws_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
{ws_url,"https://git.qpq.swiss/QPQ-AG/gex"}.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user