You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2015/06/29 23:46:38 UTC

[32/50] couch commit: updated refs/heads/COUCHDB-2734-header-date to f3e022c

add scheme to hixie_handshake


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/55011262
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/55011262
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/55011262

Branch: refs/heads/COUCHDB-2734-header-date
Commit: 550112627ba671ab6a6e0aeaf30d6f2b6e02f6af
Parents: ecee927
Author: Bob Ippolito <bo...@redivi.com>
Authored: Wed Dec 25 15:22:23 2013 -0800
Committer: Bob Ippolito <bo...@redivi.com>
Committed: Wed Dec 25 15:22:23 2013 -0800

----------------------------------------------------------------------
 src/mochiweb_request_tests.erl    | 182 ---------------------------------
 src/mochiweb_websocket.erl        |  15 ++-
 src/mochiweb_websocket_tests.erl  |  70 -------------
 test/mochiweb_request_tests.erl   | 182 +++++++++++++++++++++++++++++++++
 test/mochiweb_websocket_tests.erl |  71 +++++++++++++
 5 files changed, 265 insertions(+), 255 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/55011262/src/mochiweb_request_tests.erl
----------------------------------------------------------------------
diff --git a/src/mochiweb_request_tests.erl b/src/mochiweb_request_tests.erl
deleted file mode 100644
index b40c867..0000000
--- a/src/mochiweb_request_tests.erl
+++ /dev/null
@@ -1,182 +0,0 @@
--module(mochiweb_request_tests).
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-accepts_content_type_test() ->
-    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "multipart/related"}])),
-    ?assertEqual(true, Req1:accepts_content_type("multipart/related")),
-    ?assertEqual(true, Req1:accepts_content_type(<<"multipart/related">>)),
-
-    Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html"}])),
-    ?assertEqual(false, Req2:accepts_content_type("multipart/related")),
-
-    Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*"}])),
-    ?assertEqual(true, Req3:accepts_content_type("multipart/related")),
-
-    Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0.0"}])),
-    ?assertEqual(false, Req4:accepts_content_type("multipart/related")),
-
-    Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0"}])),
-    ?assertEqual(false, Req5:accepts_content_type("multipart/related")),
-
-    Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, */*; q=0.0"}])),
-    ?assertEqual(false, Req6:accepts_content_type("multipart/related")),
-
-    Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "multipart/*; q=0.0, */*"}])),
-    ?assertEqual(false, Req7:accepts_content_type("multipart/related")),
-
-    Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/*"}])),
-    ?assertEqual(true, Req8:accepts_content_type("multipart/related")),
-
-    Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/related"}])),
-    ?assertEqual(true, Req9:accepts_content_type("multipart/related")),
-
-    Req10 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1"}])),
-    ?assertEqual(true, Req10:accepts_content_type("text/html;level=1")),
-
-    Req11 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1, text/html"}])),
-    ?assertEqual(true, Req11:accepts_content_type("text/html")),
-
-    Req12 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
-    ?assertEqual(false, Req12:accepts_content_type("text/html;level=1")),
-
-    Req13 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
-    ?assertEqual(false, Req13:accepts_content_type("text/html; level=1")),
-
-    Req14 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html;level=1;q=0.1, text/html"}])),
-    ?assertEqual(true, Req14:accepts_content_type("text/html; level=1")).
-
-accepted_encodings_test() ->
-    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-                                mochiweb_headers:make([])),
-    ?assertEqual(["identity"],
-                 Req1:accepted_encodings(["gzip", "identity"])),
-
-    Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])),
-    ?assertEqual(["gzip", "identity"],
-                 Req2:accepted_encodings(["gzip", "identity"])),
-
-    Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=0.5, deflate"}])),
-    ?assertEqual(["deflate", "gzip", "identity"],
-                 Req3:accepted_encodings(["gzip", "deflate", "identity"])),
-
-    Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "identity, *;q=0"}])),
-    ?assertEqual(["identity"],
-                 Req4:accepted_encodings(["gzip", "deflate", "identity"])),
-
-    Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=0.1, *;q=0"}])),
-    ?assertEqual(["gzip"],
-                 Req5:accepted_encodings(["gzip", "deflate", "identity"])),
-
-    Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=, *;q=0"}])),
-    ?assertEqual(bad_accept_encoding_value,
-                 Req6:accepted_encodings(["gzip", "deflate", "identity"])),
-
-    Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=2.0, *;q=0"}])),
-    ?assertEqual(bad_accept_encoding_value,
-                 Req7:accepted_encodings(["gzip", "identity"])),
-
-    Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])),
-    ?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"])).
-
-should_close_test() ->
-    F = fun (V, H) ->
-                (mochiweb_request:new(
-                   nil, 'GET', "/", V,
-                   mochiweb_headers:make(H)
-                  )):should_close()
-        end,
-    ?assertEqual(
-       true,
-       F({1, 1}, [{"Connection", "close"}])),
-    ?assertEqual(
-       true,
-       F({1, 0}, [{"Connection", "close"}])),
-    ?assertEqual(
-       true,
-       F({1, 1}, [{"Connection", "ClOSe"}])),
-    ?assertEqual(
-       false,
-       F({1, 1}, [{"Connection", "closer"}])),
-    ?assertEqual(
-       false,
-       F({1, 1}, [])),
-    ?assertEqual(
-       true,
-       F({1, 0}, [])),
-    ?assertEqual(
-       false,
-       F({1, 0}, [{"Connection", "Keep-Alive"}])),
-    ok.
-
--endif.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/55011262/src/mochiweb_websocket.erl
----------------------------------------------------------------------
diff --git a/src/mochiweb_websocket.erl b/src/mochiweb_websocket.erl
index 8309a11..5224312 100644
--- a/src/mochiweb_websocket.erl
+++ b/src/mochiweb_websocket.erl
@@ -111,7 +111,8 @@ make_handshake(Req) ->
             Host = Req:get_header_value("Host"),
             Path = Req:get(path),
             Body = Req:recv(8),
-            hixie_handshake(Host, Path, Sec1Key, Sec2Key, Body, Origin);
+            Scheme = scheme(Req),
+            hixie_handshake(Scheme, Host, Path, Sec1Key, Sec2Key, Body, Origin);
 
        true ->
           error
@@ -127,7 +128,15 @@ hybi_handshake(SecKey) ->
                       {"Sec-Websocket-Accept", Challenge}], ""},
     {hybi, Response}.
 
-hixie_handshake(Host, Path, Key1, Key2, Body, Origin) ->
+scheme(Req) ->
+    case mochiweb_request:get(scheme, Req) of
+        http ->
+            "ws://";
+        https ->
+            "wss://"
+    end.
+
+hixie_handshake(Scheme, Host, Path, Key1, Key2, Body, Origin) ->
   Ikey1 = [D || D <- Key1, $0 =< D, D =< $9],
   Ikey2 = [D || D <- Key2, $0 =< D, D =< $9],
   Blank1 = length([D || D <- Key1, D =:= 32]),
@@ -137,7 +146,7 @@ hixie_handshake(Host, Path, Key1, Key2, Body, Origin) ->
   Ckey = <<Part1:4/big-unsigned-integer-unit:8, Part2:4/big-unsigned-integer-unit:8, Body/binary>>,
   Challenge = erlang:md5(Ckey),
 
-  Location = lists:concat(["ws://", Host, Path]),
+  Location = lists:concat([Scheme, Host, Path]),
 
   Response = {101, [{"Upgrade", "WebSocket"},
                      {"Connection", "Upgrade"},

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/55011262/src/mochiweb_websocket_tests.erl
----------------------------------------------------------------------
diff --git a/src/mochiweb_websocket_tests.erl b/src/mochiweb_websocket_tests.erl
deleted file mode 100644
index a98a9ea..0000000
--- a/src/mochiweb_websocket_tests.erl
+++ /dev/null
@@ -1,70 +0,0 @@
--module(mochiweb_websocket_tests).
--author('lukasz.lalik@zadane.pl').
-
-%% The MIT License (MIT)
-
-%% Copyright (c) 2012 Zadane.pl sp. z o.o.
-
-%% Permission is hereby granted, free of charge, to any person obtaining a copy
-%% of this software and associated documentation files (the "Software"), to deal
-%% in the Software without restriction, including without limitation the rights
-%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-%% copies of the Software, and to permit persons to whom the Software is
-%% furnished to do so, subject to the following conditions:
-
-%% The above copyright notice and this permission notice shall be included in
-%% all copies or substantial portions of the Software.
-
-%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-%% THE SOFTWARE.
-
--ifdef(TEST).
--include_lib("eunit/include/eunit.hrl").
-
-make_handshake_for_correct_client_test() ->
-    %% Hybi handshake
-    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Sec-WebSocket-Key", "Xn3fdKyc3qEXPuj2A3O+ZA=="}])),
-
-    {Version1, {HttpCode1, Headers1, _}} = mochiweb_websocket:make_handshake(Req1),
-    ?assertEqual(hybi, Version1),
-    ?assertEqual(101, HttpCode1),
-    ?assertEqual("Upgrade", proplists:get_value("Connection", Headers1)),
-    ?assertEqual(<<"BIFTHkJk4r5t8kuud82tZJaQsCE=">>, proplists:get_value("Sec-Websocket-Accept", Headers1)),
-
-    %% Hixie handshake
-    {Version2, {HttpCode2, Headers2, Body2}} = mochiweb_websocket:hixie_handshake(
-                                            "localhost", "/",
-                                            "33j284    9  z63 e 9 7",
-                                            "TF'3|6D12659H 7 70",
-                                            <<175,181,191,215,128,195,144,120>>,
-                                            "null"),
-    ?assertEqual(hixie, Version2),
-    ?assertEqual(101, HttpCode2),
-    ?assertEqual("null", proplists:get_value("Sec-WebSocket-Origin", Headers2)),
-    ?assertEqual("ws://localhost/", proplists:get_value("Sec-WebSocket-Location", Headers2)),
-    ?assertEqual(<<230,144,237,94,84,214,41,69,244,150,134,167,221,103,239,246>>, Body2).
-
-hybi_frames_decode_test() ->
-    Resp1 = mochiweb_websocket:parse_hybi_frames(nil, <<129,131,118,21,153,58,16,122,246>>, []),
-    ?assertEqual([{1, <<"foo">>}], Resp1),
-
-    Resp2 = mochiweb_websocket:parse_hybi_frames(nil, <<129,131,1,225,201,42,103,142,166,129,131,93,222,214,66,63,191,164>>, []),
-    ?assertEqual([{1, <<"foo">>}, {1, <<"bar">>}], Resp2).
-
-hixie_frames_decode_test() ->
-    Resp1 = mochiweb_websocket:parse_hixie_frames(<<>>, []),
-    ?assertEqual([], Resp1),
-
-    Resp2 = mochiweb_websocket:parse_hixie_frames(<<0,102,111,111,255>>, []),
-    ?assertEqual([<<"foo">>], Resp2),
-
-    Resp3 = mochiweb_websocket:parse_hixie_frames(<<0,102,111,111,255,0,98,97,114,255>>, []),
-    ?assertEqual([<<"foo">>, <<"bar">>], Resp3).
-
--endif.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/55011262/test/mochiweb_request_tests.erl
----------------------------------------------------------------------
diff --git a/test/mochiweb_request_tests.erl b/test/mochiweb_request_tests.erl
new file mode 100644
index 0000000..b40c867
--- /dev/null
+++ b/test/mochiweb_request_tests.erl
@@ -0,0 +1,182 @@
+-module(mochiweb_request_tests).
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+accepts_content_type_test() ->
+    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "multipart/related"}])),
+    ?assertEqual(true, Req1:accepts_content_type("multipart/related")),
+    ?assertEqual(true, Req1:accepts_content_type(<<"multipart/related">>)),
+
+    Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html"}])),
+    ?assertEqual(false, Req2:accepts_content_type("multipart/related")),
+
+    Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html, multipart/*"}])),
+    ?assertEqual(true, Req3:accepts_content_type("multipart/related")),
+
+    Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0.0"}])),
+    ?assertEqual(false, Req4:accepts_content_type("multipart/related")),
+
+    Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0"}])),
+    ?assertEqual(false, Req5:accepts_content_type("multipart/related")),
+
+    Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html, */*; q=0.0"}])),
+    ?assertEqual(false, Req6:accepts_content_type("multipart/related")),
+
+    Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "multipart/*; q=0.0, */*"}])),
+    ?assertEqual(false, Req7:accepts_content_type("multipart/related")),
+
+    Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/*"}])),
+    ?assertEqual(true, Req8:accepts_content_type("multipart/related")),
+
+    Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/related"}])),
+    ?assertEqual(true, Req9:accepts_content_type("multipart/related")),
+
+    Req10 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html; level=1"}])),
+    ?assertEqual(true, Req10:accepts_content_type("text/html;level=1")),
+
+    Req11 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html; level=1, text/html"}])),
+    ?assertEqual(true, Req11:accepts_content_type("text/html")),
+
+    Req12 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
+    ?assertEqual(false, Req12:accepts_content_type("text/html;level=1")),
+
+    Req13 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
+    ?assertEqual(false, Req13:accepts_content_type("text/html; level=1")),
+
+    Req14 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept", "text/html;level=1;q=0.1, text/html"}])),
+    ?assertEqual(true, Req14:accepts_content_type("text/html; level=1")).
+
+accepted_encodings_test() ->
+    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+                                mochiweb_headers:make([])),
+    ?assertEqual(["identity"],
+                 Req1:accepted_encodings(["gzip", "identity"])),
+
+    Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])),
+    ?assertEqual(["gzip", "identity"],
+                 Req2:accepted_encodings(["gzip", "identity"])),
+
+    Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=0.5, deflate"}])),
+    ?assertEqual(["deflate", "gzip", "identity"],
+                 Req3:accepted_encodings(["gzip", "deflate", "identity"])),
+
+    Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "identity, *;q=0"}])),
+    ?assertEqual(["identity"],
+                 Req4:accepted_encodings(["gzip", "deflate", "identity"])),
+
+    Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=0.1, *;q=0"}])),
+    ?assertEqual(["gzip"],
+                 Req5:accepted_encodings(["gzip", "deflate", "identity"])),
+
+    Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=, *;q=0"}])),
+    ?assertEqual(bad_accept_encoding_value,
+                 Req6:accepted_encodings(["gzip", "deflate", "identity"])),
+
+    Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=2.0, *;q=0"}])),
+    ?assertEqual(bad_accept_encoding_value,
+                 Req7:accepted_encodings(["gzip", "identity"])),
+
+    Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])),
+    ?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"])).
+
+should_close_test() ->
+    F = fun (V, H) ->
+                (mochiweb_request:new(
+                   nil, 'GET', "/", V,
+                   mochiweb_headers:make(H)
+                  )):should_close()
+        end,
+    ?assertEqual(
+       true,
+       F({1, 1}, [{"Connection", "close"}])),
+    ?assertEqual(
+       true,
+       F({1, 0}, [{"Connection", "close"}])),
+    ?assertEqual(
+       true,
+       F({1, 1}, [{"Connection", "ClOSe"}])),
+    ?assertEqual(
+       false,
+       F({1, 1}, [{"Connection", "closer"}])),
+    ?assertEqual(
+       false,
+       F({1, 1}, [])),
+    ?assertEqual(
+       true,
+       F({1, 0}, [])),
+    ?assertEqual(
+       false,
+       F({1, 0}, [{"Connection", "Keep-Alive"}])),
+    ok.
+
+-endif.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/55011262/test/mochiweb_websocket_tests.erl
----------------------------------------------------------------------
diff --git a/test/mochiweb_websocket_tests.erl b/test/mochiweb_websocket_tests.erl
new file mode 100644
index 0000000..98cb860
--- /dev/null
+++ b/test/mochiweb_websocket_tests.erl
@@ -0,0 +1,71 @@
+-module(mochiweb_websocket_tests).
+-author('lukasz.lalik@zadane.pl').
+
+%% The MIT License (MIT)
+
+%% Copyright (c) 2012 Zadane.pl sp. z o.o.
+
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+make_handshake_for_correct_client_test() ->
+    %% Hybi handshake
+    Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
+        mochiweb_headers:make([{"Sec-WebSocket-Key", "Xn3fdKyc3qEXPuj2A3O+ZA=="}])),
+
+    {Version1, {HttpCode1, Headers1, _}} = mochiweb_websocket:make_handshake(Req1),
+    ?assertEqual(hybi, Version1),
+    ?assertEqual(101, HttpCode1),
+    ?assertEqual("Upgrade", proplists:get_value("Connection", Headers1)),
+    ?assertEqual(<<"BIFTHkJk4r5t8kuud82tZJaQsCE=">>, proplists:get_value("Sec-Websocket-Accept", Headers1)),
+
+    %% Hixie handshake
+    {Version2, {HttpCode2, Headers2, Body2}} = mochiweb_websocket:hixie_handshake(
+                                            "ws://",
+                                            "localhost", "/",
+                                            "33j284    9  z63 e 9 7",
+                                            "TF'3|6D12659H 7 70",
+                                            <<175,181,191,215,128,195,144,120>>,
+                                            "null"),
+    ?assertEqual(hixie, Version2),
+    ?assertEqual(101, HttpCode2),
+    ?assertEqual("null", proplists:get_value("Sec-WebSocket-Origin", Headers2)),
+    ?assertEqual("ws://localhost/", proplists:get_value("Sec-WebSocket-Location", Headers2)),
+    ?assertEqual(<<230,144,237,94,84,214,41,69,244,150,134,167,221,103,239,246>>, Body2).
+
+hybi_frames_decode_test() ->
+    Resp1 = mochiweb_websocket:parse_hybi_frames(nil, <<129,131,118,21,153,58,16,122,246>>, []),
+    ?assertEqual([{1, <<"foo">>}], Resp1),
+
+    Resp2 = mochiweb_websocket:parse_hybi_frames(nil, <<129,131,1,225,201,42,103,142,166,129,131,93,222,214,66,63,191,164>>, []),
+    ?assertEqual([{1, <<"foo">>}, {1, <<"bar">>}], Resp2).
+
+hixie_frames_decode_test() ->
+    Resp1 = mochiweb_websocket:parse_hixie_frames(<<>>, []),
+    ?assertEqual([], Resp1),
+
+    Resp2 = mochiweb_websocket:parse_hixie_frames(<<0,102,111,111,255>>, []),
+    ?assertEqual([<<"foo">>], Resp2),
+
+    Resp3 = mochiweb_websocket:parse_hixie_frames(<<0,102,111,111,255,0,98,97,114,255>>, []),
+    ?assertEqual([<<"foo">>, <<"bar">>], Resp3).
+
+-endif.