mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Add 'Accept-Language' to cowboy_http_req:parse_header/2
This commit is contained in:
parent
3e443f0a6c
commit
6dbe2b2130
2 changed files with 99 additions and 13 deletions
|
@ -17,9 +17,9 @@
|
||||||
|
|
||||||
%% Parsing.
|
%% Parsing.
|
||||||
-export([list/2, nonempty_list/2,
|
-export([list/2, nonempty_list/2,
|
||||||
media_range/2, conneg/2, digits/1,
|
media_range/2, conneg/2, language_range/2,
|
||||||
http_date/1, rfc1123_date/1, rfc850_date/1, asctime_date/1,
|
http_date/1, rfc1123_date/1, rfc850_date/1, asctime_date/1,
|
||||||
token/2, token_ci/2, quoted_string/2]).
|
digits/1, token/2, token_ci/2, quoted_string/2]).
|
||||||
|
|
||||||
%% Interpretation.
|
%% Interpretation.
|
||||||
-export([connection_to_atom/1]).
|
-export([connection_to_atom/1]).
|
||||||
|
@ -176,20 +176,63 @@ conneg(Data, Fun) ->
|
||||||
token_ci(Data,
|
token_ci(Data,
|
||||||
fun (_Rest, <<>>) -> {error, badarg};
|
fun (_Rest, <<>>) -> {error, badarg};
|
||||||
(Rest, Conneg) ->
|
(Rest, Conneg) ->
|
||||||
whitespace(Rest,
|
maybe_qparam(Rest,
|
||||||
fun (<< $;, Rest2/bits >>) ->
|
fun (Rest2, Quality) ->
|
||||||
whitespace(Rest2,
|
Fun(Rest2, {Conneg, Quality})
|
||||||
fun (Rest3) ->
|
|
||||||
qparam(Rest3,
|
|
||||||
fun (Rest4, Quality) ->
|
|
||||||
Fun(Rest4, {Conneg, Quality})
|
|
||||||
end)
|
|
||||||
end);
|
|
||||||
(Rest2) ->
|
|
||||||
Fun(Rest2, {Conneg, 1000})
|
|
||||||
end)
|
end)
|
||||||
end).
|
end).
|
||||||
|
|
||||||
|
%% @doc Parse a language range, followed by an optional quality value.
|
||||||
|
-spec language_range(binary(), fun()) -> any().
|
||||||
|
language_range(<< $*, Rest/bits >>, Fun) ->
|
||||||
|
language_range_ret(Rest, Fun, '*');
|
||||||
|
language_range(Data, Fun) ->
|
||||||
|
language_tag(Data,
|
||||||
|
fun (Rest, LanguageTag) ->
|
||||||
|
language_range_ret(Rest, Fun, LanguageTag)
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec language_range_ret(binary(), fun(), '*' | {binary(), binary()}) -> any().
|
||||||
|
language_range_ret(Data, Fun, LanguageTag) ->
|
||||||
|
maybe_qparam(Data,
|
||||||
|
fun (Rest, Quality) ->
|
||||||
|
Fun(Rest, {LanguageTag, Quality})
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec language_tag(binary(), fun()) -> any().
|
||||||
|
language_tag(Data, Fun) ->
|
||||||
|
alpha(Data,
|
||||||
|
fun (_Rest, Tag) when byte_size(Tag) =:= 0; byte_size(Tag) > 8 ->
|
||||||
|
{error, badarg};
|
||||||
|
(<< $-, Rest/bits >>, Tag) ->
|
||||||
|
language_subtag(Rest, Fun, Tag, []);
|
||||||
|
(Rest, Tag) ->
|
||||||
|
Fun(Rest, {Tag, []})
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec language_subtag(binary(), fun(), binary(), [binary()]) -> any().
|
||||||
|
language_subtag(Data, Fun, Tag, Acc) ->
|
||||||
|
alpha(Data,
|
||||||
|
fun (_Rest, SubTag) when byte_size(SubTag) =:= 0;
|
||||||
|
byte_size(SubTag) > 8 -> {error, badarg};
|
||||||
|
(<< $-, Rest/bits >>, SubTag) ->
|
||||||
|
language_subtag(Rest, Fun, Tag, [SubTag|Acc]);
|
||||||
|
(Rest, SubTag) ->
|
||||||
|
Fun(Rest, {Tag, lists:reverse([SubTag|Acc])})
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec maybe_qparam(binary(), fun()) -> any().
|
||||||
|
maybe_qparam(Data, Fun) ->
|
||||||
|
whitespace(Data,
|
||||||
|
fun (<< $;, Rest/bits >>) ->
|
||||||
|
whitespace(Rest,
|
||||||
|
fun (Rest2) ->
|
||||||
|
qparam(Rest2, Fun)
|
||||||
|
end);
|
||||||
|
(Rest) ->
|
||||||
|
Fun(Rest, 1000)
|
||||||
|
end).
|
||||||
|
|
||||||
%% @doc Parse a quality parameter string (for example q=0.500).
|
%% @doc Parse a quality parameter string (for example q=0.500).
|
||||||
-spec qparam(binary(), fun()) -> any().
|
-spec qparam(binary(), fun()) -> any().
|
||||||
qparam(<< Q, $=, Data/bits >>, Fun) when Q =:= $q; Q =:= $Q ->
|
qparam(<< Q, $=, Data/bits >>, Fun) when Q =:= $q; Q =:= $Q ->
|
||||||
|
@ -458,6 +501,24 @@ digits(<< C, Rest/bits >>, Fun, Acc)
|
||||||
digits(Data, Fun, Acc) ->
|
digits(Data, Fun, Acc) ->
|
||||||
Fun(Data, Acc).
|
Fun(Data, Acc).
|
||||||
|
|
||||||
|
%% @doc Parse a list of case-insensitive alpha characters.
|
||||||
|
%%
|
||||||
|
%% Changes all characters to lowercase.
|
||||||
|
-spec alpha(binary(), fun()) -> any().
|
||||||
|
alpha(Data, Fun) ->
|
||||||
|
alpha(Data, Fun, <<>>).
|
||||||
|
|
||||||
|
-spec alpha(binary(), fun(), binary()) -> any().
|
||||||
|
alpha(<<>>, Fun, Acc) ->
|
||||||
|
Fun(<<>>, Acc);
|
||||||
|
alpha(<< C, Rest/bits >>, Fun, Acc)
|
||||||
|
when C >= $a andalso C =< $z;
|
||||||
|
C >= $A andalso C =< $Z ->
|
||||||
|
C2 = cowboy_bstr:char_to_lower(C),
|
||||||
|
alpha(Rest, Fun, << Acc/binary, C2 >>);
|
||||||
|
alpha(Data, Fun, Acc) ->
|
||||||
|
Fun(Data, Acc).
|
||||||
|
|
||||||
%% @doc Parse a case-insensitive token.
|
%% @doc Parse a case-insensitive token.
|
||||||
%%
|
%%
|
||||||
%% Changes all characters to lowercase.
|
%% Changes all characters to lowercase.
|
||||||
|
@ -559,6 +620,25 @@ nonempty_charset_list_test_() ->
|
||||||
],
|
],
|
||||||
[{V, fun() -> R = nonempty_list(V, fun conneg/2) end} || {V, R} <- Tests].
|
[{V, fun() -> R = nonempty_list(V, fun conneg/2) end} || {V, R} <- Tests].
|
||||||
|
|
||||||
|
nonempty_language_range_list_test_() ->
|
||||||
|
%% {Value, Result}
|
||||||
|
Tests = [
|
||||||
|
{<<"da, en-gb;q=0.8, en;q=0.7">>, [
|
||||||
|
{{<<"da">>, []}, 1000},
|
||||||
|
{{<<"en">>, [<<"gb">>]}, 800},
|
||||||
|
{{<<"en">>, []}, 700}
|
||||||
|
]},
|
||||||
|
{<<"en, en-US, en-cockney, i-cherokee, x-pig-latin">>, [
|
||||||
|
{{<<"en">>, []}, 1000},
|
||||||
|
{{<<"en">>, [<<"us">>]}, 1000},
|
||||||
|
{{<<"en">>, [<<"cockney">>]}, 1000},
|
||||||
|
{{<<"i">>, [<<"cherokee">>]}, 1000},
|
||||||
|
{{<<"x">>, [<<"pig">>, <<"latin">>]}, 1000}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
[{V, fun() -> R = nonempty_list(V, fun language_range/2) end}
|
||||||
|
|| {V, R} <- Tests].
|
||||||
|
|
||||||
nonempty_token_list_test_() ->
|
nonempty_token_list_test_() ->
|
||||||
%% {Value, Result}
|
%% {Value, Result}
|
||||||
Tests = [
|
Tests = [
|
||||||
|
|
|
@ -203,6 +203,7 @@ parse_header(Name, Req=#http_req{p_headers=PHeaders}) ->
|
||||||
parse_header_default('Accept') -> [];
|
parse_header_default('Accept') -> [];
|
||||||
parse_header_default('Accept-Charset') -> [];
|
parse_header_default('Accept-Charset') -> [];
|
||||||
parse_header_default('Accept-Encoding') -> [];
|
parse_header_default('Accept-Encoding') -> [];
|
||||||
|
parse_header_default('Accept-Language') -> [];
|
||||||
parse_header_default('Connection') -> [];
|
parse_header_default('Connection') -> [];
|
||||||
parse_header_default(_Name) -> undefined.
|
parse_header_default(_Name) -> undefined.
|
||||||
|
|
||||||
|
@ -226,6 +227,11 @@ parse_header(Name, Req, Default) when Name =:= 'Accept-Encoding' ->
|
||||||
fun (Value) ->
|
fun (Value) ->
|
||||||
cowboy_http:list(Value, fun cowboy_http:conneg/2)
|
cowboy_http:list(Value, fun cowboy_http:conneg/2)
|
||||||
end);
|
end);
|
||||||
|
parse_header(Name, Req, Default) when Name =:= 'Accept-Language' ->
|
||||||
|
parse_header(Name, Req, Default,
|
||||||
|
fun (Value) ->
|
||||||
|
cowboy_http:nonempty_list(Value, fun cowboy_http:language_range/2)
|
||||||
|
end);
|
||||||
parse_header(Name, Req, Default) when Name =:= 'Connection' ->
|
parse_header(Name, Req, Default) when Name =:= 'Connection' ->
|
||||||
parse_header(Name, Req, Default,
|
parse_header(Name, Req, Default,
|
||||||
fun (Value) ->
|
fun (Value) ->
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue