Packages
lustre
3.1.4
5.7.1
5.7.0
5.6.0
5.5.2
5.5.1
5.5.0
5.4.0
5.3.5
5.3.4
5.3.3
5.3.2
5.3.1
5.3.0
5.2.1
5.2.0
5.1.1
5.1.0
5.0.3
5.0.2
5.0.1
5.0.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.1
4.5.0
4.4.4
4.4.3
4.4.1
4.4.0
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.8
4.1.7
4.1.6
4.1.5
4.1.4
4.1.3
4.1.2
4.1.1
4.1.0
4.0.0
4.0.0-rc1
4.0.0-rc.2
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.5
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.2
3.0.0-rc.1
2.0.1
2.0.0
1.3.0
1.2.0
1.1.0
1.0.0
Create HTML templates, single page applications, Web Components, and real-time server components in Gleam!
Current section
Files
Jump to
Current section
Files
src/http_ffi.erl
-module(http_ffi).
-export([exec/1, serve/3, response_default_headers/0]).
exec(Command) ->
os:cmd(binary_to_list(Command)).
serve({options, Host, Port, IncludeStyles}, OnStart, OnPortTaken) ->
{ok, Pattern} = re:compile("name *= *\"(?<Name>.+)\""),
{ok, Toml} = file:read_file("gleam.toml"),
{match, [Name]} = re:run(Toml, Pattern, [{capture, all_names, binary}]),
Html =
<<
"<!DOCTYPE html>\n"
"<html lang=\"en\">\n"
"<head>\n"
" <meta charset=\"UTF-8\">\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
" <title>Lustre preview server</title>\n",
case IncludeStyles of
true ->
<<" <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/lustre-labs/ui/priv/styles.css\">\n">>;
false ->
<<"">>
end/binary,
" <script type=\"module\">\n"
" import { main } from './",
Name/binary,
"/",
Name/binary,
".mjs'\n"
"\n"
" document.addEventListener(\"DOMContentLoaded\", () => {\n"
" main();\n"
" });\n"
" </script>\n"
"</head>\n"
"<body>\n"
" <div data-lustre-app></div>\n"
"</body>\n"
"</html>"
>>,
file:write_file("build/dev/javascript/index.html", Html),
AbsPath =
string:trim(
filename:absname("build/dev/javascript"), trailing, "/."
),
inets:start(),
Address = {127, 0, 0, 1},
ActualPort =
case port_available(Port) of
true ->
Port;
false ->
OnPortTaken(Port),
first_available_port(Port + 1)
end,
{ok, Pid} =
httpd:start_service([
{bind_address, Address},
{document_root, AbsPath},
{server_root, AbsPath},
{directory_index, ["index.html"]},
{server_name, binary_to_list(Host)},
{port, ActualPort},
{default_type, "text/html"},
{mime_types, mime_types()},
{customize, ?MODULE},
{modules, [mod_alias, mod_dir, mod_get]}
]),
OnStart(ActualPort),
receive
{From, shutdown} ->
ok = httpd:stop_service(Pid),
From ! done
end.
port_available(Port) ->
case gen_tcp:listen(Port, []) of
{ok, Sock} ->
ok = gen_tcp:close(Sock),
true;
_ ->
false
end.
first_available_port(Port) ->
case port_available(Port) of
true -> Port;
false -> first_available_port(Port + 1)
end.
mime_types() ->
[
{"html", "text/html"},
{"htm", "text/html"},
{"js", "text/javascript"},
{"mjs", "text/javascript"},
{"css", "text/css"},
{"gif", "image/gif"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"png", "image/png"}
].
response_default_headers() ->
[
{"cache-control", "no-store, no-cache, must-revalidate, private"},
{"pragma", "no-cache"}
].