> git clone git://github.com/basho/rebar.git && cd rebar && ./bootstrap
> sudo ln -s `pwd`/rebar /usr/bin/rebar
> mkdir webserver && cd webserver && rebar create-app appid=webserver
rebar create-app appid=webserver
creates the skeleton of the simplest Erlang application and now our webserver directory should look like this: {deps, [ {cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {branch, "master"}}}, {sync, ".*", {git, "git://github.com/rustyio/sync.git", {branch, "master"}}}, {mimetypes, ".*", {git, "git://github.com/spawngrid/mimetypes.git", {branch, "master"}}}, {erlydtl, ".*", {git, "git://github.com/evanmiller/erlydtl.git", {branch, "master"}}} ]}.
-module(webserver). %% API -export([ start/0, stop/0 ]). -define(APPS, [crypto, ranch, cowboy, webserver]). %% =================================================================== %% API functions %% =================================================================== start() -> ok = ensure_started(?APPS), ok = sync:go(). stop() -> sync:stop(), ok = stop_apps(lists:reverse(?APPS)). %% =================================================================== %% Internal functions %% =================================================================== ensure_started([]) -> ok; ensure_started([App | Apps]) -> case application:start(App) of ok -> ensure_started(Apps); {error, {already_started, App}} -> ensure_started(Apps) end. stop_apps([]) -> ok; stop_apps([App | Apps]) -> application:stop(App), stop_apps(Apps).
start(_StartType, _StartArgs) -> Dispatch = cowboy_router:compile([ {'_', [ {"/", index_handler, []}, {'_', notfound_handler, []} ]} ]), Port = 8008, {ok, _} = cowboy:start_http(http_listener, 100, [{port, Port}], [{env, [{dispatch, Dispatch}]}] ), webserver_sup:start_link().
-module(index_handler). -behaviour(cowboy_http_handler). %% Cowboy_http_handler callbacks -export([ init/3, handle/2, terminate/3 ]). init({tcp, http}, Req, _Opts) -> {ok, Req, undefined_state}. handle(Req, State) -> Body = <<"<h1>It works!</h1>">>, {ok, Req2} = cowboy_req:reply(200, [], Body, Req), {ok, Req2, State}. terminate(_Reason, _Req, _State) -> ok.
-module(notfound_handler). -behaviour(cowboy_http_handler). %% Cowboy_http_handler callbacks -export([ init/3, handle/2, terminate/3 ]). init({tcp, http}, Req, _Opts) -> {ok, Req, undefined_state}. handle(Req, State) -> Body = <<"<h1>404 Page Not Found</h1>">>, {ok, Req2} = cowboy_req:reply(404, [], Body, Req), {ok, Req2, State}. terminate(_Reason, _Req, _State) -> ok.
> rebar get-deps > rebar compile > erl -pa ebin deps/*/ebin -s webserver
rebar get-deps
pull up dependencies from the config, rebar compile
compile the code, and erl -pa ebin deps/*/ebin -s webserver
will start the server itself. By the way, it's time to create a simple Makefile to facilitate the implementation of the above operations:REBAR = `which rebar` all: deps compile deps: @ ($ (REBAR) get-deps) compile: clean @ ($ (REBAR) compile) clean: @ ($ (REBAR) clean) run: @ (erl -pa ebin deps / * / ebin -s webserver) .PHONY: all deps compile clean run
make
, and run by calling make run
{"/", index_handler, []}, {'_', notfound_handler, []}
/css/WHATEVER -> /priv/css/WHATEVER /js/WHATEVER -> /priv/js/WHATEVER /img/WHATEVER -> priv/img/WHATEVER
Dispatch = cowboy_router:compile([ {'_', [ {"/css/[...]", cowboy_static, [ {directory, {priv_dir, webserver, [<<"css">>]}}, {mimetypes, {fun mimetypes:path_to_mimes/2, default}} ]}, {"/js/[...]", cowboy_static, [ {directory, {priv_dir, webserver, [<<"js">>]}}, {mimetypes, {fun mimetypes:path_to_mimes/2, default}} ]}, {"/img/[...]", cowboy_static, [ {directory, {priv_dir, webserver, [<<"img">>]}}, {mimetypes, {fun mimetypes:path_to_mimes/2, default}} ]}, {"/", index_handler, []}, {'_', notfound_handler, []} ]} ]).
Static = fun(Filetype) -> {lists:append(["/", Filetype, "/[...]"]), cowboy_static, [ {directory, {priv_dir, webserver, [list_to_binary(Filetype)]}}, {mimetypes, {fun mimetypes:path_to_mimes/2, default}} ]} end, Dispatch = cowboy_router:compile([ {'_', [ Static("css"), Static("js"), Static("img"), {"/", index_handler, []}, {'_', notfound_handler, []} ]} ]).
-module(webserver_app). -behaviour(application). %% Application callbacks -export([ start/2, stop/1 ]). %% API -export([dispatch_rules/0]). %% =================================================================== %% API functions %% =================================================================== dispatch_rules() -> Static = fun(Filetype) -> {lists:append(["/", Filetype, "/[...]"]), cowboy_static, [ {directory, {priv_dir, webserver, [list_to_binary(Filetype)]}}, {mimetypes, {fun mimetypes:path_to_mimes/2, default}} ]} end, cowboy_router:compile([ {'_', [ Static("css"), Static("js"), Static("img"), {"/", index_handler, []}, {'_', notfound_handler, []} ]} ]). %% =================================================================== %% Application callbacks %% =================================================================== start(_StartType, _StartArgs) -> Dispatch = dispatch_rules(), Port = 8008, {ok, _} = cowboy:start_http(http_listener, 100, [{port, Port}], [{env, [{dispatch, Dispatch}]}] ), webserver_sup:start_link(). stop(_State) -> ok.
update_routes() -> Routes = webserver_app:dispatch_rules(), cowboy:set_env(http_listener, dispatch, Routes).
%% API -export([ start/0, stop/0, update_routes/0 ]).
webserver:update_routes().
console webserver:update_routes().
create directories for statics > mkdir priv && cd priv && mkdir css js img
<!DOCTYPE html> <html> <head> <title>Webserver</title> </head> <body> {% block content %}{% endblock %} </body> </html>
{% extends "layout.dtl" %} {% block content %} <h1>Hello, {{ username | default : "stranger" }}!</h1> {% endblock %}
{% extends "layout.dtl" %} {% block content %} <h1>URL <span style="color:red;">{{ url }}</span> does not exists.</h1> {% endblock %}
ok = erlydtl:compile("tpl/layout.dtl", "layout_tpl", []), ok = erlydtl:compile("tpl/index.dtl", "index_tpl", []), ok = erlydtl:compile("tpl/404.dtl", "404_tpl", []).
c_tpl() -> c_tpl([]). c_tpl(Opts) -> c_tpl(filelib:wildcard("tpl/*.dtl"), Opts). c_tpl([], _Opts) -> ok; c_tpl([File | Files], Opts) -> ok = erlydtl:compile(File, re:replace(filename:basename(File), ".dtl", "_tpl", [global, {return, list}]), Opts), c_tpl(Files, Opts).
%% API -export([ start/0, stop/0, update_routes/0, c_tpl/0, c_tpl/1, c_tpl/2 ]).
webserver:c_tpl().
Erlang console webserver:c_tpl().
{plugins,[rebar_erlydtl_compiler]}. {deps, [ {cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {branch, "master"}}}, {sync, ".*", {git, "git://github.com/rustyio/sync.git", {branch, "master"}}}, {mimetypes, ".*", {git, "git://github.com/spawngrid/mimetypes.git", {branch, "master"}}}, {erlydtl, ".*", {git, "git://github.com/evanmiller/erlydtl.git", {branch, "master"}}} ]}. {erlydtl_opts,[ {compiler_options, [debug_info]}, [ {doc_root, "tpl"}, {out_dir, "ebin"}, {source_ext, ".dtl"}, {module_ext, "_tpl"} ] ]}.
-module(index_handler). -behaviour(cowboy_http_handler). %% Cowboy_http_handler callbacks -export([ init/3, handle/2, terminate/3 ]). init({tcp, http}, Req, _Opts) -> {ok, Req, undefined_state}. handle(Req, State) -> {Username, Req2} = cowboy_req:qs_val(<<"username">>, Req, "stranger"), {ok, HTML} = index_tpl:render([{username, Username}]), {ok, Req3} = cowboy_req:reply(200, [], HTML, Req2), {ok, Req3, State}. terminate(_Reason, _Req, _State) -> ok.
-module(notfound_handler). -behaviour(cowboy_http_handler). %% Cowboy_http_handler callbacks -export([ init/3, handle/2, terminate/3 ]). init({tcp, http}, Req, _Opts) -> {ok, Req, undefined_state}. handle(Req, State) -> {URL, Req2} = cowboy_req:url(Req), {ok, HTML} = '404_tpl':render([{url, URL}]), {ok, Req3} = cowboy_req:reply(404, [], HTML, Req2), {ok, Req3, State}. terminate(_Reason, _Req, _State) -> ok.
Source: https://habr.com/ru/post/173595/
All Articles