Skip to content

Instantly share code, notes, and snippets.

@SteveSongMIT
Created March 20, 2012 22:50
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save SteveSongMIT/2142154 to your computer and use it in GitHub Desktop.
Save SteveSongMIT/2142154 to your computer and use it in GitHub Desktop.
Simple Cowboy web server + ErlyDTL
<html>
<body>
GET squawk:<br />
{{ squawk_get }}<br /><br />
POST squawk:<br />
{{ squawk_post }}<br /><br />
<form method="POST">
post_input: <input type="text" name="post_input" /><br />
post_input: <input type="text" name="post_input" /><br />
<input type="submit" value="POST it!" /><br />
post_input2:<input type="text" name="post_input2" /><br />
</form>
</body>
</html>
<html><body>Your favorite Little Pony is {{ pony_name }}.</body></html>
%%-*- mode: erlang -*-
{sub_dirs, [
"rel"
]}.
{erl_opts, [debug_info]}. %, fail_on_warning]}.
{require_otp_vsn, "R15"}.
{deps_dir, ["deps"]}.
{deps,
[
{cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {branch, "master"}}},
{erlydtl, ".*", {git, "https://github.com/evanmiller/erlydtl.git", "HEAD"}}
]
}.
rm -R rel/simple_server
./rebar compile generate
sudo erl -sname simple_server -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s simple_server
-module(simple_server_http).
-behaviour(gen_server).
-define(SERVER, ?MODULE).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-record(state, {}).
%% ------------------------------------------------------------------
%% API Function Definitions
%% ------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%% ------------------------------------------------------------------
%% gen_server Function Definitions
%% ------------------------------------------------------------------
dispatch_rules() ->
%% {Host, list({Path, Handler, Opts})}
[{'_', [
{[], simple_server_http_static, [<<"html">>,<<"index.html">>]}
, {[<<"pony">>], simple_server_http_pony, []}
, {'_', simple_server_http_catchall, []}
]}].
confval(Key, Default) ->
case application:get_env(Key) of
undefined -> Default;
Val -> Val
end.
init([]) ->
Port = confval(port, 80),
Ip = confval(ip, "127.0.0.1"),
NumAcceptors = confval(num_acceptors, 16),
IpStr = case is_list(Ip) of true -> Ip; false -> inet_parse:ntoa(Ip) end,
error_logger:info_msg("simple_server listening on http://~s:~B/~n", [IpStr,Port]),
%%
%% Name, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
cowboy:start_listener(http, NumAcceptors,
cowboy_tcp_transport, [{port, Port}],
cowboy_http_protocol, [{dispatch, dispatch_rules()}]
),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
{noreply, ok, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%% ------------------------------------------------------------------
%% Internal Function Definitions
%% ------------------------------------------------------------------
%%
%% show details on a specific process
%%
-module(simple_server_http_captainflint).
-behaviour(cowboy_http_handler).
-export([init/3, handle/2, terminate/2]).
init({tcp, http}, Req, _Opts) ->
{ok, Req, undefined_state}.
handle(Req, State) ->
{GetVal, _} = cowboy_http_req:qs_val(<<"get_input">>, Req),
PostValArr = get_post_value(<<"post_input">>, Req),
PostVal = case PostValArr of
undefined -> undefined;
_ -> string:join([binary_to_list(X) || X <- PostValArr], ",")
end,
{ok, Body} = captainflint_dtl:render([{squawk_get, GetVal}, {squawk_post, PostVal}]),
Headers = [{<<"Content-Type">>, <<"text/html">>}],
{ok, Req2} = cowboy_http_req:reply(200, Headers, Body, Req),
{ok, Req2, State}.
get_post_values(Req) ->
{Method, _} = cowboy_http_req:method(Req),
get_post_values(Method, Req).
get_post_values('POST', Req) ->
{Vals, _} = cowboy_http_req:body_qs(Req),
Vals;
get_post_values(_, _) ->
undefined.
get_post_value(Name, Req) ->
PostVals = get_post_values(Req),
extract_post_value(Name, PostVals).
extract_post_value(_, undefined) ->
undefined;
extract_post_value(Name, PostVals) ->
Matches = [X || X <- PostVals, Name =:= element(1,X)],
process_post_value(Matches).
process_post_value([]) ->
undefined;
process_post_value(Vals) ->
{_, Result} = lists:unzip(Vals),
Result.
terminate(_Req, _State) ->
ok.
%%
%% show details on a specific process
%%
-module(simple_server_http_pony).
-behaviour(cowboy_http_handler).
-export([init/3, handle/2, terminate/2]).
init({tcp, http}, Req, _Opts) ->
{ok, Req, undefined_state}.
handle(Req, State) ->
{ok, Body} = mylittlepony_dtl:render([{pony_name, "Dazzleglow"}]),
Headers = [{<<"Content-Type">>, <<"text/html">>}],
{ok, Req2} = cowboy_http_req:reply(200, Headers, Body, Req),
{ok, Req2, State}.
terminate(_Req, _State) ->
ok.
@agadelshin
Copy link

application:get_env/1 will return {ok, Val} | undefined, but you forgot about tuple

@calebds
Copy link

calebds commented May 6, 2014

how are the templates compiled?

@stephanelpaul
Copy link

@Paislee {ok, Body} = captainflint_dtl:render([{squawk_get, GetVal}, {squawk_post, PostVal}]),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment