Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 53 additions & 41 deletions src/cowboy_bridge_modules/cowboy_simple_bridge_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
start_link/0,
init/1,
get_dispatch_info/2
]).
]).

%% ===================================================================
%% API functions
Expand All @@ -24,54 +24,69 @@ init([]) ->
application:ensure_all_started(cowboy),
{Address, Port} = simple_bridge_util:get_address_and_port(cowboy),
IP = simple_bridge_util:parse_ip(Address),

io:format("Starting Cowboy Server on ~p:~p~n",
[IP, Port]),

[IP, Port]),
Dispatch = generate_dispatch(),
io:format("Using Cowboy Dispatch Table:~n ~p~n",[Dispatch]),

Opts = #{env => #{dispatch => Dispatch},
max_keepalive => 100},

max_keepalive => 100},
%% TODO: This should be cowboy:start_tls ir using TLS.
cowboy:start_clear(http, [{ip, IP}, {port, Port}], Opts),

{ok, { {one_for_one, 5, 10}, []}}.


%% @doc Generates the dispatch based on the desired environment
%% 1) First it checks if there's a cowboy_dispatch config, if there is, it uses
%% 1) First get dispatch strategy, that can be override or merge
%% 2) Then it checks if there's a cowboy_dispatch config, if there is, it uses
%% that.
%% 2) Then it checks for cowboy_dispatch_fun, which is a tuple
%% 3) Then it checks for cowboy_dispatch_fun, which is a tuple
%% {Module,Function} and uses the result of calling Module:Function()
%% 3) Finally, if all else fails, it uses the provided document_root and
%% 4) Finally, if all else fails, it uses the provided document_root and
%% static_paths config values standard to simple_bridge to generate a
%% cowboy-specific dispatch table.
generate_dispatch() ->
case application:get_env(simple_bridge, cowboy_dispatch) of
{ok, Dispatch} -> Dispatch;
generate_dispatch() ->
DispatchStrategy = case application:get_env(simple_bridge, dispatch_strategy) of
{ok, override} -> override;
{ok, merge} -> merge;
_ -> override
end,
Dispatches = case application:get_env(simple_bridge, cowboy_dispatch) of
{ok, CustomDispatches} ->
if
DispatchStrategy =:= override -> CustomDispatches;
true -> make_default_dispatch(CustomDispatches)
end;
undefined ->
case application:get_env(simple_bridge, cowboy_dispatch_fun) of
{ok, {M,F}} ->
M:F();
CustomDispatches = M:F(),
if
DispatchStrategy =:= override -> CustomDispatches;
true -> make_default_dispatch(CustomDispatches)
end;
undefined ->
build_dispatch()
make_default_dispatch([])
end
end.
end,
build_dispatch(Dispatches).


%% @doc Gets the environment variables document_root and static_paths, and
%% generates dispatches from them
build_dispatch() ->
make_default_dispatch(CustomRoutes) ->
{DocRoot, StaticPaths} = simple_bridge_util:get_docroot_and_static_paths(cowboy),
io:format("Static Paths: ~p~nDocument Root for Static: ~s~n",
[StaticPaths, DocRoot]),
build_dispatch(DocRoot, StaticPaths).

%% @doc Generate the dispatch tables
build_dispatch(DocRoot,StaticPaths) ->
io:format("Static Paths: ~p~nDocument Root for Static: ~s~nCustom Routes: ~p~n",
[StaticPaths, DocRoot, CustomRoutes]),
{StaticDispatches,HandlerModule,HandlerOpts} = get_dispatch_info(DocRoot,StaticPaths),
StaticDispatches ++ CustomRoutes ++ [{'_', HandlerModule , HandlerOpts}].

%% @doc Generate the dispatch items
build_dispatch(Dispatches) ->
%% Start Cowboy...
%% NOTE: According to Loic, there's no way to pass the buck back to cowboy
%% to handle static dispatch files so we want to make sure that any large
Expand All @@ -81,33 +96,30 @@ build_dispatch(DocRoot,StaticPaths) ->
%%
%% Simple Bridge will do its best to efficiently handle static files, if
%% necessary but it's recommended to just make sure you properly use the
%% static_paths, or rewrite cowboy's dispatch table
%% static_paths, or rewrite cowboy's dispatch table
BaseDispatch=[
%% Nitrogen will handle everything that's not handled in the StaticDispatches
{'_', StaticDispatches ++ [{'_', HandlerModule , HandlerOpts}]}
],
cowboy_router:compile(BaseDispatch).
%% Nitrogen will handle everything that's not handled in the StaticDispatches
{'_', Dispatches}
],
cowboy_router:compile(BaseDispatch).

