Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add mochiweb_request:accepted_content_types/1 #49

Merged
merged 2 commits into from

2 participants

@fdmanana

%% @spec accepted_content_types([string() | binary()]) -> [string()] | bad_accept_header
%%
%% @doc Filters which of the given media types this request accepts. This filtering
%% is performed by analyzing the "Accept" header. The returned list is sorted
%% according to the preferences specified in the "Accept" header (higher Q values
%% first). If two or more types have the same preference (Q value), they're order
%% in the returned list is the same as they're order in the input list.
%%
%% Examples
%%
%% 1) For a missing "Accept" header:
%% accepted_content_types(["text/html", "application/json"]) ->
%% ["text/html", "application/json"]
%%
%% 2) For an "Accept" header with value "text/html, application/":
%% accepted_content_types(["application/json", "text/html"]) ->
%% ["application/json", "text/html"]
%%
%% 3) For an "Accept" header with value "text/html, */
; q=0.0":
%% accepted_content_types(["text/html", "application/json"]) ->
%% ["text/html"]
%%
%% 4) For an "Accept" header with value "text/html; q=0.5, /; q=0.1":
%% accepts_content_types(["application/json", "text/html"]) ->
%% ["text/html", "application/json"]
%%

fdmanana added some commits
@fdmanana fdmanana Add mochiweb_request:accepted_content_types/1
%% @spec accepted_content_types([string() | binary()]) -> [string()] | bad_accept_header
%%
%% @doc Filters which of the given media types this request accepts. This filtering
%%      is performed by analyzing the "Accept" header. The returned list is sorted
%%      according to the preferences specified in the "Accept" header (higher Q values
%%      first). If two or more types have the same preference (Q value), they're order
%%      in the returned list is the same as they're order in the input list.
%%
%%      Examples
%%
%%      1) For a missing "Accept" header:
%%         accepted_content_types(["text/html", "application/json"]) ->
%%             ["text/html", "application/json"]
%%
%%      2) For an "Accept" header with value "text/html, application/*":
%%         accepted_content_types(["application/json", "text/html"]) ->
%%             ["application/json", "text/html"]
%%
%%      3) For an "Accept" header with value "text/html, */*; q=0.0":
%%         accepted_content_types(["text/html", "application/json"]) ->
%%             ["text/html"]
%%
%%      4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1":
%%         accepts_content_types(["application/json", "text/html"]) ->
%%             ["text/html", "application/json"]
%%
68fd47d
@fdmanana fdmanana Add one more test for mochiweb_request:accepted_content_types/1 a2e3bb5
@etrepum etrepum merged commit 5d21379 into mochi:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 17, 2011
  1. @fdmanana

    Add mochiweb_request:accepted_content_types/1

    fdmanana authored
    %% @spec accepted_content_types([string() | binary()]) -> [string()] | bad_accept_header
    %%
    %% @doc Filters which of the given media types this request accepts. This filtering
    %%      is performed by analyzing the "Accept" header. The returned list is sorted
    %%      according to the preferences specified in the "Accept" header (higher Q values
    %%      first). If two or more types have the same preference (Q value), they're order
    %%      in the returned list is the same as they're order in the input list.
    %%
    %%      Examples
    %%
    %%      1) For a missing "Accept" header:
    %%         accepted_content_types(["text/html", "application/json"]) ->
    %%             ["text/html", "application/json"]
    %%
    %%      2) For an "Accept" header with value "text/html, application/*":
    %%         accepted_content_types(["application/json", "text/html"]) ->
    %%             ["application/json", "text/html"]
    %%
    %%      3) For an "Accept" header with value "text/html, */*; q=0.0":
    %%         accepted_content_types(["text/html", "application/json"]) ->
    %%             ["text/html"]
    %%
    %%      4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1":
    %%         accepts_content_types(["application/json", "text/html"]) ->
    %%             ["text/html", "application/json"]
    %%
Commits on Jun 21, 2011
  1. @fdmanana
This page is out of date. Refresh to see the latest.
Showing with 123 additions and 7 deletions.
  1. +76 −7 src/mochiweb_request.erl
  2. +47 −0 src/mochiweb_request_tests.erl
