Permalink
Browse files

Add support for custom_auth_mod server option

This option aims to provide the mean to override #headers.authorization
 at a early stage so that a cookie user name can be dumped in the access logs.
  • Loading branch information...
1 parent 54acbb6 commit 840ee7021b1b3fca751661637cad3e3b7bd7f697 @nthauvin committed Feb 21, 2012
Showing with 61 additions and 5 deletions.
  1. +2 −1 include/yaws.hrl
  2. +15 −0 man/yaws.conf.5
  3. +4 −0 src/yaws_config.erl
  4. +12 −3 src/yaws_server.erl
  5. +2 −1 test/eunit/Makefile
  6. +26 −0 test/eunit/yaws_server_test.erl
View
@@ -235,7 +235,8 @@
stats, %% raw traffic statistics
fcgi_app_server, %% FastCGI application server {host,port}
php_handler = {cgi, "/usr/bin/php-cgi"},
- shaper
+ shaper,
+ custom_auth
}).
%% we cannot compare sconfs directly due to the ets
View
@@ -612,6 +612,21 @@ that is not located in your docroot. See the example at the bottom of this man
page for how to use the \fIopaque\fR + \fIvdir\fR elements to instruct the
\fIyaws_vdir\fR module what paths to rewrite.
+.TP
+\fBcustom_auth_mod = Module\fR
+This module is called just after the parsing of the headers and allows
+to modify them, for example to be able to change the authorization
+structure according to a cookie value. This customisation is done
+even earlier than \farg_rewrite_mod\f, enabling the user
+name to be dumped in the access logs.
+
+The module \fIyaws_vdir\fR can be used in case you want to serve static content
+that is not located in your docroot. See the example at the bottom of this man
+page for how to use the \fIopaque\fR + \fIvdir\fR elements to instruct the
+\fIyaws_vdir\fR module what paths to rewrite.
+
+
+
.TP
\fBstart_mod = Module\fR
Defines a user provided callback module.
View
@@ -1252,6 +1252,10 @@ fload(FD, server, GC, C, Cs, Lno, Chars) ->
C2 = C#sconf{shaper = list_to_atom(Module)},
fload(FD, server, GC, C2, Cs, Lno+1, Next);
+ ["custom_auth_mod", '=', Module] ->
+ C2 = C#sconf{custom_auth = list_to_atom(Module)},
+ fload(FD, server, GC, C2, Cs, Lno+1, Next);
+
[H|T] ->
{error, ?F("Unexpected input ~p at line ~w", [[H|T], Lno])};
Err ->
View
@@ -48,6 +48,9 @@
'DELETE'/4,
'PATCH'/4]).
+%% tests
+-export ([custom_auth/2]).
+
-import(lists, [member/2, foreach/2, map/2,
flatten/1, reverse/1]).
@@ -1125,9 +1128,10 @@ aloop(CliSock, {IP,Port}, GS, Num) ->
?Debug("Head = ~p~n", [Head]),
case Head of
{Req0, H0} when Req0#http_request.method /= bad_request ->
- {Req, H} = fix_abs_uri(Req0, H0),
- ?Debug("{Req, H} = ~p~n", [{Req, H}]),
- SC = pick_sconf(GS#gs.gconf, H, GS#gs.group),
+ {Req, H1} = fix_abs_uri(Req0, H0),
+ ?Debug("{Req, H} = ~p~n", [{Req, H1}]),
+ SC = pick_sconf(GS#gs.gconf, H1, GS#gs.group),
+ H = custom_auth(H1, SC),
?Debug("SC: ~s", [?format_record(SC, sconf)]),
?TC([{record, SC, sconf}]),
?Debug("Headers = ~s~n", [?format_record(H, headers)]),
@@ -1315,6 +1319,11 @@ fix_abs_uri(Req, H) ->
_ -> {Req, H}
end.
+custom_auth(H, SC) ->
+ case SC#sconf.custom_auth of
+ undefined -> H;
+ Mod -> Mod:custom_auth(H)
+ end.
%% Case-insensitive compare servername and ignore any optional :Port
%% postfix. This is performance-sensitive code, so if you change it,
View
@@ -1,14 +1,15 @@
include ../support/include.mk
all: multipart_post_parsing.beam \
+ yaws_server_test.beam \
yaws_session_server_test.beam \
ehtml_test.beam \
embedded_yaws_id_dir.beam
test: all
$(ERL) -pa ../src $(YTOP)/ebin -noshell \
-s test run multipart_post_parsing yaws_session_server_test \
- ehtml_test embedded_yaws_id_dir
+ ehtml_test embedded_yaws_id_dir yaws_server_test
clean: tclean
@@ -0,0 +1,26 @@
+-module (yaws_server_test).
+
+%% test callback
+-export ([custom_auth/1]).
+
+-include_lib ("eunit/include/eunit.hrl").
+-include ("../../include/yaws.hrl").
+-include ("../../include/yaws_api.hrl").
+
+custom_auth_test () ->
+ Headers = #headers{cookie = ["foo=bar; login=ABC"]},
+ SC = #sconf{custom_auth = ?MODULE},
+ Result = yaws_server:custom_auth(Headers, SC),
+ Expected = Headers#headers{authorization = {"abc", undefined, undefined}},
+ ?assertEqual(Expected, Result).
+
+custom_auth (#headers{cookie = Cookie} = Headers) ->
+ Value = yaws_api:find_cookie_val("login", Cookie),
+ Auth = {string:to_lower(Value), undefined, undefined},
+ Headers#headers{authorization = Auth}.
+
+custom_auth_not_defined_test () ->
+ Headers = #headers{cookie = ["foo=bar; login=ABC"]},
+ SC = #sconf{},
+ Result = yaws_server:custom_auth(Headers, SC),
+ ?assertEqual(Headers, Result).

0 comments on commit 840ee70

Please sign in to comment.