%% @doc Return base, Nitrogen-specific dispatch information (potentially
%% reusable by third-parties
get_dispatch_info(DocRoot,StaticPaths) ->
StaticDispatches = lists:map(fun(Dir) ->
Path = reformat_path(Dir),
{StaticType, StaticFileDir} = localized_dir_file(DocRoot, Dir),
Opts = [{mimetypes, cow_mimetypes, all}],
%% This will end up being something like:
%% { [<<"js">>,'...'], cowboy_static, {dir, "./priv/static/js", Opts}}
{Path, cowboy_static, {StaticType, StaticFileDir, Opts}}
end,StaticPaths),

Path = reformat_path(Dir),
{StaticType, StaticFileDir} = localized_dir_file(DocRoot, Dir),
Opts = [{mimetypes, cow_mimetypes, all}],
%% This will end up being something like:
%% { [<<"js">>,'...'], cowboy_static, {dir, "./priv/static/js", Opts}}
{Path, cowboy_static, {StaticType, StaticFileDir, Opts}}
end,StaticPaths),
%% HandlerModule will end up calling HandlerModule:handle(Req,HandlerOpts)
HandlerModule = simple_bridge_util:get_anchor_module(cowboy),
HandlerOpts = [],

HandlerOpts = [],
{StaticDispatches,HandlerModule,HandlerOpts}.



localized_dir_file(DocRoot,Path) ->
NewPath = case hd(Path) of
$/ -> DocRoot ++ Path;
Expand Down
73 changes: 43 additions & 30 deletions src/webmachine_bridge_modules/webmachine_simple_bridge_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
-export([
start_link/0,
init/1
]).
]).

%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
Expand All @@ -25,54 +25,67 @@ init([]) ->
application:start(inets),
application:start(crypto),
application:load(webmachine),

{Address, Port} = simple_bridge_util:get_address_and_port(webmachine),
Dispatch = generate_dispatch(),

io:format("Starting Webmachine Server on ~p:~p~n", [Address, Port]),

Options = [
{ip, Address},
{port, Port},
{dispatch, Dispatch}
],
{ip, Address},
{port, Port},
{dispatch, Dispatch}
],
Web = {webmachine_mochiweb,
{webmachine_mochiweb, start, [Options]},
permanent, 5000, worker, [mochiweb_socket_server]},
Processes = [Web],
{ok, _} = application:ensure_all_started(webmachine),
{ok, { {one_for_one, 5, 10}, Processes} }.

generate_dispatch() ->
case application:get_env(simple_bridge, webmachine_dispatch) of
{ok, Dispatch} -> Dispatch;
generate_dispatch() ->
DispatchStrategy = case application:get_env(simple_bridge, dispatch_strategy) of
{ok, override} -> override;
{ok, merge} -> merge;
_ -> override
end,
Dispatches = case application:get_env(simple_bridge, webmachine_dispatch) of
{ok, CustomDispatches} ->
if
DispatchStrategy =:= override -> CustomDispatches;
true -> make_default_dispatch(CustomDispatches)
end;
undefined ->
case application:get_env(simple_bridge, webmachine_dispatch_fun) of
{ok, {M,F}} ->
M:F();
CustomDispatches = M:F(),
if
DispatchStrategy =:= override -> CustomDispatches;
true -> make_default_dispatch(CustomDispatches)
end;
undefined ->
build_dispatch()
make_default_dispatch([])
end
end.
end,
build_dispatch(Dispatches).

build_dispatch() ->
make_default_dispatch(CustomRoutes) ->
{DocRoot, StaticPaths} = simple_bridge_util:get_docroot_and_static_paths(webmachine),
io:format("Static Paths: ~p~nDocument Root for Static: ~s~n",
[StaticPaths, DocRoot]),
build_dispatch(DocRoot, StaticPaths).


build_dispatch(DocRoot, StaticPaths) ->
Handler = simple_bridge_util:get_env(handler),
io:format("Static Paths: ~p~nDocument Root for Static: ~s~nCustom Routes: ~p~n",
[StaticPaths, DocRoot, CustomRoutes]),
%% Static content handlers can be defined manually like so:
%% {["js", '*'], webmachine_simple_bridge_static, [{root, "./site/static/js"}]},
%% {["css", '*'], webmachine_simple_bridge_static, [{root, "./site/static/css"}]},
%% {["images", '*'], webmachine_simple_bridge_static, [{root, "./site/static/images"}]},
%%
%% But instead of doing it manually, we'll load it from the configuration
StaticDispatches = [make_static_dispatch(DocRoot, StaticPath) || StaticPath <- StaticPaths],
StaticDispatches ++ [
%% Static content handlers can be defined manually like so:
%% {["js", '*'], webmachine_simple_bridge_static, [{root, "./site/static/js"}]},
%% {["css", '*'], webmachine_simple_bridge_static, [{root, "./site/static/css"}]},
%% {["images", '*'], webmachine_simple_bridge_static, [{root, "./site/static/images"}]},
%%
%% But instead of doing it manually, we'll load it from the configuration
StaticDispatches ++ CustomRoutes.


build_dispatch(Dispatches) ->
Handler = simple_bridge_util:get_env(handler),
Dispatches ++ [
%% Add routes to your modules here. The last entry makes the
%% system use simple_bridge's handler, which is a generic handler for
%% all non-static requests, and uses the `handler` configuration
Expand All @@ -85,7 +98,7 @@ build_dispatch(DocRoot, StaticPaths) ->
%% {["path","to","module2",'*'], HandlerModule2, InitialState2}
%% {["path","to","module3",'*'], HandlerModule3, InitialState3}
{['*'], simple_bridge_util:get_anchor_module(webmachine), Handler}
].
].

join_path(Root,Path) when is_binary(Root) orelse is_binary(Path) ->
join_path(wf:to_list(Root),wf:to_list(Path));
Expand Down