Current section

Files

Jump to
nitrogen_core src handlers route named_route_handler.erl
Raw

src/handlers/route/named_route_handler.erl

% vim: sw=4 ts=4 et ft=erlang
% Nitrogen Web Framework for Erlang
% Copyright (c) 2008-2010 Rusty Klophaus
% See MIT-LICENSE for licensing information.
-module (named_route_handler).
-behaviour (route_handler).
-include("wf.hrl").
-export ([
init/2,
finish/2
]).
%% @doc
%% The named route handler allows you to specify strongly
%% named routes that are then dispatched to modules. Routes
%% are of the form {Prefix, Module} where Prefix is a string
%% and Module is an atom name of a module, or 'static_file' if
%% this should be treated as a static file or directory.
%%
%% Here is a an example setting up some routes, taken from
%% the SlideBlast.com configuration. The root
%% path would go to web_index, any requests for "/view/..."
%% go to web_view, any requests for "/nitrogen" are treated
%% as a static file, etc.
%%
%% wf_handler:set_handler(named_route_handler, [
%% % Modules...
%% {"/", web_index},
%% {"/view", web_view},
%% {"/img", web_img},
%%
%% % Static directories...
%% {"/nitrogen", static_file},
%% {"/js", static_file},
%% {"/images", static_file},
%% {"/css", static_file}
%% ])
init(undefined, State) -> init([], State);
init(Routes, State) ->
% Get the path...
Bridge = wf_context:bridge(),
Path = sbw:path(Bridge),
% Match to the longest possible route.
{Module, PathInfo} = route(Path, Routes),
{Module1, PathInfo1} = check_for_404(Module, PathInfo, Path),
wf_context:page_module(Module1),
wf_context:path_info(PathInfo1),
{ok, State}.
finish(_Config, State) ->
{ok, State}.
%%% PRIVATE FUNCTIONS %%%
% Look through all routes for a route that matches
% the specified path. If none are found, then
% this is a static file. If more than one route are
% found, takes the longest.
route(Path, Routes) ->
% Returns {SizeOfMatch, Prefix, Module}
F = fun(Prefix, Module) ->
case string:str(Path, Prefix) of
1 -> {length(Prefix), Prefix, Module};
_ -> not_found
end
end,
Matches = [F(Prefix, Module) || {Prefix, Module} <- Routes],
Matches1 = lists:reverse(lists:sort([X || X <- Matches, X /= not_found])),
case Matches1 of
[] ->
{static_file, Path};
[{_, _, static_file}|_] ->
{static_file, Path};
[{_, Prefix, Module}|_] ->
{Module, string:substr(Path, length(Prefix) + 1)}
end.
check_for_404(static_file, _PathInfo, Path) ->
{static_file, Path};
check_for_404(Module, PathInfo, Path) ->
% Make sure the requested module is loaded. If it
% is not, then try to load the web_404 page. If that
% is not available, then default to the 'file_not_found_page' module.
case wf_utils:ensure_loaded(Module) of
{module, Module} -> {Module, PathInfo};
_ ->
case wf_utils:ensure_loaded(web_404) of
{module, web_404} -> {web_404, Path};
_ -> {file_not_found_page, Path}
end
end.