Skip to content
This repository

Add mochiweb_request:accepted_content_types/1 #49

Merged
merged 2 commits into from over 2 years ago

2 participants

Filipe Manana Bob Ippolito
Filipe Manana

%% @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"]
%%

added some commits
Filipe Manana 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
Filipe Manana Add one more test for mochiweb_request:accepted_content_types/1 a2e3bb5
Bob Ippolito etrepum merged commit 5d21379 into from
Bob Ippolito etrepum closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Jun 17, 2011
Filipe Manana 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
Jun 21, 2011
Filipe Manana Add one more test for mochiweb_request:accepted_content_types/1 a2e3bb5
This page is out of date. Refresh to see the latest.
83  src/mochiweb_request.erl
@@ -21,7 +21,7 @@
21 21
 -export([parse_cookie/0, get_cookie_value/1]).
22 22
 -export([serve_file/2, serve_file/3]).
23 23
 -export([accepted_encodings/1]).
24  
--export([accepts_content_type/1]).
  24
+-export([accepts_content_type/1, accepted_content_types/1]).
25 25
 
26 26
 -define(SAVE_QS, mochiweb_request_qs).
27 27
 -define(SAVE_PATH, mochiweb_request_path).
@@ -731,12 +731,7 @@ accepts_content_type(ContentType) when is_binary(ContentType) ->
731 731
     accepts_content_type(binary_to_list(ContentType));
732 732
 accepts_content_type(ContentType1) ->
733 733
     ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]),
734  
-    AcceptHeader = case get_header_value("Accept") of
735  
-        undefined ->
736  
-            "*/*";
737  
-        Value ->
738  
-            Value
739  
-    end,
  734
+    AcceptHeader = accept_header(),
740 735
     case mochiweb_util:parse_qvalues(AcceptHeader) of
741 736
         invalid_qvalue_string ->
742 737
             bad_accept_header;
@@ -757,6 +752,80 @@ accepts_content_type(ContentType1) ->
757 752
             (not lists:member({SuperType, 0.0}, QList))
758 753
     end.
759 754
 
  755
+%% @spec accepted_content_types([string() | binary()]) -> [string()] | bad_accept_header
  756
+%%
  757
+%% @doc Filters which of the given media types this request accepts. This filtering
  758
+%%      is performed by analyzing the "Accept" header. The returned list is sorted
  759
+%%      according to the preferences specified in the "Accept" header (higher Q values
  760
+%%      first). If two or more types have the same preference (Q value), they're order
  761
+%%      in the returned list is the same as they're order in the input list.
  762
+%%
  763
+%%      Examples
  764
+%%
  765
+%%      1) For a missing "Accept" header:
  766
+%%         accepted_content_types(["text/html", "application/json"]) ->
  767
+%%             ["text/html", "application/json"]
  768
+%%
  769
+%%      2) For an "Accept" header with value "text/html, application/*":
  770
+%%         accepted_content_types(["application/json", "text/html"]) ->
  771
+%%             ["application/json", "text/html"]
  772
+%%
  773
+%%      3) For an "Accept" header with value "text/html, */*; q=0.0":
  774
+%%         accepted_content_types(["text/html", "application/json"]) ->
  775
+%%             ["text/html"]
  776
+%%
  777
+%%      4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1":
  778
+%%         accepts_content_types(["application/json", "text/html"]) ->
  779
+%%             ["text/html", "application/json"]
  780
+%%
  781
+accepted_content_types(Types1) ->
  782
+    Types = lists:map(
  783
+        fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end,
  784
+        Types1),
  785
+    AcceptHeader = accept_header(),
  786
+    case mochiweb_util:parse_qvalues(AcceptHeader) of
  787
+        invalid_qvalue_string ->
  788
+            bad_accept_header;
  789
+        QList ->
  790
