Skip to content

Commit

Permalink
Added RFC6265 compliant variant of setcookie.
Browse files Browse the repository at this point in the history
The new set_cookie/3 function implements more complete RFC2109
cookie formatting than setcookie/6 and is 10x - 15x more efficient
than its old setcookie counterpart because of avoiding the use of
io_lib:format/2.  The setcookie/2 through setcookie/6 are marked
as deprecated.  The function is named set_cookie rather than setcookie
to facilitate the ease of depricating the old implementation.
  • Loading branch information
saleyn committed Oct 6, 2012
1 parent 1e7a122 commit 00c152b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
25 changes: 24 additions & 1 deletion man/yaws_api.5
Expand Up @@ -139,9 +139,32 @@ The equivalent of io_lib:format/2. This function is automatically
\fBhtmlize(Binary | List | Char)\fR
Htmlize an IO list object.

.TP
\fBset_cookie(Name, Value, Options])\fR
Sets a cookie to the browser. Options are:
\fI
.nf

{expires, UtcTime} - Cookie expiration time, where UtcTime is
a tuple returned by calendar:universal_time/0.
{max_age, Age} - Defines the lifetime of the cookie, in seconds,
where age is an integer >= 0.
{path, Path} - Path is a string that specifies the subset of URLs to
which this cookie applies.
{domain, Domain} - Domain is a string that specifies the domain for which
the cookie is valid.
{comment, Comment} - Comment is a string that doccuments the server's
intended use of the cookie.
secure - Directs the user agent to use only secure means to
contact the origin server whenever it sends back this
cookie.
http_only - Restricts cookie access from other non-HTTP APIs.
.fi
\fR

.TP
\fBsetcookie(Name, Value, [Path, [ Expire, [Domain , [Secure]]]])\fR
Sets a cookie to the browser.
Sets a cookie to the browser. This function is deprecated by set_cookie/3.

.TP
\fBfind_cookie_val(Cookie, Header)\fR
Expand Down
2 changes: 2 additions & 0 deletions src/yaws.erl
Expand Up @@ -100,6 +100,8 @@

-export([parse_ipmask/1, match_ipmask/2]).

%% Internal
-export([local_time_as_gmt_string/1, universal_time_as_string/1]).

start() ->
application:start(yaws, permanent).
Expand Down
38 changes: 37 additions & 1 deletion src/yaws_api.erl
Expand Up @@ -22,6 +22,12 @@
parse_multipart/2, parse_multipart/3]).
-export([code_to_phrase/1, ssi/2, redirect/1]).
-export([setcookie/2, setcookie/3, setcookie/4, setcookie/5, setcookie/6]).
-deprecated([{setcookie, 2, eventually},
{setcookie, 3, eventually},
{setcookie, 4, eventually},
{setcookie, 5, eventually},
{setcookie, 6, eventually}]).
-export([set_cookie/3]).
-export([pre_ssi_files/2, pre_ssi_string/1, pre_ssi_string/2,
set_content_type/1,
htmlize/1, htmlize_char/1, f/2, fl/1]).
Expand Down Expand Up @@ -683,7 +689,37 @@ secs() ->
{MS, S, _} = now(),
(MS * 1000000) + S.


cookie_option(secure) ->
"; Secure";
cookie_option(http_only) ->
"; HttpOnly";
cookie_option(I) ->
throw({badarg, I}).
cookie_option(expires, UTC) when is_tuple(UTC) ->
["; Expires=" | yaws:universal_time_as_string(UTC)];
cookie_option(max_age, Age) when is_integer(Age) ->
V = if Age < 0 -> "0"; true -> integer_to_list(Age) end,
["; Max-Age=" | V];
cookie_option(path, Path) when is_list(Path), Path =/= [] ->
["; Path=" | Path];
cookie_option(domain, Domain) when is_list(Domain), Domain =/= [] ->
["; Domain=" | Domain];
cookie_option(comment, Comment) when is_list(Comment), Comment=/= [] ->
["; Comment=" | Comment];
cookie_option(I, _) ->
throw({badarg, I}).

%% @doc Generate a set_cookie header field tuple.
%% This function is more RFC6265 compliant than setcookie/6 and
%% therefore it deprecates setcookie/6 completely.
set_cookie(Key, Value, Options)
when is_list(Key), is_list(Value), is_list(Options) ->
%% RFC6265 (4.1.1): Name=Value options must come first.
{NV,SV} = lists:foldl(fun
({N,V}, {L1, L2}) -> {[cookie_option(N,V) | L1], L2};
(N, {L1, L2}) -> {L1, [cookie_option(N) | L2]}
end, {[], []}, Options),
{header, {set_cookie, [Key, $=, Value, "; Version=1", NV | SV]}}.

setcookie(Name, Value) ->
{header, {set_cookie, f("~s=~s;", [Name, Value])}}.
Expand Down

0 comments on commit 00c152b

Please sign in to comment.