View
83 src/mochiweb_request.erl
@@ -21,7 +21,7 @@
-export([parse_cookie/0, get_cookie_value/1]).
-export([serve_file/2, serve_file/3]).
-export([accepted_encodings/1]).
--export([accepts_content_type/1]).
+-export([accepts_content_type/1, accepted_content_types/1]).
-define(SAVE_QS, mochiweb_request_qs).
-define(SAVE_PATH, mochiweb_request_path).
@@ -731,12 +731,7 @@ accepts_content_type(ContentType) when is_binary(ContentType) ->
accepts_content_type(binary_to_list(ContentType));
accepts_content_type(ContentType1) ->
ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]),
- AcceptHeader = case get_header_value("Accept") of
- undefined ->
- "*/*";
- Value ->
- Value
- end,
+ AcceptHeader = accept_header(),
case mochiweb_util:parse_qvalues(AcceptHeader) of
invalid_qvalue_string ->
bad_accept_header;
@@ -757,6 +752,80 @@ accepts_content_type(ContentType1) ->
(not lists:member({SuperType, 0.0}, QList))
end.
+%% @spec accepted_content_types([string() | binary()]) -> [string()] | bad_accept_header
+%%
+%% @doc Filters which of the given media types this request accepts. This filtering
+%% is performed by analyzing the "Accept" header. The returned list is sorted
+%% according to the preferences specified in the "Accept" header (higher Q values
+%% first). If two or more types have the same preference (Q value), they're order
+%% in the returned list is the same as they're order in the input list.
+%%
+%% Examples
+%%
+%% 1) For a missing "Accept" header:
+%% accepted_content_types(["text/html", "application/json"]) ->
+%% ["text/html", "application/json"]
+%%
+%% 2) For an "Accept" header with value "text/html, application/*":
+%% accepted_content_types(["application/json", "text/html"]) ->
+%% ["application/json", "text/html"]
+%%
+%% 3) For an "Accept" header with value "text/html, */*; q=0.0":
+%% accepted_content_types(["text/html", "application/json"]) ->
+%% ["text/html"]
+%%
+%% 4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1":
+%% accepts_content_types(["application/json", "text/html"]) ->
+%% ["text/html", "application/json"]
+%%
+accepted_content_types(Types1) ->
+ Types = lists:map(
+ fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end,
+ Types1),
+ AcceptHeader = accept_header(),
+ case mochiweb_util:parse_qvalues(AcceptHeader) of
+ invalid_qvalue_string ->
+ bad_accept_header;
+ QList ->
+ TypesQ = lists:foldr(
+ fun(T, Acc) ->
+ case proplists:get_value(T, QList) of
+ undefined ->
+ [MainType, _SubType] = string:tokens(T, "/"),
+ case proplists:get_value(MainType ++ "/*", QList) of
+ undefined ->
+ case proplists:get_value("*/*", QList) of
+ Q when is_float(Q), Q > 0.0 ->
+ [{Q, T} | Acc];
+ _ ->
+ Acc
+ end;
+ Q when Q > 0.0 ->
+ [{Q, T} | Acc];
+ _ ->
+ Acc
+ end;
+ Q when Q > 0.0 ->
+ [{Q, T} | Acc];
+ _ ->
+ Acc
+ end
+ end,
+ [], Types),
+ % Note: Stable sort. If 2 types have the same Q value we leave them in the
+ % same order as in the input list.
+ SortFun = fun({Q1, _}, {Q2, _}) -> Q1 >= Q2 end,
+ [Type || {_Q, Type} <- lists:sort(SortFun, TypesQ)]
+ end.
+
+accept_header() ->
+ case get_header_value("Accept") of
+ undefined ->
+ "*/*";
+ Value ->
+ Value
+ end.
+
%%
%% Tests
%%
View
47 src/mochiweb_request_tests.erl
@@ -101,4 +101,51 @@ accepted_encodings_test() ->
?assertEqual([],
Req8:accepted_encodings(["gzip", "identity"])).
+accepted_content_types_test() ->
+ Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/html"}])),
+ ?assertEqual(["text/html"],
+ Req1:accepted_content_types(["text/html", "application/json"])),
+
+ Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/html, */*;q=0"}])),
+ ?assertEqual(["text/html"],
+ Req2:accepted_content_types(["text/html", "application/json"])),
+
+ Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/*, */*;q=0"}])),
+ ?assertEqual(["text/html"],
+ Req3:accepted_content_types(["text/html", "application/json"])),
+
+ Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
+ ?assertEqual(["text/html", "application/json"],
+ Req4:accepted_content_types(["application/json", "text/html"])),
+
+ Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
+ ?assertEqual(["text/html", "application/json"],
+ Req5:accepted_content_types(["text/html", "application/json"])),
+
+ Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/*;q=0.5, */*;q=0.5"}])),
+ ?assertEqual(["application/json", "text/html"],
+ Req6:accepted_content_types(["application/json", "text/html"])),
+
+ Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make(
+ [{"Accept", "text/html;q=0.5, application/json;q=0.5"}])),
+ ?assertEqual(["application/json", "text/html"],
+ Req7:accepted_content_types(["application/json", "text/html"])),
+
+ Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/html"}])),
+ ?assertEqual([],
+ Req8:accepted_content_types(["application/json"])),
+
+ Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+ mochiweb_headers:make([{"Accept", "text/*;q=0.9, text/html;q=0.5, */*;q=0.7"}])),
+ ?assertEqual(["application/json", "text/html"],
+ Req9:accepted_content_types(["text/html", "application/json"])).
+
-endif.
Something went wrong with that request. Please try again.