diff options
author | Loïc Hoguin <[email protected]> | 2013-04-26 15:48:06 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2013-04-26 15:48:06 +0200 |
commit | 9bc276df3bbd540be1594e4919f90d0a38aa09ad (patch) | |
tree | 4ac7649a76c20d90d94fc56627928181fac1fbbc | |
parent | 12bd1afeedab23ef0a4fef302896dca5ee638ac2 (diff) | |
parent | 2f40a69c116c778e4dbc5abeff13c3cbf9758ac8 (diff) | |
download | cowboy-9bc276df3bbd540be1594e4919f90d0a38aa09ad.tar.gz cowboy-9bc276df3bbd540be1594e4919f90d0a38aa09ad.tar.bz2 cowboy-9bc276df3bbd540be1594e4919f90d0a38aa09ad.zip |
Merge branch 'range_header' of git://github.com/Egobrain/cowboy
-rw-r--r-- | src/cowboy_http.erl | 82 | ||||
-rw-r--r-- | src/cowboy_req.erl | 2 |
2 files changed, 84 insertions, 0 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index c4d3d3d..f889b52 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -37,6 +37,7 @@ -export([token_ci/2]). -export([quoted_string/2]). -export([authorization/2]). +-export([range/1]). %% Decoding. -export([te_chunked/2]). @@ -843,6 +844,64 @@ authorization_basic_password(<<>>, Fun, Acc) -> authorization_basic_password(<<C, Rest/binary>>, Fun, Acc) -> authorization_basic_password(Rest, Fun, <<Acc/binary, C>>). +%% @doc Parse range header according rfc 2616. +-spec range(binary()) -> {Unit, [Range]} | {error, badarg} when + Unit :: binary(), + Range :: {non_neg_integer(), non_neg_integer() | infinity} | neg_integer(). +range(Data) -> + cowboy_http:token_ci(Data, fun range/2). + +range(Data, Token) -> + whitespace(Data, + fun(<<"=", Rest/binary>>) -> + case cowboy_http:list(Rest, fun range_beginning/2) of + {error, badarg} -> + {error, badarg}; + Ranges -> + {Token, Ranges} + end; + (_) -> + {error, badarg} + end). + +range_beginning(Data, Fun) -> + range_digits(Data, suffix, + fun(D, RangeBeginning) -> + range_ending(D, Fun, RangeBeginning) + end). + +range_ending(Data, Fun, RangeBeginning) -> + whitespace(Data, + fun(<<"-", R/binary>>) -> + case RangeBeginning of + suffix -> + range_digits(R, fun(D, RangeEnding) -> Fun(D, -RangeEnding) end); + _ -> + range_digits(R, infinity, + fun(D, RangeEnding) -> + Fun(D, {RangeBeginning, RangeEnding}) + end) + end; + (_) -> + {error, badarg} + end). + +-spec range_digits(binary(), fun()) -> any(). +range_digits(Data, Fun) -> + whitespace(Data, + fun(D) -> + digits(D, Fun) + end). + +-spec range_digits(binary(), any(), fun()) -> any(). +range_digits(Data, Default, Fun) -> + whitespace(Data, + fun(<< C, Rest/binary >>) when C >= $0, C =< $9 -> + digits(Rest, Fun, C - $0); + (_) -> + Fun(Data, Default) + end). + %% Decoding. %% @doc Decode a stream of chunks. @@ -1364,4 +1423,27 @@ http_authorization_test_() -> ], [{V, fun() -> R = authorization(V,T) end} || {T, V, R} <- Tests]. +http_range_test_() -> + Tests = [ + {<<"bytes=1-20">>, + {<<"bytes">>, [{1, 20}]}}, + {<<"bytes=-100">>, + {<<"bytes">>, [-100]}}, + {<<"bytes=1-">>, + {<<"bytes">>, [{1, infinity}]}}, + {<<"bytes=1-20,30-40,50-">>, + {<<"bytes">>, [{1, 20}, {30, 40}, {50, infinity}]}}, + {<<"bytes = 1 - 20 , 50 - , - 300 ">>, + {<<"bytes">>, [{1, 20}, {50, infinity}, -300]}}, + {<<"bytes=1-20,-500,30-40">>, + {<<"bytes">>, [{1, 20}, -500, {30, 40}]}}, + {<<"test=1-20,-500,30-40">>, + {<<"test">>, [{1, 20}, -500, {30, 40}]}}, + {<<"bytes=-">>, + {error, badarg}}, + {<<"bytes=-30,-">>, + {error, badarg}} + ], + [fun() -> R = range(V) end ||{V, R} <- Tests]. + -endif. diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 552048a..76c4085 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -441,6 +441,8 @@ parse_header(Name, Req, Default) when Name =:= <<"if-modified-since">>; Name =:= <<"if-unmodified-since">> -> parse_header(Name, Req, Default, fun cowboy_http:http_date/1); +parse_header(Name = <<"range">>, Req, Default) -> + parse_header(Name, Req, Default, fun cowboy_http:range/1); parse_header(Name, Req, Default) when Name =:= <<"sec-websocket-protocol">>; Name =:= <<"x-forwarded-for">> -> |