+            TypesQ = lists:foldr(
  791
+                fun(T, Acc) ->
  792
+                    case proplists:get_value(T, QList) of
  793
+                        undefined ->
  794
+                            [MainType, _SubType] = string:tokens(T, "/"),
  795
+                            case proplists:get_value(MainType ++ "/*", QList) of
  796
+                                undefined ->
  797
+                                    case proplists:get_value("*/*", QList) of
  798
+                                        Q when is_float(Q), Q > 0.0 ->
  799
+                                            [{Q, T} | Acc];
  800
+                                        _ ->
  801
+                                            Acc
  802
+                                    end;
  803
+                                Q when Q > 0.0 ->
  804
+                                    [{Q, T} | Acc];
  805
+                                _ ->
  806
+                                    Acc
  807
+                            end;
  808
+                        Q when Q > 0.0 ->
  809
+                            [{Q, T} | Acc];
  810
+                        _ ->
  811
+                            Acc
  812
+                    end
  813
+                end,
  814
+                [], Types),
  815
+            % Note: Stable sort. If 2 types have the same Q value we leave them in the
  816
+            % same order as in the input list.
  817
+            SortFun = fun({Q1, _}, {Q2, _}) -> Q1 >= Q2 end,
  818
+            [Type || {_Q, Type} <- lists:sort(SortFun, TypesQ)]
  819
+    end.
  820
+
  821
+accept_header() ->
  822
+    case get_header_value("Accept") of
  823
+        undefined ->
  824
+            "*/*";
  825
+        Value ->
  826
+            Value
  827
+    end.
  828
+
760 829
 %%
761 830
 %% Tests
762 831
 %%
47  src/mochiweb_request_tests.erl
@@ -101,4 +101,51 @@ accepted_encodings_test() ->
101 101
     ?assertEqual([],
102 102
                  Req8:accepted_encodings(["gzip", "identity"])).
103 103
 
  104
+accepted_content_types_test() ->
  105
+    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  106
+        mochiweb_headers:make([{"Accept", "text/html"}])),
  107
+    ?assertEqual(["text/html"],
  108
+        Req1:accepted_content_types(["text/html", "application/json"])),
  109
+
  110
+    Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  111
+        mochiweb_headers:make([{"Accept", "text/html, */*;q=0"}])),
  112
+    ?assertEqual(["text/html"],
  113
+        Req2:accepted_content_types(["text/html", "application/json"])),
  114
+
  115
+    Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  116
+        mochiweb_headers:make([{"Accept", "text/*, */*;q=0"}])),
  117
+    ?assertEqual(["text/html"],
  118
+        Req3:accepted_content_types(["text/html", "application/json"])),
  119
+
  120
+    Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  121
+        mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
  122
+    ?assertEqual(["text/html", "application/json"],
  123
+        Req4:accepted_content_types(["application/json", "text/html"])),
  124
+
  125
+    Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  126
+        mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
  127
+    ?assertEqual(["text/html", "application/json"],
  128
+        Req5:accepted_content_types(["text/html", "application/json"])),
  129
+
  130
+    Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  131
+        mochiweb_headers:make([{"Accept", "text/*;q=0.5, */*;q=0.5"}])),
  132
+    ?assertEqual(["application/json", "text/html"],
  133
+        Req6:accepted_content_types(["application/json", "text/html"])),
  134
+
  135
+    Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  136
+        mochiweb_headers:make(
  137
+            [{"Accept", "text/html;q=0.5, application/json;q=0.5"}])),
  138
+    ?assertEqual(["application/json", "text/html"],
  139
+        Req7:accepted_content_types(["application/json", "text/html"])),
  140
+
  141
+    Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  142
+        mochiweb_headers:make([{"Accept", "text/html"}])),
  143
+    ?assertEqual([],
  144
+        Req8:accepted_content_types(["application/json"])),
  145
+
  146
+    Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
  147
+        mochiweb_headers:make([{"Accept", "text/*;q=0.9, text/html;q=0.5, */*;q=0.7"}])),
  148
+    ?assertEqual(["application/json", "text/html"],
  149
+        Req9:accepted_content_types(["text/html", "application/json"])).
  150
+
104 151
 -endif.
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.