Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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 from
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.