Chicago Boss home

The Chicago Boss API is mostly stable, but still might change before 1.0.

Jump to:   Routes   Authorization   Return values   Post-processing   SimpleBridge request object

Chicago Boss associates each URL with a function of a controller. The URL /foo/bar will call the function foo_controller:bar. Each controller module should go into your project's src/controller/ directory and the file name should start with the application name and end with "_controller.erl", e.g. "appname_my_controller.erl". Helper functions should go into your project's src/lib/ directory. Controllers can take one parameter or two parameters: the SimpleBridge request object, and an optional session ID (if sessions are enabled). Declare it like:

-module(appname_my_controller, [Req]).

Or:

-module(appname_my_controller, [Req, SessionID]).

Each exported controller function takes two or three arguments:

Example function clauses:

% GET /blog/view
view('GET', []) ->
    ...
% GET /blog/view/1234
view('GET', [Id]) ->
    ...
% GET /blog/view/tag/funny
view('GET', ["tag", Tag]) ->
    ...
% GET /blog/view/tag/funny/author/saint-paul
view('GET', ["tag", Tag, "author", AuthorName]) ->
    ...
% GET /blog/view/2009/08
view('GET', [Year, Month]) ->
    ...

These function clauses act as templates for constructing URLs in the view; for each CamelCase variable, simply use the lower-cased underscored equivalent as the parameter name. To continue the example above, you can construct URLs to match the above controllers with the following view tags:

{% url action="view" %}
{% url action="view" id="1234" %}
{% url action="view" tag="funny" %}
{% url action="view" tag="funny" author_name="saint-paul" %}
{% url action="view" year="2009" month="08" %}

Template variables can of course be used in place of string literals.

Routes

Most routing takes place in the controller pattern-matching code. You can define additional routes in priv/my_application.routes. The file contains a list of erlang terms, one per line finished with a dot. Each term is a tuple with a URL or an HTTP status code as the first term, and a {Controller::string(), Action::string()} or {Controller::string(), Action::string(), Parameters::proplist()} tuple as the second term.

A few examples:

{"/", [{controller, "main"}, {action, "welcome"}]}.
{"/signup", [{application, login_app}, {controller, "account"}, {"create"}]}.
{404, [{controller, "main"}, {action, "not_found"}]}.

Most routes directly render the specified action; however, routing across applications (as in the second example) results in a 302 redirect.

To define a default action for a controller, simply add a default_action attribute to the controller like so:

-default_action(index).

Authorization

If an action takes three arguments, then the function before_/1 in your controller will be passed the action name as a string and should return one of:

{ok, ExtraInfo}

ExtraInfo will be passed as the third argument to the action, and as a variable called "before_" to the templates.

{redirect, Location}

Location = string() | [{Key::atom(), Value::atom()}]

Do not execute the action. Instead, perform a 302 redirect to Location, which can be a string or a proplist that will be converted to a URL using the routes system.

Probably most common before_ looks like:

before_(_) ->
    my_user_lib:require_login(Req).

Which might return a tuple of user credential or else redirect to a login page. This way, if you want to require a login to a set of actions, just give those actions a User argument, and the actions will be login protected and have access to the User variable.


Return values

Whether or not it takes a third argument, a controller action should return with one of the following:

ok

The template will be rendered without any variables.

{ok, Variables::proplist()}

Variables will be passed into the associated Django template.

{ok, Variables::proplist(), Headers::proplist()}

Variables will be passed into the associated Django template, and Headers are HTTP headers you want to set (e.g., Content-Type).

{redirect, Location}

Location = string() | [{action, Value::string()}, ...]

Perform a 302 HTTP redirect to Location, which may be a URL string or a proplist of parameters that will be converted to a URL using the routes system.

{redirect, Location, Headers::proplist()}

Perform a 302 HTTP redirect to Location and set additional HTTP Headers.

{action_other, OtherLocation}

OtherLocation = [{action, Value::string()}, ...]

Execute the controller action specified by OtherLocation, but without performing an HTTP redirect.

{render_other, OtherLocation}

OtherLocation = [{action, Value::string()}, ...]

Render the view from OtherLocation, but don't actually execute the associated controller action.

{render_other, OtherLocation, Variables}

Render the view from OtherLocation using Variables, but don't actually execute the associated controller action.

{output, Output::iolist()}

Skip views altogether and return Output to the client.

{output, Output::iolist(), Headers::proplist()}

Skip views altogether and return Output to the client while setting additional HTTP Headers.

{json, Data::proplist()}

Return Data as a JSON object to the client. Performs appropriate serialization if the values in Data contain a BossRecord or a list of BossRecords.

{json, Data::proplist(), Headers::proplist()}

Return Data to the client as a JSON object while setting additional HTTP Headers.

{jsonp, Callback::string(), Data::proplist()}

Returns Data as a JSONP method call to the client. Performs appropriate serialization if the values in Data contain a BossRecord or a list of BossRecords.

{jsonp, Callback::string(), Data::proplist(), Headers::proplist()}

Return Data to the client as a JSONP method call (as above) while setting additional HTTP Headers.

not_found

Invoke the 404 File Not Found handler.


Post-processing

If it exists, a function called after_ in your controller will be passed the result that is about to be returned to the client. The 'after_' function takes two or three arguments:

  1. The action name, as a string
  2. The HTTP result tuple
  3. The result of the before_ function, provided one exists

The after_ function should return a (possibly) modified HTTP result tuple. Result tuples may be one of:

{redirect, Location::string(), Headers::proplist()}

Performs a 302 HTTP redirect to Location and sets additional HTTP Headers.

{ok, Payload::iolist(), Headers::proplist()}

Returns a 200 OK response to the client with Payload as the HTTP body, and sets additional HTTP Headers.


SimpleBridge

Controller functions are passed a SimpleBridge request object (slightly modified for Boss's purposes). Useful functions in the request object include:

request_method() -> atom()

Get the request method, e.g. GET, POST, etc.

query_param( Key::string() ) -> string() | undefined

Get the value of a given query string parameter (e.g. "?id=1234")

post_param( Key::string() ) -> string() | undefined

Get the value of a given POST parameter

deep_post_param( [ Path::string() ] ) -> DeepParam | undefined

Get the value of a given "deep" POST parameter. This function parses parameters that have numerical or labeled indices, such as "widget[4][name]", and returns either a value or a set of nested lists (for numerical indices) and proplists (for string indices).

header( Header::string() | atom() ) -> string() | undefined

Get the value of a given HTTP request header. Valid values are strings or one of these atoms:

cookie( Key::string() ) -> string() | undefined

Get the value of a given cookie.