Permalink
Browse files

Added support for excluding dirs from an appmod. This is useful for /…

… appmods
  • Loading branch information...
1 parent a7ee64c commit b7656dee696241308472756920e1ac5a854c36f4 @klacke committed Nov 29, 2009
Showing with 88 additions and 13 deletions.
  1. +7 −7 include/yaws.hrl
  2. +11 −0 man/yaws.conf.5
  3. +14 −0 src/yaws_config.erl
  4. +21 −4 src/yaws_server.erl
  5. +24 −1 www/appmods.yaws
  6. +11 −1 www/embed.yaws
View
@@ -186,7 +186,13 @@
ssl, %% undefined | #ssl{}
authdirs = [],
partial_post_size = nolimit,
- appmods = [], %% list of modules for this app
+ appmods = [],
+ %% An item in the appmods list can be either of the
+ %% following, this is all due to backwards compat issues.
+ %% 1. an atom - this is the equivalent to {atom, atom}
+ %% 2 . A two tuple {Path, Mod}
+ %% 3 A three tuple {Path, Mod, [ExcludeDir ....]}
+
errormod_401 = yaws_outmod, %% the default 401 error module
errormod_404 = yaws_outmod, %% the default 404 error module
errormod_crash = yaws_outmod, %% use the same module for crashes
@@ -287,12 +293,6 @@
-
--record(appmodspec, {
- type, %% atom, pair or absolute
- data}).
-
-
%% as read by application:get_env()
-record(env, {debug,
trace,
View
@@ -353,6 +353,17 @@ instead of searching the filesystems below the point foo.
The Arg argument will have the missing path part supplied in its
appmoddata field.
+It is also possible to exclude certain directories from appmod
+processing. This is particulaly interesting for '/' appmods.
+Here is an example:
+
+ appmods = </, myapp exclude_paths icons js top/static>
+
+The above configuration will invoke the 'myapp' erlang module on everything
+except any file found in directories, 'icons', 'js' and 'top/static'
+relative to the docroot.
+
+
.TP
\fBerrormod_404 = Module\fR
View
@@ -1451,6 +1451,20 @@ parse_appmods(['<', PathElem, ',' , AppMod, '>' | Tail], Ack) ->
S = {PathElem , list_to_atom(AppMod)},
parse_appmods(Tail, [S |Ack]);
+parse_appmods(['<', PathElem, ',' , AppMod, "exclude_paths" |Tail], Ack)->
+ Paths = lists:takewhile(fun(X) -> X /= '>' end,
+ Tail),
+ Tail2 = lists:dropwhile(fun(X) -> X /= '>' end,
+ Tail),
+ Tail3 = tl(Tail2),
+
+ S = {PathElem , list_to_atom(AppMod), lists:map(
+ fun(Str) ->
+ string:tokens(Str, "/")
+ end, Paths)},
+ parse_appmods(Tail3, [S |Ack]);
+
+
parse_appmods([AppMod | Tail], Ack) ->
%% just some simpleminded test to catch syntax errors in the config
case AppMod of
View
@@ -3790,12 +3790,18 @@ active_appmod(AppMods, RequestSegs) ->
Matched =
lists:foldl(
fun(Pair,Acc) ->
- {Mount, Mod} = Pair,
+ {Mount, Mod, Excludes} = case Pair of
+ {X, Y} -> {X, Y, []};
+ {X,Y,Z} -> {X,Y,Z}
+ end,
{ReqSegs, {LongestSoFar, _}} = Acc,
MountSegs = string:tokens(Mount,"/"),
- case lists:prefix(MountSegs,ReqSegs) of
- true ->
+ case {is_excluded(ReqSegs, Excludes) ,
+ lists:prefix(MountSegs,ReqSegs)} of
+ {true, _} ->
+ Acc;
+ {false, true} ->
case LongestSoFar of
[$/|_] ->
%%simple comparison of string length
@@ -3813,7 +3819,7 @@ active_appmod(AppMods, RequestSegs) ->
{ReqSegs, {Mount, Mod}}
end;
- false ->
+ {false, false} ->
case LongestSoFar of
[$/|_] ->
%%There is already a match for an
@@ -3848,6 +3854,17 @@ active_appmod(AppMods, RequestSegs) ->
end
.
+is_excluded(_, []) ->
+ false;
+is_excluded(RequestSegs, [ExcludeSegs|T]) ->
+ case lists:prefix(ExcludeSegs, RequestSegs) of
+ true ->
+ true;
+ false ->
+ is_excluded(RequestSegs, T)
+ end.
+
+
%%split a list of segments into 2 lists either side of element matching Seg.
%%(no elements contain slashes)
split_at_segment(_, [], _Acc) ->
View
@@ -67,7 +67,30 @@ A#arg.querydata = \"a=b\""),
{br,[],[]},
{p, [],
- "Appmods would typically be used by webapplications that want to provide the illusion of proper paths to the browser. "}
+ "Appmods would typically be used by webapplications that want to provide the illusion of proper paths to the browser. "},
+
+ {p, [], "A special case of an appmod that is particularly interesting is the '/' appmod. This used when we want application code to handle all requests. This is common with web frameworks such as Nitrogen."},
+
+ box("
+<server tita>
+ port = 8001
+ listen = 0.0.0.0
+ docroot = /home/klacke/yaws/yaws/scripts/../www
+ appmods = </, myappmod>
+</server>"),
+
+ {p, [], "The above configuration snippet is an example of a slash appmod. One complication with the slash appmod is that usually we have a set of folders containing static data, images and java script, and we want yaws to just deliver those files without intervention from the slash appmod. This can be achieved by excluding a set of directories."},
+
+
+ box("
+<server tita>
+ port = 8001
+ listen = 0.0.0.0
+ docroot = /home/klacke/yaws/yaws/scripts/../www
+ appmods = </, myappmod exclude_paths icons js top/static>
+</server>"),
+
+ {p, [], "The above configuration will invoke the 'myappmod' erlang module on everything except any file found in directories, 'icons', 'js' and 'top/static' relative to the docroot"}
]
View
@@ -122,7 +122,7 @@ out(A) ->
ssl,
authdirs = [],
partial_post_size = nolimit,
- appmods = [], %% list of modules for this app
+ appmods = [], %% list of appmod specs
errormod_404 = yaws_404, %% the default 404 error module
errormod_crash = yaws_404, %% use the same module for crashes
arg_rewrite_mod = yaws,
@@ -265,6 +265,16 @@ functions are disabled when we use yaws as an embedded web server. I.e
yaws --ls, yaws --stop etc. This under the assumption that you already have support for this type of functionality in your application.
</p>
+<p>Finally, an interesting appmod definition that may apply to many embedded yaws installations is that / appmod with a set of exclude dirs. Here is an example:
+</p>
+<div class="box">
+<verbatim>
+SC#sconf{.....
+ appmods = {"/", myapp, [["js"], ["top", "static"], ["icons"]]},
+ ....
+</verbatim>
+</div>
+
</div>

0 comments on commit b7656de

Please sign in to comment.