Kill-Bill

Web Application Server

Installation

Using rebar:

{deps, [
    {kill_bill, ".*", {hg, "https://bitbucket.org/jjmrocha/kill-bill", "1.0.0"}}
]}.

Start Kill-Bill

Kill-Bill depends on cowboy, jsondoc, erlydtl and gibreel, you need to start cowboy and gibreel before kill-bill.

%% Start cowboy
ok = application:start(crypto),
ok = application:start(ranch),
ok = application:start(cowlib),
ok = application:start(cowboy),
%% Start gibreel
ok = application:start(columbo),
ok = application:start(cclock),
ok = application:start(gibreel),
%% Start Kill-Bill
ok = application:start(kill_bill).

Server Management

API

%% Setup a server
kill_bill:config_server(ServerConfig :: Config) -> {ok, ServerName :: atom()} | {error, Reason :: any()} 
    when Config :: ConfigFile :: string()
                     | {server_config, ServerName :: atom(), Config :: list()}.

%% Start server
kill_bill:start_server(ServerName :: atom()) -> ok | {error, Reason :: any()}.

%% Stop server
kill_bill:stop_server(ServerName :: atom()) -> ok | {error, Reason :: any()}.

%% List all servers
kill_bill:get_server_list() -> list().

Server configuration file

{server_config, ServerName, [
    {host, Host}, 
    {protocol, Protocol}, 
    {ssl, SSLConfig},
    {port, Port},
    {acceptor_number, AcceptorNumber},
    {max_connections, MaxConnections}
]}.

Where:

Example: Accept connections on port 8080 for all hosts.

{server_config, my_server, []}.

Web Application Management

API

%% Deploy a WebApp
kill_bill:deploy(ServerName :: atom(), WebAppConfig :: Config) -> ok | {error, Reason :: any()} 
    when Config :: WebAppFile :: string()
                     | {webapp_config, WebAppName :: atom(), Config :: list()}. 

%% Undeploy WebApp
kill_bill:undeploy(WebAppName :: atom()) -> ok | {error, Reason :: any()}.

%% List all WebApps
kill_bill:get_webapp_list() -> WebAppList
    when WebAppList :: [{WebAppName :: atom(), ServerName :: atom()}, ...].

WebApp configuration file

{webapp_config, WebAppName, [
    {context, Context},
    {template, TemplateConfig},
    {resource, ResourceConfig},
    {action, ActionList},
    {static, StaticConfig},
    {session_timeout, SesionTimeout}
]}.

Where:

Example

The following code was removed from the example project, that you will find on the "examples" directory.

{ok, ServerID} = kill_bill:config_server("./priv/default-server.config"),
ok = kill_bill:deploy(ServerID, "./priv/root-webapp.config"),
ok = kill_bill:deploy(ServerID, "./priv/examples-webapp.config"),
ok = kill_bill:start_server(ServerID).

kb_action_handler callback

The actions must implement the kb_action_handler callback behaviour.

handle(Method :: binary(), Path :: list(), Request :: #kb_request{}) 
    -> {html, Value :: iodata(), Request1 :: #kb_request{}} 
     | {json, Value :: any(), Request1 :: #kb_request{}}
     | {dtl, Template :: module(), Args :: list(), Request1 :: #kb_request{}}
     | {redirect, Url :: iolist(), Request1 :: #kb_request{}} 
     | {raw, Status :: integer(), Headers :: list(), Body :: iodata(), Request1 :: #kb_request{}}.

Parameters:

Example

WebApp configuration file:

{webapp_config, examples, [
    {context, "/examples/"},
    {action, [ 
        {"/", examples_action}      
    ]}
]}.

Action module:

-module(examples_action).

-behaviour(kb_action_handler).

-export([handle/3]).

handle(_Method, [], Req) ->
    {html, "<html><body>Kill-Bill examples.</body></html>", Req};

handle(_Method, [<<"obj">>, Id, <<"create">>], Req) ->
    Obj = [{id, Id}, {type, <<"obj">>}],
    {json, Obj, Req};

handle(<<"GET">>, [<<"cities">>], Req) ->
    CitiesList = [<<"Lisbon">>, <<"London">>, <<"Madrid">>],
    Args = [{cities, ValueList}],
    {dtl, cities_dtl, Args, Req};

handle(_Method, [<<"google">>], Req) ->
    {redirect, <<"http://www.google.com">>, Req};

handle(_Method, _Path, Req) ->
    {raw, 404, [], "Not found!", Req}.

kb_action_helper Helper module

The module kb_action_helper provides functions to interact with Kill-Bill.

API

%% Retrive WebApp context
kb_action_helper:get_context(Req :: #kb_request{}) -> binary().

%% Retrive args from request
kb_action_helper:get_args(Req :: #kb_request{}) -> {Args, Req1 :: #kb_request{}}
    when Args :: [{Key :: binary(), Value :: binary()}, ...].

%% Retrive JSON from request body
kb_action_helper:get_json(Req :: #kb_request{}) -> {Doc :: jsondoc:jsondoc(), Req1 :: #kb_request{}}.

%% Retrive data from session
kb_action_helper:get_session(Req :: #kb_request{}) -> {SessionData, Req1 :: #kb_request{}}
    when SessionData :: [{Key :: any(), Value :: any()}, ...].

%% Store data in session
kb_action_helper:set_session(SessionData, Req :: #kb_request{}) -> Req1 :: #kb_request{}
    when SessionData :: [{Key :: any(), Value :: any()}, ...].

%% Invalidate session
kb_action_helper:invalidate_session(Req :: #kb_request{}) -> #kb_request{}.

The module kb_action_helper has many more functions.

Kill-Bill tags

Kill-Bill provides two tags to be use on templates:

TAG context

Without parameters, returns the WebApp's context

<form action="{% context %}action" method="post">
...
</form>

With the "file" parameter, the TAG prefixes the path to the file with the WebApp's context:

<img src="{% context file="/images/kill-bill-logo.png" %}">

TAG message

Retrieves the localized message for "key" from the messages file (defined in the WebApp configuration file):

<h1>{% message key="page_title" %}</h1>

Configuration

To use Kill-Bill's tags, add the following to your project's rebar.config:

{erlydtl_opts, [{custom_tags_modules, [kb_dtl_tag]}]}.