Chat with websockets
- -
-
-
-
-
- diff --git a/priv/chat.html b/priv/chat.html deleted file mode 100644 index 895393b..0000000 --- a/priv/chat.html +++ /dev/null @@ -1,100 +0,0 @@ - - -
- - blocks that do not have a block as an ancestor
- *
- * ie the `inline code`
- */
-code:not(pre *) {
- border-radius: 6px;
- border: 1px solid var(--lgray1);
- padding-left: 3px;
- padding-right: 3px;
- padding-top: 1px;
- padding-bottom: 1px;
- background: var(--lgreen1);
-}
-
-/* this is specifically for ```fenced blocks``` */
-pre {
- border-radius: 6px;
- border: 1px solid var(--lgray1);
- padding: 5px;
- background: var(--lgreen1);
- overflow: scroll;
-}
-
-/* All `unfenced` or ```fenced``` blocks */
-code {
- font-family: Liberation Mono, Roboto Mono, monospace;
- color: var(--dgreen1);
-}
diff --git a/priv/ws-test-echo.html b/priv/ws-test-echo.html
deleted file mode 100644
index 2c3d47d..0000000
--- a/priv/ws-test-echo.html
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
- Websockets echo test
-
-
-
-
- Websockets echo test
-
-
-
-
-
-
-
-
-
-
diff --git a/src/fd_client.erl b/src/fd_client.erl
index c50d18a..f5e7fcb 100644
--- a/src/fd_client.erl
+++ b/src/fd_client.erl
@@ -224,12 +224,9 @@ handle_request(Sock, R = #request{method = M, path = P}) when M =/= undefined, P
route(Sock, get, Route, Request) ->
case Route of
- <<"/">> -> home(Sock);
- <<"/default.css">> -> default_css(Sock);
- <<"/chat.html">> -> chat_html(Sock);
- <<"/ws-test-echo.html">> -> ws_test_echo_html(Sock);
- <<"/ws/echo">> -> ws_echo(Sock, Request);
- _ -> http_err(Sock, 404)
+ <<"/ws/echo">> -> ws_echo(Sock, Request);
+ <<"/">> -> route_static(Sock, <<"/index.html">>);
+ _ -> route_static(Sock, Route)
end;
route(Sock, post, Route, Request) ->
case Route of
@@ -240,6 +237,28 @@ route(Sock, _, _, _) ->
http_err(Sock, 404).
+route_static(Sock, Route) ->
+ respond_static(Sock, fd_sfc:query(Route)).
+
+respond_static(Sock, {found, Entry}) ->
+ % -record(e, {fs_path :: file:filename(),
+ % last_modified :: file:date_time(),
+ % mime_type :: string(),
+ % encoding :: encoding(),
+ % contents :: binary()}).
+ Headers0 =
+ case fd_sfc_entry:encoding(Entry) of
+ gzip -> [{"content-encoding", "gzip"}];
+ none -> []
+ end,
+ Headers1 = [{"content-type", fd_sfc_entry:mime_type(Entry)} | Headers0],
+ Response = #response{headers = Headers1,
+ body = fd_sfc_entry:contents(Entry)},
+ respond(Sock, Response);
+respond_static(Sock, not_found) ->
+ http_err(Sock, 404).
+
+
ws_echo(Sock, Request) ->
try
ws_echo2(Sock, Request)
@@ -279,59 +298,6 @@ ws_echo_loop(Sock, Frames, Received) ->
error(Error)
end.
-
-home(Sock) ->
- %% fixme: cache
- Path_IH = filename:join([zx:get_home(), "priv", "index.html"]),
- case file:read_file(Path_IH) of
- {ok, Body} ->
- Resp = #response{headers = [{"content-type", "text/html"}],
- body = Body},
- respond(Sock, Resp);
- Error ->
- tell("error: ~p~n", [self(), Error]),
- http_err(Sock, 500)
- end.
-
-default_css(Sock) ->
- %% fixme: cache
- Path_IH = filename:join([zx:get_home(), "priv", "default.css"]),
- case file:read_file(Path_IH) of
- {ok, Body} ->
- Resp = #response{headers = [{"content-type", "text/css"}],
- body = Body},
- respond(Sock, Resp);
- Error ->
- io:format("~p error: ~p~n", [self(), Error]),
- http_err(Sock, 500)
- end.
-
-ws_test_echo_html(Sock) ->
- %% fixme: cache
- Path_IH = filename:join([zx:get_home(), "priv", "ws-test-echo.html"]),
- case file:read_file(Path_IH) of
- {ok, Body} ->
- Resp = #response{headers = [{"content-type", "text/html"}],
- body = Body},
- respond(Sock, Resp);
- Error ->
- io:format("~p error: ~p~n", [self(), Error]),
- http_err(Sock, 500)
- end.
-
-chat_html(Sock) ->
- %% fixme: cache
- Path_IH = filename:join([zx:get_home(), "priv", "chat.html"]),
- case file:read_file(Path_IH) of
- {ok, Body} ->
- Resp = #response{headers = [{"content-type", "text/html"}],
- body = Body},
- respond(Sock, Resp);
- Error ->
- io:format("~p error: ~p~n", [self(), Error]),
- http_err(Sock, 500)
- end.
-
wfcin(Sock, #request{enctype = json,
cookies = Cookies,
body = #{"wfcin" := Input}}) ->
diff --git a/src/fd_sfc.erl b/src/fd_sfc.erl
index 32347e9..bc17c2d 100644
--- a/src/fd_sfc.erl
+++ b/src/fd_sfc.erl
@@ -5,6 +5,8 @@
-export([
%% caller context
+ base_path/0,
+ renew/0, query/1,
start_link/0,
%% process context
@@ -15,8 +17,24 @@
-include("$zx_include/zx_logger.hrl").
--record(s, {cache = fd_sfc_cache:new() :: fd_sfc_cache:cache()}).
--type state() :: #s{}.
+-record(s, {base_path = base_path() :: file:filename(),
+ cache = fd_sfc_cache:new(base_path()) :: fd_sfc_cache:cache(),
+ auto_renew = 5_000 :: pos_integer()}).
+%-type state() :: #s{}.
+
+
+%%-----------------------------------------------------------------------------
+%% caller context
+%%-----------------------------------------------------------------------------
+
+base_path() ->
+ filename:join([zx:get_home(), "priv", "static"]).
+
+renew() ->
+ gen_server:cast(?MODULE, renew).
+
+query(Path) ->
+ gen_server:call(?MODULE, {query, Path}).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, none, []).
@@ -31,19 +49,31 @@ start_link() ->
init(none) ->
log(info, "starting fd_cache"),
InitState = #s{},
+ erlang:send_after(3_000, self(), auto_renew),
{ok, InitState}.
+handle_call({query, Path}, _, State = #s{cache = Cache}) ->
+ Reply = fd_sfc_cache:query(Path, Cache),
+ {reply, Reply, State};
handle_call(Unexpected, From, State) ->
tell("~tp: unexpected call from ~tp: ~tp", [?MODULE, Unexpected, From]),
{noreply, State}.
+handle_cast(renew, State) ->
+ NewState = i_renew(State),
+ {noreply, NewState};
handle_cast(Unexpected, State) ->
tell("~tp: unexpected cast: ~tp", [?MODULE, Unexpected]),
{noreply, State}.
+handle_info(auto_renew, State = #s{auto_renew = MS}) ->
+ log(info, "~tp: auto_renew", [?MODULE]),
+ erlang:send_after(MS, self(), auto_renew),
+ NewState = i_renew(State),
+ {noreply, NewState};
handle_info(Unexpected, State) ->
tell("~tp: unexpected info: ~tp", [?MODULE, Unexpected]),
{noreply, State}.
@@ -54,3 +84,13 @@ code_change(_, State, _) ->
terminate(_, _) ->
ok.
+
+
+%%-----------------------------------------------------------------------------
+%% internals
+%%-----------------------------------------------------------------------------
+
+i_renew(State = #s{base_path = BasePath}) ->
+ NewCache = fd_sfc_cache:new(BasePath),
+ NewState = State#s{cache = NewCache},
+ NewState.
diff --git a/src/fd_sfc_entry.erl b/src/fd_sfc_entry.erl
index a363484..623bd73 100644
--- a/src/fd_sfc_entry.erl
+++ b/src/fd_sfc_entry.erl
@@ -50,7 +50,7 @@ contents(#e{contents = X}) -> X.
% returns not_found if ANY I/O error occurs during the process. will be logged
new(Path) ->
- tell("~tp:new(~tp)", [?MODULE, Path]),
+ log(info, "~tp:new(~tp)", [?MODULE, Path]),
case file:read_file(Path) of
{ok, Binary} ->
{found, new2(Path, Binary)};