You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by wi...@apache.org on 2020/01/13 19:41:59 UTC

[couchdb-mochiweb] branch upstream updated (9608d78 -> 1b7c058)

This is an automated email from the ASF dual-hosted git repository.

willholley pushed a change to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git.


    from 9608d78  Merge pull request #205 from choptastic/exit_if_inval
     new d1c202f  add map support for mochijson2:decode/2
     new 7e6f4ef  Allow setting {buffer, Buffer} socket server option
     new 0981560  Add 21.1 and 21.2 to otp_release matrix
     new 5e06455  Use ssl:handshake/2 unconditionally to see when it is first available
     new 105c9cb  Conditional ssl:handshake/2
     new ea863d7  Add a runtime SSL compatibility check for OTP 21 releases
     new e2eb019  Update README.md
     new 1991194  Update vsn and CHANGES in prep for a release (waiting for an OTP maint release that fixes SSL)
     new b39178e  Confirmed that 21.2.3 is compatible
     new 790f135  Note this PR. Still have to wait a day for Travis-CI to have this build available
     new 5d4686c  Update CHANGES.md with release date
     new 82002ed  Add missing issue URL to CHANGES.md
     new 4bee8b6  fix cookie value parsing
     new 3752e99  Use more direct translation of RFC 6265 grammar
     new 9f82853  Remove compile(tuple_calls) from mochifmt
     new 9465b8a  Remove compile(tuple_calls) from mochiweb_acceptor
     new 75d8849  Remove compile(tuple_calls) from mochiweb_http
     new 6a287a2  Remove compile(tuple_calls) from mochiweb_multipart
     new 9c964e3  Remove compile(tuple_calls) from mochiweb_request
     new 6a8a828  Remove compile(tuple_calls) from mochiweb_response
     new 0e0d1de  Remove compile(tuple_calls) from mochiweb_websocket
     new 896999a  Remove compile(tuple_calls) from the template
     new 7421d25  Remove compile(tuple_calls) from examples/hmac_api
     new 78f5e15  Remove compile(tuple_calls) from examples/https_store
     new f3a5b37  Remove compile(tuple_calls) from examples/keepalive
     new 344dd93  Remove compile(tuple_calls) from test/mochiweb_http_tests
     new 13ea57e  Remove compile(tuple_calls) from test/mochiweb_websocket_tests
     new 79acdab  Remove compile(tuple_calls) from test/mochiweb_tests
     new 63d44f0  Remove compile(tuple_calls) from test/mochiweb_request_tests
     new 3d3f929  Run erl_tidy on modified source files
     new 2eb68af  Update README.md
     new dc3db03  Update README.md
     new 80739b7  Debug Travis, it seems like older releases are not working
     new 1006be7  Use a matrix to get an older dist for old releases
     new a7e09cd  Use https for URLs in README.md
     new f2b90b9  add support for SameSite=none in cookies
     new 1b7c058  Update CHANGES and add OTP 21.3, 22 to travis matrix

The 37 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .travis.yml                                        |   18 +-
 CHANGES.md                                         |   25 +
 README                                             |   17 -
 README.md                                          |   23 +
 examples/hmac_api/README                           |    2 +-
 examples/hmac_api/hmac_api_lib.erl                 |  356 +++---
 examples/https/https_store.erl                     |  148 +--
 examples/keepalive/keepalive.erl                   |   76 +-
 rebar.config                                       |    4 +-
 src/mochifmt.erl                                   |  418 ++++---
 src/mochijson2.erl                                 |   21 +-
 src/mochiweb.app.src                               |    2 +-
 src/mochiweb_acceptor.erl                          |   69 +-
 src/mochiweb_cookies.erl                           |   43 +-
 src/mochiweb_http.erl                              |  380 +++---
 src/mochiweb_multipart.erl                         | 1243 ++++++++++---------
 src/mochiweb_request.erl                           | 1284 ++++++++++++--------
 src/mochiweb_response.erl                          |   45 +-
 src/mochiweb_socket.erl                            |   12 +
 src/mochiweb_socket_server.erl                     |   63 +-
 src/mochiweb_websocket.erl                         |  293 +++--
 .../mochiwebapp_skel/src/mochiapp_web.erl          |   90 +-
 test/mochiweb_http_tests.erl                       |   48 +-
 test/mochiweb_request_tests.erl                    |  294 +++--
 test/mochiweb_tests.erl                            |  246 ++--
 test/mochiweb_websocket_tests.erl                  |  191 +--
 26 files changed, 2979 insertions(+), 2432 deletions(-)
 delete mode 100644 README
 create mode 100644 README.md


[couchdb-mochiweb] 37/37: Update CHANGES and add OTP 21.3, 22 to travis matrix

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 1b7c0582cef4f412113b1722dca5dd84b28dbd7d
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sun Jul 14 21:39:43 2019 -0400

    Update CHANGES and add OTP 21.3, 22 to travis matrix
---
 .travis.yml | 2 ++
 CHANGES.md  | 5 ++++-
 README.md   | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index ecc72df..271323e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,8 @@ language: erlang
 notifications:
   email: false
 otp_release:
+  - 22.0
+  - 21.3
   - 21.2.3
   - 21.1
   - 21.0
diff --git a/CHANGES.md b/CHANGES.md
index e4f10d7..fdf306b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,8 @@
-Version 2.20.0 released 2019-XX-XX
+Version 2.20.0 released 2019-07-14
 
+* Expand testing matrix to include Erlang/OTP 22.0 and Erlang/OTP 21.3
+* Add support for SameSite=none in cookies
+  https://github.com/mochi/mochiweb/pull/225
 * Fix parsing of certain unquoted cookie values
   https://github.com/mochi/mochiweb/pull/212
 
diff --git a/README.md b/README.md
index 44e392b..dcd96f8 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ To create a new mochiweb using project in a specific directory:
 
 Information about Rebar (Erlang build tool) is available at https://github.com/rebar/rebar
 
-MochiWeb is currently tested with Erlang/OTP R15B03 through 21.2.3.
+MochiWeb is currently tested with Erlang/OTP R15B03 through 22.0.
 
 # OTP 21.2, 21.2.1, 21.2.2 warning
 


[couchdb-mochiweb] 28/37: Remove compile(tuple_calls) from test/mochiweb_tests

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 79acdab50df9a5951350077bb5a4d55ea7a82f7b
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Mar 12 01:32:24 2019 +0000

    Remove compile(tuple_calls) from test/mochiweb_tests
---
 test/mochiweb_tests.erl | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/test/mochiweb_tests.erl b/test/mochiweb_tests.erl
index 697f7c6..ae88bda 100644
--- a/test/mochiweb_tests.erl
+++ b/test/mochiweb_tests.erl
@@ -2,14 +2,12 @@
 -include_lib("eunit/include/eunit.hrl").
 -include("mochiweb_test_util.hrl").
 
--compile(tuple_calls).
-
 with_server(Transport, ServerFun, ClientFun) ->
     mochiweb_test_util:with_server(Transport, ServerFun, ClientFun).
 
 request_test() ->
     R = mochiweb_request:new(z, z, "//foo///bar/baz%20wibble+quux?qs=2", z, []),
-    "/foo/bar/baz wibble quux" = R:get(path),
+    "/foo/bar/baz wibble quux" = mochiweb_request:get(path, R),
     ok.
 
 -define(LARGE_TIMEOUT, 60).
@@ -77,7 +75,7 @@ single_GET_scheme_test_() ->
 single_GET_absoluteURI_test_() ->
     Uri = "https://example.com:123/x/",
     ServerFun = fun (Req) ->
-                        Req:ok({"text/plain", Req:get(path)})
+                        mochiweb_request:ok({"text/plain", mochiweb_request:get(path, Req)}, Req)
                 end,
     %% Note that all the scheme/host/port information is discarded from path
     ClientFun = new_client_fun('GET', [#treq{path = Uri, xreply = <<"/x/">>}]),
@@ -91,7 +89,7 @@ single_CONNECT_test_() ->
 
 single_GET_any_test_() ->
     ServerFun = fun (Req) ->
-                        Req:ok({"text/plain", Req:get(path)})
+                        mochiweb_request:ok({"text/plain", mochiweb_request:get(path, Req)}, Req)
                 end,
     ClientFun = new_client_fun('GET', [#treq{path = "*", xreply = <<"*">>}]),
     [{atom_to_list(Transport),
@@ -104,8 +102,8 @@ cookie_header_test() ->
     ExHeaders = [{"Set-Cookie", "foo=bar"},
                  {"Set-Cookie", "foo=baz"}],
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ Req:get(path),
-                        Req:ok({"text/plain", ExHeaders, Reply})
+                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+                        mochiweb_request:ok({"text/plain", ExHeaders, Reply}, Req)
                 end,
     Path = "cookie_header",
     ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
@@ -119,8 +117,8 @@ do_CONNECT(Transport, Times) ->
     PathPrefix = "example.com:",
     ReplyPrefix = "You requested: ",
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ Req:get(path),
-                        Req:ok({"text/plain", Reply})
+                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+                        mochiweb_request:ok({"text/plain", Reply}, Req)
                 end,
     TestReqs = [begin
                     Path = PathPrefix ++ integer_to_list(N),
@@ -137,8 +135,8 @@ do_GET(Transport, Times) ->
 do_GET(PathPrefix, Transport, Times) ->
     ReplyPrefix = "You requested: ",
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ Req:get(path),
-                        Req:ok({"text/plain", Reply})
+                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+                        mochiweb_request:ok({"text/plain", Reply}, Req)
                 end,
     TestReqs = [begin
                     Path = PathPrefix ++ integer_to_list(N),
@@ -151,9 +149,9 @@ do_GET(PathPrefix, Transport, Times) ->
 
 do_POST(Transport, Size, Times) ->
     ServerFun = fun (Req) ->
-                        Body = Req:recv_body(),
+                        Body = mochiweb_request:recv_body(Req),
                         Headers = [{"Content-Type", "application/octet-stream"}],
-                        Req:respond({201, Headers, Body})
+                        mochiweb_request:respond({201, Headers, Body}, Req)
                 end,
     TestReqs = [begin
                     Path = "/stuff/" ++ integer_to_list(N),


[couchdb-mochiweb] 07/37: Update README.md

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit e2eb019bf2e3e2aeb13dbf0ac95ed2413696f27c
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Jan 15 15:14:16 2019 -0800

    Update README.md
---
 README => README.md | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/README b/README.md
similarity index 55%
rename from README
rename to README.md
index 80ee6e4..d39374a 100644
--- a/README
+++ b/README.md
@@ -4,14 +4,17 @@ The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
 
 The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
 
-R12B compatibility:
-The master of MochiWeb is tested with R14A and later. A branch compatible
-with R12B is maintained separately at http://github.com/lemenkov/mochiweb
-The R12B branch of that repository is mirrored in the official repository
-occasionally for convenience.
-
 To create a new mochiweb using project:
    make app PROJECT=project_name
 
 To create a new mochiweb using project in a specific directory:
    make app PROJECT=project_name PREFIX=$HOME/projects/
+
+MochiWeb is currently tested with Erlang/OTP R15B03 through 21.1.
+
+# OTP 21.2 warning
+
+OTP 21.2 (up to and including 21.2.2) introduced an SSL regression that
+makes these releases unsafe to use. See [ERL-830](https://bugs.erlang.org/browse/ERL-830).
+This issue has been fixed in the maintenance branch but a release is not
+yet available.


[couchdb-mochiweb] 03/37: Add 21.1 and 21.2 to otp_release matrix

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 0981560d8c22b96a4bbae894fbdcc3c72aa91126
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Thu Jan 10 11:58:57 2019 -0800

    Add 21.1 and 21.2 to otp_release matrix
---
 .travis.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 8de93ab..8c8d1d2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,8 @@ language: erlang
 notifications:
   email: false
 otp_release:
+  - 21.2
+  - 21.1
   - 21.0
   - 20.0
   - 19.0


[couchdb-mochiweb] 32/37: Update README.md

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit dc3db03a04702cc5add3490a5c0024e2ee701e20
Author: penhs <46...@users.noreply.github.com>
AuthorDate: Tue May 21 17:26:37 2019 -0700

    Update README.md
---
 README.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 3f00b31..673e384 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,7 @@ The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
 
 The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
 
-Required for setting up the MochiWeb environment:
-   Erlang OTP: http://www.erlang.org/
+Erlang OTP is required for setting up the MochiWeb environment and is available at http://www.erlang.org/
 
 To create a new mochiweb using project:
    make app PROJECT=project_name
@@ -13,8 +12,7 @@ To create a new mochiweb using project:
 To create a new mochiweb using project in a specific directory:
    make app PROJECT=project_name PREFIX=$HOME/projects/
 
-Information about Rebar (Erlang build tool): 
-   https://github.com/rebar/rebar
+Information about Rebar (Erlang build tool) is available at https://github.com/rebar/rebar
 
 MochiWeb is currently tested with Erlang/OTP R15B03 through 21.2.3.
 


[couchdb-mochiweb] 12/37: Add missing issue URL to CHANGES.md

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 82002ed40e2537755360042d64986c5f89f47f4d
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Thu Jan 17 18:01:02 2019 +0000

    Add missing issue URL to CHANGES.md
---
 CHANGES.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGES.md b/CHANGES.md
index e3ac5c3..45464d0 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -13,6 +13,7 @@ Version 2.19.0 released 2019-01-17
 * No longer crash when a socket is closed server-side
   https://github.com/mochi/mochiweb/pull/205
 * Support for SameSite cookie setting
+  https://github.com/mochi/mochiweb/pull/203
 
 Version 2.18.0 released 2018-05-12
 


[couchdb-mochiweb] 01/37: add map support for mochijson2:decode/2

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit d1c202f5a7147b66f14a205545ceca3a88d369c4
Author: Oleg Nemanov <le...@yandex.ru>
AuthorDate: Fri Nov 30 14:37:53 2018 +0300

    add map support for mochijson2:decode/2
    
    Option {format, map} switch output to map.
---
 src/mochijson2.erl | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/mochijson2.erl b/src/mochijson2.erl
index e39c522..94ac2f8 100644
--- a/src/mochijson2.erl
+++ b/src/mochijson2.erl
@@ -125,10 +125,11 @@ decoder(Options) ->
     State = parse_decoder_options(Options, #decoder{}),
     fun (O) -> json_decode(O, State) end.
 
-%% @spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term()
+%% @spec decode(iolist(), [{format, proplist | eep18 | struct | map}]) -> json_term()
 %% @doc Decode the given iolist to Erlang terms using the given object format
 %%      for decoding, where proplist returns JSON objects as [{binary(), json_term()}]
-%%      proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct
+%%      proplists, eep18 returns JSON objects as {[binary(), json_term()]},
+%%      map returns JSON objects as #{binary() => json_term()}, and struct
 %%      returns them as-is.
 decode(S, Options) ->
     json_decode(S, parse_decoder_options(Options, #decoder{})).
@@ -151,10 +152,21 @@ parse_decoder_options([], State) ->
     State;
 parse_decoder_options([{object_hook, Hook} | Rest], State) ->
     parse_decoder_options(Rest, State#decoder{object_hook=Hook});
+parse_decoder_options([{format, map} | Rest], State) ->
+    Hook = make_object_hook_for_map(),
+    parse_decoder_options(Rest, State#decoder{object_hook=Hook});
 parse_decoder_options([{format, Format} | Rest], State)
   when Format =:= struct orelse Format =:= eep18 orelse Format =:= proplist ->
     parse_decoder_options(Rest, State#decoder{object_hook=Format}).
 
+-ifdef(map_unavailable).
+make_object_hook_for_map() ->
+    exit({json_decode, {bad_format, map_unavailable}}).
+-else.
+make_object_hook_for_map() ->
+    fun ({struct, P}) -> maps:from_list(P) end.
+-endif.
+
 
 json_encode(true, _State) ->
     <<"true">>;
@@ -967,6 +979,11 @@ utf8_non_character_test_() ->
 
 -ifndef(map_unavailable).
 
+decode_map_test() ->
+    Json = "{\"var1\": 3, \"var2\": {\"var3\": 7}}",
+    M = #{<<"var1">> => 3,<<"var2">> => #{<<"var3">> => 7}},
+    ?assertEqual(M, decode(Json, [{format, map}])).
+
 encode_map_test() ->
     M = <<"{\"a\":1,\"b\":{\"c\":2}}">>,
     ?assertEqual(M, iolist_to_binary(encode(#{a => 1, b => #{ c => 2}}))).


[couchdb-mochiweb] 19/37: Remove compile(tuple_calls) from mochiweb_request

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 9c964e32fdf5614d9b9296c034d4d3edda332345
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:50:54 2019 +0000

    Remove compile(tuple_calls) from mochiweb_request
---
 src/mochiweb_request.erl | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/mochiweb_request.erl b/src/mochiweb_request.erl
index 240f043..3889d33 100644
--- a/src/mochiweb_request.erl
+++ b/src/mochiweb_request.erl
@@ -24,8 +24,6 @@
 -module(mochiweb_request).
 -author('bob@mochimedia.com').
 
--compile(tuple_calls).
-
 -include_lib("kernel/include/file.hrl").
 -include("internal.hrl").
 
@@ -428,7 +426,7 @@ ok({ContentType, Body}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version,
     ok({ContentType, [], Body}, THIS);
 ok({ContentType, ResponseHeaders, Body}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
-    case THIS:get(range) of
+    case get(range, THIS) of
         X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked ->
             %% http://code.google.com/p/mochiweb/issues/detail?id=54
             %% Range header not supported when chunked, return 200 and provide


[couchdb-mochiweb] 18/37: Remove compile(tuple_calls) from mochiweb_multipart

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 6a287a29e146d15d2afac0cf1becf9e458e31624
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:47:44 2019 +0000

    Remove compile(tuple_calls) from mochiweb_multipart
---
 src/mochiweb_multipart.erl | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/mochiweb_multipart.erl b/src/mochiweb_multipart.erl
index 6f611c0..46b7090 100644
--- a/src/mochiweb_multipart.erl
+++ b/src/mochiweb_multipart.erl
@@ -24,8 +24,6 @@
 -module(mochiweb_multipart).
 -author('bob@mochimedia.com').
 
--compile(tuple_calls).
-
 -export([parse_form/1, parse_form/2]).
 -export([parse_multipart_request/2]).
 -export([parts_to_body/3, parts_to_multipart_body/4]).
@@ -146,11 +144,11 @@ default_file_handler_1(Filename, ContentType, Acc) ->
             default_file_handler_1(Filename, ContentType, [Next | Acc])
     end.
 
-parse_multipart_request(Req, Callback) ->
+parse_multipart_request({ReqM, _} = Req, Callback) ->
     %% TODO: Support chunked?
-    Length = list_to_integer(Req:get_combined_header_value("content-length")),
+    Length = list_to_integer(ReqM:get_combined_header_value("content-length", Req)),
     Boundary = iolist_to_binary(
-                 get_boundary(Req:get_header_value("content-type"))),
+                 get_boundary(ReqM:get_header_value("content-type", Req))),
     Prefix = <<"\r\n--", Boundary/binary>>,
     BS = byte_size(Boundary),
     Chunk = read_chunk(Req, Length),
@@ -182,12 +180,12 @@ split_header(Line) ->
     {string:to_lower(string:strip(Name)),
      mochiweb_util:parse_header(Value)}.
 
-read_chunk(Req, Length) when Length > 0 ->
+read_chunk({ReqM, _} = Req, Length) when Length > 0 ->
     case Length of
         Length when Length < ?CHUNKSIZE ->
-            Req:recv(Length);
+            ReqM:recv(Length, Req);
         _ ->
-            Req:recv(?CHUNKSIZE)
+            ReqM:recv(?CHUNKSIZE, Req)
     end.
 
 read_more(State=#mp{length=Length, buffer=Buffer, req=Req}) ->


[couchdb-mochiweb] 27/37: Remove compile(tuple_calls) from test/mochiweb_websocket_tests

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 13ea57e7ba2c00b7a9242961e769933275789ce6
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Mar 12 01:32:14 2019 +0000

    Remove compile(tuple_calls) from test/mochiweb_websocket_tests
---
 test/mochiweb_websocket_tests.erl | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/test/mochiweb_websocket_tests.erl b/test/mochiweb_websocket_tests.erl
index 71fb9a6..0af29b7 100644
--- a/test/mochiweb_websocket_tests.erl
+++ b/test/mochiweb_websocket_tests.erl
@@ -23,8 +23,6 @@
 %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 %% THE SOFTWARE.
 
--compile(tuple_calls).
-
 -include_lib("eunit/include/eunit.hrl").
 
 make_handshake_for_correct_client_test() ->
@@ -94,8 +92,8 @@ end_to_end_test_factory(ServerTransport) ->
       end).
 
 end_to_end_server(Req) ->
-    ?assertEqual("Upgrade", Req:get_header_value("connection")),
-    ?assertEqual("websocket", Req:get_header_value("upgrade")),
+    ?assertEqual("Upgrade", mochiweb_request:get_header_value("connection", Req)),
+    ?assertEqual("websocket", mochiweb_request:get_header_value("upgrade", Req)),
     {ReentryWs, _ReplyChannel} = mochiweb_websocket:upgrade_connection(
                                    Req,
                                    fun end_to_end_ws_loop/3),


[couchdb-mochiweb] 23/37: Remove compile(tuple_calls) from examples/hmac_api

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 7421d25f1a1d27b1365c752e85f1f6b77507cf82
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Mon Mar 11 22:51:02 2019 +0000

    Remove compile(tuple_calls) from examples/hmac_api
---
 examples/hmac_api/hmac_api_lib.erl | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/examples/hmac_api/hmac_api_lib.erl b/examples/hmac_api/hmac_api_lib.erl
index 95d7c58..4c26f2f 100644
--- a/examples/hmac_api/hmac_api_lib.erl
+++ b/examples/hmac_api/hmac_api_lib.erl
@@ -5,8 +5,6 @@
 
 -author("Hypernumbers Ltd <go...@hypernumbers.com>").
 
--compile(tuple_calls).
-
 %%% this library supports the hmac_sha api on both the client-side
 %%% AND the server-side
 %%%
@@ -36,9 +34,9 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 authorize_request(Req) ->
-    Method      = Req:get(method),
-    Path        = Req:get(path),
-    Headers     = normalise(mochiweb_headers:to_list(Req:get(headers))),
+    Method      = mochiweb_request:get(method, Req),
+    Path        = mochiweb_request:get(path, Req),
+    Headers     = normalise(mochiweb_headers:to_list(mochiweb_request:get(headers, Req))),
     ContentMD5  = get_header(Headers, "content-md5"),
     ContentType = get_header(Headers, "content-type"),
     Date        = get_header(Headers, "date"),


[couchdb-mochiweb] 14/37: Use more direct translation of RFC 6265 grammar

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 3752e99ec61efef6e6b1d57c5e0c43d84238721b
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Mon Mar 4 16:45:59 2019 +0000

    Use more direct translation of RFC 6265 grammar
---
 CHANGES.md               |  5 +++++
 src/mochiweb.app.src     |  2 +-
 src/mochiweb_cookies.erl | 19 ++++++++++++-------
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 45464d0..e4f10d7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,8 @@
+Version 2.20.0 released 2019-XX-XX
+
+* Fix parsing of certain unquoted cookie values
+  https://github.com/mochi/mochiweb/pull/212
+
 Version 2.19.0 released 2019-01-17
 
 * Fix warning in 21.2.3 and crash on incompatible releases
diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src
index 70c7165..6486fcb 100644
--- a/src/mochiweb.app.src
+++ b/src/mochiweb.app.src
@@ -1,7 +1,7 @@
 %% This is generated from src/mochiweb.app.src
 {application, mochiweb,
  [{description, "MochiMedia Web Server"},
-  {vsn, "2.19.0"},
+  {vsn, "2.20.0"},
   {modules, []},
   {registered, []},
   {env, []},
diff --git a/src/mochiweb_cookies.erl b/src/mochiweb_cookies.erl
index b6afb65..c7b0fcf 100644
--- a/src/mochiweb_cookies.erl
+++ b/src/mochiweb_cookies.erl
@@ -40,12 +40,17 @@
          C =:= ${ orelse C =:= $})).
 
 %% RFC 6265 cookie value allowed characters
--define(IS_COOKIE_VAL_ALLOWED(C),
-        (C =:= 33
-         orelse (C >= 35 andalso C =< 43)
-         orelse (C >= 45 andalso C =< 58)
-         orelse (C >= 60 andalso C =< 91)
-         orelse (C >= 93 andalso C =< 126))).
+%%  cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+%%                        ; US-ASCII characters excluding CTLs,
+%%                        ; whitespace DQUOTE, comma, semicolon,
+%%                        ; and backslash
+-define(IS_COOKIE_OCTET(C),
+        (C =:= 16#21
+         orelse (C >= 16#23 andalso C =< 16#2B)
+         orelse (C >= 16#2D andalso C =< 16#3A)
+         orelse (C >= 16#3C andalso C =< 16#5B)
+         orelse (C >= 16#5D andalso C =< 16#7E)
+        )).
 
 %% @type proplist() = [{Key::string(), Value::string()}].
 %% @type header() = {Name::string(), Value::string()}.
@@ -222,7 +227,7 @@ read_value(String) ->
     {"", String}.
 
 read_value_(String) ->
-    F = fun (C) -> ?IS_COOKIE_VAL_ALLOWED(C) end,
+    F = fun (C) -> ?IS_COOKIE_OCTET(C) end,
     lists:splitwith(F, String).
 
 read_quoted([?QUOTE | String]) ->


[couchdb-mochiweb] 20/37: Remove compile(tuple_calls) from mochiweb_response

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 6a8a8282d3b5390eca33ae54047f4a08f5fe8d9f
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:53:33 2019 +0000

    Remove compile(tuple_calls) from mochiweb_response
---
 src/mochiweb_response.erl | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/src/mochiweb_response.erl b/src/mochiweb_response.erl
index dc9569e..81325b5 100644
--- a/src/mochiweb_response.erl
+++ b/src/mochiweb_response.erl
@@ -24,8 +24,6 @@
 -module(mochiweb_response).
 -author('bob@mochimedia.com').
 
--compile(tuple_calls).
-
 -define(QUIP, "Any of you quaids got a smint?").
 
 -export([new/3, get_header_value/2, get/2, dump/1]).
@@ -56,26 +54,26 @@ get(headers, {?MODULE, [_Request, _Code, Headers]}) ->
 %% @spec dump(response()) -> {mochiweb_request, [{atom(), term()}]}
 %% @doc Dump the internal representation to a "human readable" set of terms
 %%      for debugging/inspection purposes.
-dump({?MODULE, [Request, Code, Headers]}) ->
-    [{request, Request:dump()},
+dump({?MODULE, [{ReqM, _} = Request, Code, Headers]}) ->
+    [{request, ReqM:dump(Request)},
      {code, Code},
      {headers, mochiweb_headers:to_list(Headers)}].
 
 %% @spec send(iodata(), response()) -> ok
 %% @doc Send data over the socket if the method is not HEAD.
-send(Data, {?MODULE, [Request, _Code, _Headers]}) ->
-    case Request:get(method) of
+send(Data, {?MODULE, [{ReqM, _} = Request, _Code, _Headers]}) ->
+    case ReqM:get(method, Request) of
         'HEAD' ->
             ok;
         _ ->
-            Request:send(Data)
+            ReqM:send(Data, Request)
     end.
 
 %% @spec write_chunk(iodata(), response()) -> ok
 %% @doc Write a chunk of a HTTP chunked response. If Data is zero length,
 %%      then the chunked response will be finished.
-write_chunk(Data, {?MODULE, [Request, _Code, _Headers]}=THIS) ->
-    case Request:get(version) of
+write_chunk(Data, {?MODULE, [{ReqM, _} = Request, _Code, _Headers]}=THIS) ->
+    case ReqM:get(version, Request) of
         Version when Version >= {1, 1} ->
             Length = iolist_size(Data),
             send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS);


[couchdb-mochiweb] 17/37: Remove compile(tuple_calls) from mochiweb_http

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 75d884904a858c85abb1389ac84e4fb9cf0e474a
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:43:12 2019 +0000

    Remove compile(tuple_calls) from mochiweb_http
---
 src/mochiweb_http.erl | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/mochiweb_http.erl b/src/mochiweb_http.erl
index a4bfa9e..6854b6a 100644
--- a/src/mochiweb_http.erl
+++ b/src/mochiweb_http.erl
@@ -28,8 +28,6 @@
 -export([after_response/2, reentry/1]).
 -export([parse_range_request/1, range_skip_length/2]).
 
--compile(tuple_calls).
-
 -define(REQUEST_RECV_TIMEOUT, 300000).   %% timeout waiting for request line
 -define(HEADERS_RECV_TIMEOUT, 30000).    %% timeout waiting for headers
 
@@ -76,7 +74,7 @@ start_link(Options) ->
     ok = ensure_started(mochiweb_clock),
     mochiweb_socket_server:start_link(parse_options(Options)).
 
-ensure_started(M) ->
+ensure_started(M) when is_atom(M) ->
     case M:start() of
         {ok, _Pid} ->
             ok;
@@ -140,9 +138,9 @@ headers(Socket, Opts, Request, Headers, Body, HeaderCount) ->
         exit(normal)
     end.
 
-call_body({M, F, A}, Req) ->
+call_body({M, F, A}, Req) when is_atom(M) ->
     erlang:apply(M, F, [Req | A]);
-call_body({M, F}, Req) ->
+call_body({M, F}, Req) when is_atom(M) ->
     M:F(Req);
 call_body(Body, Req) ->
     Body(Req).
@@ -164,8 +162,8 @@ handle_invalid_msg_request(Msg, Socket, Opts, Request, RevHeaders) ->
 
 -spec handle_invalid_request(term(), term(), term(), term()) -> no_return().
 handle_invalid_request(Socket, Opts, Request, RevHeaders) ->
-    Req = new_request(Socket, Opts, Request, RevHeaders),
-    Req:respond({400, [], []}),
+    {ReqM, _} = Req = new_request(Socket, Opts, Request, RevHeaders),
+    ReqM:respond({400, [], []}, Req),
     mochiweb_socket:close(Socket),
     exit(normal).
 
@@ -173,14 +171,14 @@ new_request(Socket, Opts, Request, RevHeaders) ->
     ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, raw}])),
     mochiweb:new_request({Socket, Opts, Request, lists:reverse(RevHeaders)}).
 
-after_response(Body, Req) ->
-    Socket = Req:get(socket),
-    case Req:should_close() of
+after_response(Body, {ReqM, _} = Req) ->
+    Socket = ReqM:get(socket, Req),
+    case ReqM:should_close(Req) of
         true ->
             mochiweb_socket:close(Socket),
             exit(normal);
         false ->
-            Req:cleanup(),
+            ReqM:cleanup(Req),
             erlang:garbage_collect(),
             ?MODULE:loop(Socket, mochiweb_request:get(opts, Req), Body)
     end.


[couchdb-mochiweb] 24/37: Remove compile(tuple_calls) from examples/https_store

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 78f5e15d116bd21ff52c01451199494eea47e9b5
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Mon Mar 11 22:55:44 2019 +0000

    Remove compile(tuple_calls) from examples/https_store
---
 examples/https/https_store.erl | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/examples/https/https_store.erl b/examples/https/https_store.erl
index 23e2447..719f206 100644
--- a/examples/https/https_store.erl
+++ b/examples/https/https_store.erl
@@ -34,8 +34,6 @@
 
 -module(https_store).
 
--compile(tuple_calls).
-
 -export([start/0,
          stop/0,
          dispatch/1,
@@ -77,7 +75,7 @@ stop() ->
     ok.
 
 dispatch(Req) ->
-    case Req:get(method) of
+    case mochiweb_request:get(method, Req) of
         'GET' ->
             get_resource(Req);
         'PUT' ->
@@ -86,41 +84,41 @@ dispatch(Req) ->
             delete_resource(Req);
         _ ->
             Headers = [{"Allow", "GET,PUT,DELETE"}],
-            Req:respond({405, Headers, "405 Method Not Allowed\r\n"})
+            mochiweb_request:respond({405, Headers, "405 Method Not Allowed\r\n"}, Req)
     end.
 
 get_resource(Req) ->
-    Path = Req:get(path),
+    Path = mochiweb_request:get(path, Req),
     case ets:lookup(?MODULE, Path) of
         [{Path, #resource{type=Type, data=Data}}] ->
-            Req:ok({Type, Data});
+            mochiweb_request:ok({Type, Data}, Req);
         [] ->
-            Req:respond({404, [], "404 Not Found\r\n"})
+            mochiweb_request:respond({404, [], "404 Not Found\r\n"}, Req)
     end.
 
 put_resource(Req) ->
-    ContentType = case Req:get_header_value("Content-Type") of
+    ContentType = case mochiweb_request:get_header_value("Content-Type", Req) of
         undefined ->
             "application/octet-stream";
         S ->
             S
     end,
-    Resource = #resource{type=ContentType, data=Req:recv_body()},
-    http_store ! {self(), {put, Req:get(path), Resource}},
+    Resource = #resource{type=ContentType, data=mochiweb_request:recv_body(Req)},
+    http_store ! {self(), {put, mochiweb_request:get(path, Req), Resource}},
     Pid = whereis(http_store),
     receive
         {Pid, created} ->
-            Req:respond({201, [], "201 Created\r\n"});
+            mochiweb_request:respond({201, [], "201 Created\r\n"}, Req);
         {Pid, updated} ->
-            Req:respond({200, [], "200 OK\r\n"})
+            mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
     end.
 
 delete_resource(Req) ->
-    http_store ! {self(), {delete, Req:get(path)}},
+    http_store ! {self(), {delete, mochiweb_request:get(path, Req)}},
     Pid = whereis(http_store),
     receive
         {Pid, ok} ->
-            Req:respond({200, [], "200 OK\r\n"})
+            mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
     end.
 
 loop(#sd{http=Http, https=Https} = SD) ->


[couchdb-mochiweb] 02/37: Allow setting {buffer, Buffer} socket server option

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 7e6f4ef7782f2e7403768732225673df820aa456
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Thu Dec 13 17:48:08 2018 -0500

    Allow setting {buffer, Buffer} socket server option
    
    If `recbuf` is `undefined` then buffer size is set explicitly to the
    previous `recbuf` default of 8192.
    
    The recent option `{recbuf, undefined}` to allow sockets to pick up optimal OS
    default kernel buffer sizes inadvertently reset Erlang's userland buffer size
    to a default value of 1460. This buffer size, due to a longstanding bug in
    Erlang http parser, limits the maximum URL line that can be parsed by the
    {packet, http} socket option, and so breaks existing code.
    
    For example this shows how recbuf also sets buffer size:
    
    ```
    > f(), SockInfo = fun(S) -> inet:getopts(S, [recbuf, buffer]) end, {ok, LS} = gen_tcp:listen(0, [{recbuf, 8192}]), LRes = SockInfo(LS).
    {ok,[{recbuf,8192},{buffer,8192}]}
    ```
    
    Not setting recbuf resets buffer size to 1460:
    
    ```
    f(), SockInfo = fun(S) -> inet:getopts(S, [recbuf, buffer]) end, {ok, LS} = gen_tcp:listen(0, []), LRes = SockInfo(LS).
    {ok,[{recbuf,131072},{buffer,1460}]}
    ```
    
    References:
    
     https://github.com/apache/couchdb/issues/1810
     http://erlang.org/pipermail/erlang-questions/2011-June/059571.html
     http://erlang.org/doc/man/inet.html#setopts-2
---
 src/mochiweb_socket_server.erl | 46 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/mochiweb_socket_server.erl b/src/mochiweb_socket_server.erl
index 7a9b0d3..56c1243 100644
--- a/src/mochiweb_socket_server.erl
+++ b/src/mochiweb_socket_server.erl
@@ -23,6 +23,7 @@
          listen=null,
          nodelay=false,
          recbuf=?RECBUF_SIZE,
+         buffer=undefined,
          backlog=128,
          active_sockets=0,
          acceptor_pool_size=16,
@@ -132,6 +133,15 @@ parse_options([{recbuf, RecBuf} | Rest], State) when is_integer(RecBuf) orelse
     %% In case undefined is passed instead of the default buffer
     %% size ?RECBUF_SIZE, no size is set and the OS can control it dynamically
     parse_options(Rest, State#mochiweb_socket_server{recbuf=RecBuf});
+parse_options([{buffer, Buffer} | Rest], State) when is_integer(Buffer) orelse
+                                                Buffer == undefined ->
+    %% `buffer` sets Erlang's userland socket buffer size. The size of this
+    %% buffer affects the maximum URL path that can be parsed. URL sizes that
+    %% are larger than this plus the size of the HTTP verb and some whitespace
+    %% will result in an `emsgsize` TCP error.
+    %%
+    %% If this value is not set Erlang sets it to 1460 which might be too low.
+    parse_options(Rest, State#mochiweb_socket_server{buffer=Buffer});
 parse_options([{acceptor_pool_size, Max} | Rest], State) ->
     MaxInt = ensure_int(Max),
     parse_options(Rest,
@@ -179,7 +189,8 @@ ipv6_supported() ->
     end.
 
 init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog,
-                                   nodelay=NoDelay, recbuf=RecBuf}) ->
+                                   nodelay=NoDelay, recbuf=RecBuf,
+                                   buffer=Buffer}) ->
     process_flag(trap_exit, true),
 
     BaseOpts = [binary,
@@ -200,14 +211,28 @@ init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog,
         {_, _, _, _, _, _, _, _} -> % IPv6
             [inet6, {ip, Ip} | BaseOpts]
     end,
-    OptsBuf=case RecBuf of
-        undefined ->
-            Opts;
-        _ ->
-            [{recbuf, RecBuf}|Opts]
-    end,
+    OptsBuf = set_buffer_opts(RecBuf, Buffer, Opts),
     listen(Port, OptsBuf, State).
 
+
+set_buffer_opts(undefined, undefined, Opts) ->
+    % If recbuf is undefined, user space buffer is set to the default 1460
+    % value. That unexpectedly break the {packet, http} parser and any URL
+    % lines longer than 1460 would error out with emsgsize. So when recbuf is
+    % undefined, use previous value of recbuf for buffer in order to keep older
+    % code from breaking.
+    [{buffer, ?RECBUF_SIZE} | Opts];
+set_buffer_opts(RecBuf, undefined, Opts) ->
+    [{recbuf, RecBuf} | Opts];
+set_buffer_opts(undefined, Buffer, Opts) ->
+    [{buffer, Buffer} | Opts];
+set_buffer_opts(RecBuf, Buffer, Opts) ->
+    % Note: order matters, recbuf will override buffer unless buffer value
+    % comes first, except on older versions of Erlang (ex. 17.0) where it works
+    % exactly the opposite.
+    [{buffer, Buffer}, {recbuf, RecBuf} | Opts].
+
+
 new_acceptor_pool(State=#mochiweb_socket_server{acceptor_pool_size=Size}) ->
     lists:foldl(fun (_, S) -> new_acceptor(S) end, State, lists:seq(1, Size)).
 
@@ -391,4 +416,11 @@ upgrade_state_test() ->
                                        profile_fun=undefined},
     ?assertEqual(CmpState, State).
 
+
+set_buffer_opts_test() ->
+    ?assertEqual([{buffer, 8192}], set_buffer_opts(undefined, undefined, [])),
+    ?assertEqual([{recbuf, 5}], set_buffer_opts(5, undefined, [])),
+    ?assertEqual([{buffer, 6}], set_buffer_opts(undefined, 6, [])),
+    ?assertEqual([{buffer, 6}, {recbuf, 5}], set_buffer_opts(5, 6, [])).
+
 -endif.


[couchdb-mochiweb] 05/37: Conditional ssl:handshake/2

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 105c9cb1af15dafcdc393cce04ffac65305e91dd
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Thu Jan 10 12:16:29 2019 -0800

    Conditional ssl:handshake/2
---
 rebar.config            |  3 ++-
 src/mochiweb_socket.erl | 12 ++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/rebar.config b/rebar.config
index adc1d78..0c6180d 100644
--- a/rebar.config
+++ b/rebar.config
@@ -4,7 +4,8 @@
             {platform_define, "^(R14|R15|R16B-)", 'crypto_compatibility'},
             {platform_define, "^(R14|R15|R16B|17)", 'rand_mod_unavailable'},
             {platform_define, "^(R14|R15|R16B|17)", 'sni_unavailable'},
-            {platform_define, "^(R14|R15|R16)", 'map_unavailable'}]}.
+            {platform_define, "^(R14|R15|R16)", 'map_unavailable'},
+            {platform_define, "^(R14|R15|R16|17|18|19|20)", 'ssl_handshake_unavailable'}]}.
 {cover_enabled, true}.
 {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.
 {dialyzer_opts, [{warnings, [no_return,
diff --git a/src/mochiweb_socket.erl b/src/mochiweb_socket.erl
index 8dc1b9d..9aeca2a 100644
--- a/src/mochiweb_socket.erl
+++ b/src/mochiweb_socket.erl
@@ -87,6 +87,17 @@ transport_accept({ssl, ListenSocket}) ->
 transport_accept(ListenSocket) ->
     gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT).
 
+-ifdef(ssl_handshake_unavailable).
+finish_accept({ssl, Socket}) ->
+    case ssl:ssl_accept(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
+        ok ->
+            {ok, {ssl, Socket}};
+        {error, _} = Err ->
+            Err
+    end;
+finish_accept(Socket) ->
+    {ok, Socket}.
+-else.
 finish_accept({ssl, Socket}) ->
     case ssl:handshake(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
         {ok, SslSocket} ->
@@ -96,6 +107,7 @@ finish_accept({ssl, Socket}) ->
     end;
 finish_accept(Socket) ->
     {ok, Socket}.
+-endif.
 
 recv({ssl, Socket}, Length, Timeout) ->
     ssl:recv(Socket, Length, Timeout);


[couchdb-mochiweb] 09/37: Confirmed that 21.2.3 is compatible

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit b39178ebb7c79c380852bc8f1781d6ff0d162981
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Wed Jan 16 09:38:25 2019 -0800

    Confirmed that 21.2.3 is compatible
---
 .travis.yml | 2 +-
 README.md   | 7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 8c8d1d2..18bf781 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ language: erlang
 notifications:
   email: false
 otp_release:
-  - 21.2
+  - 21.2.3
   - 21.1
   - 21.0
   - 20.0
diff --git a/README.md b/README.md
index d39374a..74e6620 100644
--- a/README.md
+++ b/README.md
@@ -10,11 +10,10 @@ To create a new mochiweb using project:
 To create a new mochiweb using project in a specific directory:
    make app PROJECT=project_name PREFIX=$HOME/projects/
 
-MochiWeb is currently tested with Erlang/OTP R15B03 through 21.1.
+MochiWeb is currently tested with Erlang/OTP R15B03 through 21.2.3.
 
-# OTP 21.2 warning
+# OTP 21.2, 21.2.1, 21.2.2 warning
 
 OTP 21.2 (up to and including 21.2.2) introduced an SSL regression that
 makes these releases unsafe to use. See [ERL-830](https://bugs.erlang.org/browse/ERL-830).
-This issue has been fixed in the maintenance branch but a release is not
-yet available.
+This issue was resolved in OTP 21.2.3.


[couchdb-mochiweb] 06/37: Add a runtime SSL compatibility check for OTP 21 releases

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit ea863d77c0e24c0f2d555fb23fd9a9077f91387f
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Jan 15 15:08:21 2019 -0800

    Add a runtime SSL compatibility check for OTP 21 releases
---
 rebar.config                   |  3 ++-
 src/mochiweb_socket_server.erl | 17 ++++++++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/rebar.config b/rebar.config
index 0c6180d..2fc417e 100644
--- a/rebar.config
+++ b/rebar.config
@@ -5,7 +5,8 @@
             {platform_define, "^(R14|R15|R16B|17)", 'rand_mod_unavailable'},
             {platform_define, "^(R14|R15|R16B|17)", 'sni_unavailable'},
             {platform_define, "^(R14|R15|R16)", 'map_unavailable'},
-            {platform_define, "^(R14|R15|R16|17|18|19|20)", 'ssl_handshake_unavailable'}]}.
+            {platform_define, "^(R14|R15|R16|17|18|19|20)", 'ssl_handshake_unavailable'},
+            {platform_define, "^21-", 'otp_21'}]}.
 {cover_enabled, true}.
 {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.
 {dialyzer_opts, [{warnings, [no_return,
diff --git a/src/mochiweb_socket_server.erl b/src/mochiweb_socket_server.erl
index 56c1243..f830483 100644
--- a/src/mochiweb_socket_server.erl
+++ b/src/mochiweb_socket_server.erl
@@ -167,11 +167,26 @@ start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) ->
             gen_server:F(Name, ?MODULE, State, [])
     end.
 
+-ifdef(otp_21).
+check_ssl_compatibility() ->
+    case lists:keyfind(ssl, 1, application:loaded_applications()) of
+        {_, _, V} when V =:= "9.1" orelse V =:= "9.1.1" ->
+            {error, "ssl-" ++ V ++ " (OTP 21.2 to 21.2.2) has a regression and is not safe to use with mochiweb. See https://bugs.erlang.org/browse/ERL-830"};
+        _ ->
+            ok
+    end.
+-else.
+check_ssl_compatibility() ->
+    ok.
+-endif.
+
 prep_ssl(true) ->
     ok = mochiweb:ensure_started(crypto),
     ok = mochiweb:ensure_started(asn1),
     ok = mochiweb:ensure_started(public_key),
-    ok = mochiweb:ensure_started(ssl);
+    ok = mochiweb:ensure_started(ssl),
+    ok = check_ssl_compatibility(),
+    ok;
 prep_ssl(false) ->
     ok.
 


[couchdb-mochiweb] 04/37: Use ssl:handshake/2 unconditionally to see when it is first available

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 5e0645545a7b9c5c00bdf0b4b889d5eb0a427fdc
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Thu Jan 10 12:09:24 2019 -0800

    Use ssl:handshake/2 unconditionally to see when it is first available
---
 src/mochiweb_socket.erl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/mochiweb_socket.erl b/src/mochiweb_socket.erl
index cbce78a..8dc1b9d 100644
--- a/src/mochiweb_socket.erl
+++ b/src/mochiweb_socket.erl
@@ -88,9 +88,9 @@ transport_accept(ListenSocket) ->
     gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT).
 
 finish_accept({ssl, Socket}) ->
-    case ssl:ssl_accept(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
-        ok ->
-            {ok, {ssl, Socket}};
+    case ssl:handshake(Socket, ?SSL_HANDSHAKE_TIMEOUT) of
+        {ok, SslSocket} ->
+            {ok, {ssl, SslSocket}};
         {error, _} = Err ->
             Err
     end;


[couchdb-mochiweb] 35/37: Use https for URLs in README.md

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit a7e09cd6d937d2d6d22b872e672da8514a5adfbb
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue May 21 20:41:21 2019 -0700

    Use https for URLs in README.md
---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 673e384..44e392b 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
 MochiWeb is an Erlang library for building lightweight HTTP servers.
 
-The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
+The latest version of MochiWeb is available at https://github.com/mochi/mochiweb
 
-The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
+The mailing list for MochiWeb is at https://groups.google.com/group/mochiweb/
 
-Erlang OTP is required for setting up the MochiWeb environment and is available at http://www.erlang.org/
+Erlang OTP is required for setting up the MochiWeb environment and is available at https://www.erlang.org/
 
 To create a new mochiweb using project:
    make app PROJECT=project_name


[couchdb-mochiweb] 31/37: Update README.md

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 2eb68af635aef7d6cbc439d4e6f61e08ab37563c
Author: penhs <46...@users.noreply.github.com>
AuthorDate: Tue May 21 17:24:46 2019 -0700

    Update README.md
---
 README.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/README.md b/README.md
index 74e6620..3f00b31 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,18 @@ The latest version of MochiWeb is available at http://github.com/mochi/mochiweb
 
 The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/
 
+Required for setting up the MochiWeb environment:
+   Erlang OTP: http://www.erlang.org/
+
 To create a new mochiweb using project:
    make app PROJECT=project_name
 
 To create a new mochiweb using project in a specific directory:
    make app PROJECT=project_name PREFIX=$HOME/projects/
 
+Information about Rebar (Erlang build tool): 
+   https://github.com/rebar/rebar
+
 MochiWeb is currently tested with Erlang/OTP R15B03 through 21.2.3.
 
 # OTP 21.2, 21.2.1, 21.2.2 warning


[couchdb-mochiweb] 36/37: add support for SameSite=none in cookies

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit f2b90b9f0b449c391dc328842ff1ee4cfc053d63
Author: Anthony Molinaro <an...@openx.com>
AuthorDate: Fri Jul 12 22:00:34 2019 +0000

    add support for SameSite=none in cookies
---
 src/mochiweb_cookies.erl | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/mochiweb_cookies.erl b/src/mochiweb_cookies.erl
index c7b0fcf..dd28610 100644
--- a/src/mochiweb_cookies.erl
+++ b/src/mochiweb_cookies.erl
@@ -65,7 +65,7 @@ cookie(Key, Value) ->
 %% where Option = {max_age, int_seconds()} | {local_time, {date(), time()}}
 %%                | {domain, string()} | {path, string()}
 %%                | {secure, true | false} | {http_only, true | false}
-%%                | {same_site, lax | strict}
+%%                | {same_site, lax | strict | none}
 %%
 %% @doc Generate a Set-Cookie header field tuple.
 cookie(Key, Value, Options) ->
@@ -130,7 +130,9 @@ cookie(Key, Value, Options) ->
             lax ->
                 "; SameSite=Lax";
             strict ->
-                "; SameSite=Strict"
+                "; SameSite=Strict";
+            none ->
+                "; SameSite=None"
         end,
     CookieParts = [Cookie, ExpiresPart, SecurePart, DomainPart, PathPart,
         HttpOnlyPart, SameSitePart],
@@ -378,6 +380,18 @@ cookie_test() ->
           "Max-Age=86417"},
     C3 = cookie("Customer", "WILE_E_COYOTE",
                 [{max_age, 86417}, {local_time, LocalTime}]),
+
+    % test various values for SameSite
+    %
+    % unset default to nothing
+    C4 = {"Set-Cookie","i=test123; Version=1"},
+    C4 = cookie("i", "test123", []),
+    C5 = {"Set-Cookie","i=test123; Version=1; SameSite=Strict"},
+    C5 = cookie("i", "test123", [ {same_site, strict}]),
+    C6 = {"Set-Cookie","i=test123; Version=1; SameSite=Lax"},
+    C6 = cookie("i", "test123", [ {same_site, lax}]),
+    C7 = {"Set-Cookie","i=test123; Version=1; SameSite=None"},
+    C7 = cookie("i", "test123", [ {same_site, none}]),
     ok.
 
 -endif.


[couchdb-mochiweb] 33/37: Debug Travis, it seems like older releases are not working

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 80739b78887470f635d3057fad27c532ac28badb
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue May 21 20:24:56 2019 -0700

    Debug Travis, it seems like older releases are not working
---
 .travis.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 18bf781..eb26c04 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,3 +12,5 @@ otp_release:
   - 17.5
   - R16B03-1
   - R15B03
+before_script:
+  - kerl list installations


[couchdb-mochiweb] 30/37: Run erl_tidy on modified source files

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 3d3f929a99abcbcd75f2e32e6eb1ee2c8c3b075f
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Mar 12 03:49:26 2019 +0000

    Run erl_tidy on modified source files
    
    ```erlang
    lists:foreach(
      fun (F) -> erl_tidy:file(F, [{backups, false}, keep_unused]) end,
      string:split(
        string:trim(
          os:cmd("git diff --name-only origin/master | grep \".erl$\"")
        ),
        "\n",
        all
      )
    ).
    ```
---
 examples/hmac_api/hmac_api_lib.erl                 |  354 +++---
 examples/https/https_store.erl                     |  142 +--
 examples/keepalive/keepalive.erl                   |   72 +-
 src/mochifmt.erl                                   |  405 ++++---
 src/mochiweb_acceptor.erl                          |   61 +-
 src/mochiweb_http.erl                              |  366 +++---
 src/mochiweb_multipart.erl                         | 1237 ++++++++++---------
 src/mochiweb_request.erl                           | 1280 ++++++++++++--------
 src/mochiweb_response.erl                          |   37 +-
 src/mochiweb_websocket.erl                         |  287 +++--
 .../mochiwebapp_skel/src/mochiapp_web.erl          |   79 +-
 test/mochiweb_http_tests.erl                       |   50 +-
 test/mochiweb_request_tests.erl                    |  292 +++--
 test/mochiweb_tests.erl                            |  244 ++--
 test/mochiweb_websocket_tests.erl                  |  189 +--
 15 files changed, 2741 insertions(+), 2354 deletions(-)

diff --git a/examples/hmac_api/hmac_api_lib.erl b/examples/hmac_api/hmac_api_lib.erl
index 4c26f2f..1dae62d 100644
--- a/examples/hmac_api/hmac_api_lib.erl
+++ b/examples/hmac_api/hmac_api_lib.erl
@@ -1,6 +1,7 @@
 -module(hmac_api_lib).
 
 -include("hmac_api.hrl").
+
 -include_lib("eunit/include/eunit.hrl").
 
 -author("Hypernumbers Ltd <go...@hypernumbers.com>").
@@ -21,11 +22,8 @@
 %%%
 %%% THE AMAZON API MUNGES HOSTNAME AND PATHS IN A CUSTOM WAY
 %%% THIS IMPLEMENTATION DOESN'T
--export([
-         authorize_request/1,
-         sign/5,
-         get_api_keypair/0
-        ]).
+-export([authorize_request/1, get_api_keypair/0,
+	 sign/5]).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%%                                                                          %%%
@@ -34,27 +32,27 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 authorize_request(Req) ->
-    Method      = mochiweb_request:get(method, Req),
-    Path        = mochiweb_request:get(path, Req),
-    Headers     = normalise(mochiweb_headers:to_list(mochiweb_request:get(headers, Req))),
-    ContentMD5  = get_header(Headers, "content-md5"),
+    Method = mochiweb_request:get(method, Req),
+    Path = mochiweb_request:get(path, Req),
+    Headers =
+	normalise(mochiweb_headers:to_list(mochiweb_request:get(headers,
+								Req))),
+    ContentMD5 = get_header(Headers, "content-md5"),
     ContentType = get_header(Headers, "content-type"),
-    Date        = get_header(Headers, "date"),
-    IncAuth     = get_header(Headers, "authorization"),
+    Date = get_header(Headers, "date"),
+    IncAuth = get_header(Headers, "authorization"),
     {_Schema, _PublicKey, _Sig} = breakout(IncAuth),
     %% normally you would use the public key to look up the private key
-    PrivateKey  = ?privatekey,
+    PrivateKey = (?privatekey),
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = Path},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = Path},
     Signed = sign_data(PrivateKey, Signature),
     {_, AuthHeader} = make_HTTPAuth_header(Signed),
     case AuthHeader of
-        IncAuth -> "match";
-        _       -> "no_match"
+      IncAuth -> "match";
+      _ -> "no_match"
     end.
 
 sign(PrivateKey, Method, URL, Headers, ContentType) ->
@@ -62,15 +60,12 @@ sign(PrivateKey, Method, URL, Headers, ContentType) ->
     ContentMD5 = get_header(Headers2, "content-md5"),
     Date = get_header(Headers2, "date"),
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     SignedSig = sign_data(PrivateKey, Signature),
     make_HTTPAuth_header(SignedSig).
 
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%%                                                                          %%%
 %%% Internal Functions                                                       %%%
@@ -83,22 +78,30 @@ breakout(Header) ->
     {Schema, PublicKey, Signature}.
 
 get_api_keypair() ->
-    Public  = mochihex:to_hex(binary_to_list(crypto:strong_rand_bytes(16))),
-    Private = mochihex:to_hex(binary_to_list(crypto:strong_rand_bytes(16))),
+    Public =
+	mochihex:to_hex(binary_to_list(crypto:strong_rand_bytes(16))),
+    Private =
+	mochihex:to_hex(binary_to_list(crypto:strong_rand_bytes(16))),
     {Public, Private}.
 
 make_HTTPAuth_header(Signature) ->
-    {"Authorization", ?schema ++ " "
-     ++ ?publickey ++ ":" ++ Signature}.
+    {"Authorization",
+     (?schema) ++ " " ++ (?publickey) ++ ":" ++ Signature}.
 
 make_signature_string(#hmac_signature{} = S) ->
-    Date = get_date(S#hmac_signature.headers, S#hmac_signature.date),
-    string:to_upper(atom_to_list(S#hmac_signature.method)) ++ "\n"
-        ++ S#hmac_signature.contentmd5 ++ "\n"
-        ++ S#hmac_signature.contenttype ++ "\n"
-        ++ Date ++ "\n"
-        ++ canonicalise_headers(S#hmac_signature.headers)
-        ++ canonicalise_resource(S#hmac_signature.resource).
+    Date = get_date(S#hmac_signature.headers,
+		    S#hmac_signature.date),
+    string:to_upper(atom_to_list(S#hmac_signature.method))
+      ++
+      "\n" ++
+	S#hmac_signature.contentmd5 ++
+	  "\n" ++
+	    S#hmac_signature.contenttype ++
+	      "\n" ++
+		Date ++
+		  "\n" ++
+		    canonicalise_headers(S#hmac_signature.headers) ++
+		      canonicalise_resource(S#hmac_signature.resource).
 
 sign_data(PrivateKey, #hmac_signature{} = Signature) ->
     Str = make_signature_string(Signature),
@@ -109,35 +112,41 @@ sign_data(PrivateKey, #hmac_signature{} = Signature) ->
 %% yer Donald is well and truly Ducked so ye may as weel test it...
 sign2(PrivateKey, Str) ->
     Sign = xmerl_ucs:to_utf8(Str),
-    binary_to_list(base64:encode(crypto:sha_mac(PrivateKey, Sign))).
+    binary_to_list(base64:encode(crypto:sha_mac(PrivateKey,
+						Sign))).
 
 canonicalise_headers([]) -> "\n";
 canonicalise_headers(List) when is_list(List) ->
-    List2 = [{string:to_lower(K), V} || {K, V} <- lists:sort(List)],
+    List2 = [{string:to_lower(K), V}
+	     || {K, V} <- lists:sort(List)],
     c_headers2(consolidate(List2, []), []).
 
-c_headers2([], Acc)       -> string:join(Acc, "\n") ++ "\n";
-c_headers2([{?headerprefix ++ Rest, Key} | T], Acc) ->
-    Hd = string:strip(?headerprefix ++ Rest) ++ ":" ++ string:strip(Key),
+c_headers2([], Acc) -> string:join(Acc, "\n") ++ "\n";
+c_headers2([{(?headerprefix) ++ Rest, Key} | T], Acc) ->
+    Hd = string:strip((?headerprefix) ++ Rest) ++
+	   ":" ++ string:strip(Key),
     c_headers2(T, [Hd | Acc]);
 c_headers2([_H | T], Acc) -> c_headers2(T, Acc).
 
-consolidate([H | []], Acc) -> [H | Acc];
+consolidate([H], Acc) -> [H | Acc];
 consolidate([{H, K1}, {H, K2} | Rest], Acc) ->
     consolidate([{H, join(K1, K2)} | Rest], Acc);
 consolidate([{H1, K1}, {H2, K2} | Rest], Acc) ->
-    consolidate([{rectify(H2), rectify(K2)} | Rest], [{H1, K1} | Acc]).
+    consolidate([{rectify(H2), rectify(K2)} | Rest],
+		[{H1, K1} | Acc]).
 
 join(A, B) -> string:strip(A) ++ ";" ++ string:strip(B).
 
 %% removes line spacing as per RFC 2616 Section 4.2
 rectify(String) ->
-    Re = "[\x20* | \t*]+",
+    Re = "[ * | \t*]+",
     re:replace(String, Re, " ", [{return, list}, global]).
 
-canonicalise_resource("http://"  ++ Rest) -> c_res2(Rest);
-canonicalise_resource("https://" ++ Rest) -> c_res2(Rest);
-canonicalise_resource(X)                  -> c_res3(X).
+canonicalise_resource("http://" ++ Rest) ->
+    c_res2(Rest);
+canonicalise_resource("https://" ++ Rest) ->
+    c_res2(Rest);
+canonicalise_resource(X) -> c_res3(X).
 
 c_res2(Rest) ->
     N = string:str(Rest, "/"),
@@ -146,15 +155,15 @@ c_res2(Rest) ->
 
 c_res3(Tail) ->
     URL = case string:str(Tail, "#") of
-              0 -> Tail;
-              N -> {U, _Anchor} = lists:split(N, Tail),
-                   U
-          end,
+	    0 -> Tail;
+	    N -> {U, _Anchor} = lists:split(N, Tail), U
+	  end,
     U3 = case string:str(URL, "?") of
-             0  -> URL;
-             N2 -> {U2, Q} = lists:split(N2, URL),
-                   U2 ++ canonicalise_query(Q)
-         end,
+	   0 -> URL;
+	   N2 ->
+	       {U2, Q} = lists:split(N2, URL),
+	       U2 ++ canonicalise_query(Q)
+	 end,
     string:to_lower(U3).
 
 canonicalise_query(List) ->
@@ -163,11 +172,12 @@ canonicalise_query(List) ->
     string:join(lists:sort(List2), "&").
 
 %% if there's a header date take it and ditch the date
-get_date([], Date)            -> Date;
-get_date([{K, _V} | T], Date) -> case string:to_lower(K) of
-                                     ?dateheader -> [];
-                                     _           ->  get_date(T, Date)
-                                 end.
+get_date([], Date) -> Date;
+get_date([{K, _V} | T], Date) ->
+    case string:to_lower(K) of
+      ?dateheader -> [];
+      _ -> get_date(T, Date)
+    end.
 
 normalise(List) -> norm2(List, []).
 
@@ -178,11 +188,10 @@ norm2([H | T], Acc) -> norm2(T, [H | Acc]).
 
 get_header(Headers, Type) ->
     case lists:keyfind(Type, 1, Headers) of
-        false   -> [];
-        {_K, V} -> V
+      false -> [];
+      {_K, V} -> V
     end.
 
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %%%                                                                          %%%
 %%% Unit Tests                                                               %%%
@@ -190,10 +199,13 @@ get_header(Headers, Type) ->
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
                                                 % taken from Amazon docs
+
 %% http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
 hash_test1(_) ->
-    Sig = "DELETE\n\n\n\nx-amz-date:Tue, 27 Mar 2007 21:20:26 +0000\n/johnsmith/photos/puppy.jpg",
-    Key = ?privatekey,
+    Sig = "DELETE\n\n\n\nx-amz-date:Tue, 27 Mar "
+	  "2007 21:20:26 +0000\n/johnsmith/photos/puppy."
+	  "jpg",
+    Key = (?privatekey),
     Hash = sign2(Key, Sig),
     Expected = "k3nL7gH3+PadhTEVn5Ip83xlYzk=",
     ?assertEqual(Expected, Hash).
@@ -201,7 +213,8 @@ hash_test1(_) ->
 %% taken from Amazon docs
 %% http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
 hash_test2(_) ->
-    Sig = "GET\n\n\nTue, 27 Mar 2007 19:44:46 +0000\n/johnsmith/?acl",
+    Sig = "GET\n\n\nTue, 27 Mar 2007 19:44:46 +0000\n/jo"
+	  "hnsmith/?acl",
     Key = "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
     Hash = sign2(Key, Sig),
     Expected = "thdUi9VAkzhkniLj96JIrOPGi0g=",
@@ -210,8 +223,9 @@ hash_test2(_) ->
 %% taken from Amazon docs
 %% http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
 hash_test3(_) ->
-    Sig = "GET\n\n\nWed, 28 Mar 2007 01:49:49 +0000\n/dictionary/"
-        ++ "fran%C3%A7ais/pr%c3%a9f%c3%a8re",
+    Sig = "GET\n\n\nWed, 28 Mar 2007 01:49:49 +0000\n/di"
+	  "ctionary/"
+	    ++ "fran%C3%A7ais/pr%c3%a9f%c3%a8re",
     Key = "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o",
     Hash = sign2(Key, Sig),
     Expected = "dxhSBHoI6eVSPcXJqEghlUzZMnY=",
@@ -225,13 +239,12 @@ signature_test1(_) ->
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "POST\n\n\nSun, 10 Jul 2011 05:07:19 UTC\n\n/tongs/ya/bas",
+    Expected = "POST\n\n\nSun, 10 Jul 2011 05:07:19 "
+	       "UTC\n\n/tongs/ya/bas",
     ?assertEqual(Expected, Sig).
 
 signature_test2(_) ->
@@ -242,13 +255,13 @@ signature_test2(_) ->
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [{"x-amz-acl", "public-read"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz-acl:public-read\n/tongs/ya/bas",
+    Expected =
+	"GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz"
+	"-acl:public-read\n/tongs/ya/bas",
     ?assertEqual(Expected, Sig).
 
 signature_test3(_) ->
@@ -258,17 +271,17 @@ signature_test3(_) ->
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [{"x-amz-acl", "public-read"},
-               {"yantze", "blast-off"},
-               {"x-amz-doobie", "bongwater"},
-               {"x-amz-acl", "public-write"}],
+	       {"yantze", "blast-off"}, {"x-amz-doobie", "bongwater"},
+	       {"x-amz-acl", "public-write"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz-acl:public-read;public-write\nx-amz-doobie:bongwater\n/tongs/ya/bas",
+    Expected =
+	"GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz"
+	"-acl:public-read;public-write\nx-amz-doobie:b"
+	"ongwater\n/tongs/ya/bas",
     ?assertEqual(Expected, Sig).
 
 signature_test4(_) ->
@@ -278,17 +291,18 @@ signature_test4(_) ->
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [{"x-amz-acl", "public-read"},
-               {"yantze", "blast-off"},
-               {"x-amz-doobie  oobie \t boobie ", "bongwater"},
-               {"x-amz-acl", "public-write"}],
+	       {"yantze", "blast-off"},
+	       {"x-amz-doobie  oobie \t boobie ", "bongwater"},
+	       {"x-amz-acl", "public-write"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz-acl:public-read;public-write\nx-amz-doobie oobie boobie:bongwater\n/tongs/ya/bas",
+    Expected =
+	"GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz"
+	"-acl:public-read;public-write\nx-amz-doobie "
+	"oobie boobie:bongwater\n/tongs/ya/bas",
     ?assertEqual(Expected, Sig).
 
 signature_test5(_) ->
@@ -298,138 +312,122 @@ signature_test5(_) ->
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [{"x-amz-acl", "public-Read"},
-               {"yantze", "Blast-Off"},
-               {"x-amz-doobie  Oobie \t boobie ", "bongwater"},
-               {"x-amz-acl", "public-write"}],
+	       {"yantze", "Blast-Off"},
+	       {"x-amz-doobie  Oobie \t boobie ", "bongwater"},
+	       {"x-amz-acl", "public-write"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz-acl:public-Read;public-write\nx-amz-doobie oobie boobie:bongwater\n/tongs/ya/bas",
+    Expected =
+	"GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\nx-amz"
+	"-acl:public-Read;public-write\nx-amz-doobie "
+	"oobie boobie:bongwater\n/tongs/ya/bas",
     ?assertEqual(Expected, Sig).
 
 signature_test6(_) ->
-    URL = "http://example.com:90/tongs/ya/bas/?andy&zbish=bash&bosh=burp",
+    URL = "http://example.com:90/tongs/ya/bas/?andy&zbis"
+	  "h=bash&bosh=burp",
     Method = get,
     ContentMD5 = "",
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
     Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\n\n"
-        ++ "/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
+		 ++ "/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
     ?assertEqual(Expected, Sig).
 
 signature_test7(_) ->
-    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBish=Bash&bOsh=burp",
+    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBis"
+	  "h=Bash&bOsh=burp",
     Method = get,
     ContentMD5 = "",
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
     Headers = [],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
     Expected = "GET\n\n\nSun, 10 Jul 2011 05:07:19 UTC\n\n"
-        ++"/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
+		 ++ "/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
     ?assertEqual(Expected, Sig).
 
 signature_test8(_) ->
-    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBish=Bash&bOsh=burp",
+    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBis"
+	  "h=Bash&bOsh=burp",
     Method = get,
     ContentMD5 = "",
     ContentType = "",
     Date = "",
-    Headers = [{"x-aMz-daTe", "Tue, 27 Mar 2007 21:20:26 +0000"}],
+    Headers = [{"x-aMz-daTe",
+		"Tue, 27 Mar 2007 21:20:26 +0000"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\n\n"
-        ++"x-amz-date:Tue, 27 Mar 2007 21:20:26 +0000\n"
-        ++"/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
+    Expected = "GET\n\n\n\n" ++
+		 "x-amz-date:Tue, 27 Mar 2007 21:20:26 "
+		 "+0000\n"
+		   ++ "/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
     ?assertEqual(Expected, Sig).
 
 signature_test9(_) ->
-    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBish=Bash&bOsh=burp",
+    URL = "http://exAMPLE.Com:90/tONgs/ya/bas/?ANdy&ZBis"
+	  "h=Bash&bOsh=burp",
     Method = get,
     ContentMD5 = "",
     ContentType = "",
     Date = "Sun, 10 Jul 2011 05:07:19 UTC",
-    Headers = [{"x-amz-date", "Tue, 27 Mar 2007 21:20:26 +0000"}],
+    Headers = [{"x-amz-date",
+		"Tue, 27 Mar 2007 21:20:26 +0000"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = make_signature_string(Signature),
-    Expected = "GET\n\n\n\n"
-        ++"x-amz-date:Tue, 27 Mar 2007 21:20:26 +0000\n"
-        ++"/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
+    Expected = "GET\n\n\n\n" ++
+		 "x-amz-date:Tue, 27 Mar 2007 21:20:26 "
+		 "+0000\n"
+		   ++ "/tongs/ya/bas/?andy&bosh=burp&zbish=bash",
     ?assertEqual(Expected, Sig).
 
 amazon_test1(_) ->
-    URL = "http://exAMPLE.Com:90/johnsmith/photos/puppy.jpg",
+    URL =
+	"http://exAMPLE.Com:90/johnsmith/photos/puppy.jpg",
     Method = delete,
     ContentMD5 = "",
     ContentType = "",
     Date = "",
-    Headers = [{"x-amz-date", "Tue, 27 Mar 2007 21:20:26 +0000"}],
+    Headers = [{"x-amz-date",
+		"Tue, 27 Mar 2007 21:20:26 +0000"}],
     Signature = #hmac_signature{method = Method,
-                                contentmd5 = ContentMD5,
-                                contenttype = ContentType,
-                                date = Date,
-                                headers = Headers,
-                                resource = URL},
+				contentmd5 = ContentMD5,
+				contenttype = ContentType, date = Date,
+				headers = Headers, resource = URL},
     Sig = sign_data(?privatekey, Signature),
     Expected = "k3nL7gH3+PadhTEVn5Ip83xlYzk=",
     ?assertEqual(Expected, Sig).
 
 unit_test_() ->
-    Setup   = fun() -> ok end,
-    Cleanup = fun(_) -> ok end,
-
-    Series1 = [
-               fun hash_test1/1,
-               fun hash_test2/1,
-               fun hash_test3/1
-              ],
-
-    Series2 = [
-               fun signature_test1/1,
-               fun signature_test2/1,
-               fun signature_test3/1,
-               fun signature_test4/1,
-               fun signature_test5/1,
-               fun signature_test6/1,
-               fun signature_test7/1,
-               fun signature_test8/1,
-               fun signature_test9/1
-              ],
-
-    Series3 = [
-               fun amazon_test1/1
-              ],
-
-    {setup, Setup, Cleanup, [
-                             {with, [], Series1},
-                             {with, [], Series2},
-                             {with, [], Series3}
-                            ]}.
+    Setup = fun () -> ok end,
+    Cleanup = fun (_) -> ok end,
+    Series1 = [fun hash_test1/1, fun hash_test2/1,
+	       fun hash_test3/1],
+    Series2 = [fun signature_test1/1, fun signature_test2/1,
+	       fun signature_test3/1, fun signature_test4/1,
+	       fun signature_test5/1, fun signature_test6/1,
+	       fun signature_test7/1, fun signature_test8/1,
+	       fun signature_test9/1],
+    Series3 = [fun amazon_test1/1],
+    {setup, Setup, Cleanup,
+     [{with, [], Series1}, {with, [], Series2},
+      {with, [], Series3}]}.
diff --git a/examples/https/https_store.erl b/examples/https/https_store.erl
index 719f206..a9a4ec0 100644
--- a/examples/https/https_store.erl
+++ b/examples/https/https_store.erl
@@ -1,4 +1,3 @@
-
 %% Trivial web storage app. It's available over both HTTP (port 8442)
 %% and HTTPS (port 8443). You use a PUT to store items, a GET to
 %% retrieve them and DELETE to delete them. The HTTP POST method is
@@ -34,113 +33,102 @@
 
 -module(https_store).
 
--export([start/0,
-         stop/0,
-         dispatch/1,
-         loop/1
-         ]).
+-export([dispatch/1, loop/1, start/0, stop/0]).
 
--define(HTTP_OPTS, [
-            {loop, {?MODULE, dispatch}},
-            {port, 8442},
-            {name, http_8442}
-            ]).
+-define(HTTP_OPTS,
+	[{loop, {?MODULE, dispatch}}, {port, 8442},
+	 {name, http_8442}]).
 
--define(HTTPS_OPTS, [
-            {loop, {?MODULE, dispatch}},
-            {port, 8443},
-            {name, https_8443},
-            {ssl, true},
-            {ssl_opts, [
-                {certfile, "server_cert.pem"},
-                {keyfile, "server_key.pem"}]}
-            ]).
+-define(HTTPS_OPTS,
+	[{loop, {?MODULE, dispatch}}, {port, 8443},
+	 {name, https_8443}, {ssl, true},
+	 {ssl_opts,
+	  [{certfile, "server_cert.pem"},
+	   {keyfile, "server_key.pem"}]}]).
 
 -record(sd, {http, https}).
+
 -record(resource, {type, data}).
 
 start() ->
     {ok, Http} = mochiweb_http:start(?HTTP_OPTS),
     {ok, Https} = mochiweb_http:start(?HTTPS_OPTS),
-    SD = #sd{http=Http, https=Https},
-    Pid = spawn_link(fun() ->
-                             ets:new(?MODULE, [named_table]),
-                             loop(SD)
-                     end),
+    SD = #sd{http = Http, https = Https},
+    Pid = spawn_link(fun () ->
+			     ets:new(?MODULE, [named_table]), loop(SD)
+		     end),
     register(http_store, Pid),
     ok.
 
-stop() ->
-    http_store ! stop,
-    ok.
+stop() -> http_store ! stop, ok.
 
 dispatch(Req) ->
     case mochiweb_request:get(method, Req) of
-        'GET' ->
-            get_resource(Req);
-        'PUT' ->
-            put_resource(Req);
-        'DELETE' ->
-            delete_resource(Req);
-        _ ->
-            Headers = [{"Allow", "GET,PUT,DELETE"}],
-            mochiweb_request:respond({405, Headers, "405 Method Not Allowed\r\n"}, Req)
+      'GET' -> get_resource(Req);
+      'PUT' -> put_resource(Req);
+      'DELETE' -> delete_resource(Req);
+      _ ->
+	  Headers = [{"Allow", "GET,PUT,DELETE"}],
+	  mochiweb_request:respond({405, Headers,
+				    "405 Method Not Allowed\r\n"},
+				   Req)
     end.
 
 get_resource(Req) ->
     Path = mochiweb_request:get(path, Req),
     case ets:lookup(?MODULE, Path) of
-        [{Path, #resource{type=Type, data=Data}}] ->
-            mochiweb_request:ok({Type, Data}, Req);
-        [] ->
-            mochiweb_request:respond({404, [], "404 Not Found\r\n"}, Req)
+      [{Path, #resource{type = Type, data = Data}}] ->
+	  mochiweb_request:ok({Type, Data}, Req);
+      [] ->
+	  mochiweb_request:respond({404, [], "404 Not Found\r\n"},
+				   Req)
     end.
 
 put_resource(Req) ->
-    ContentType = case mochiweb_request:get_header_value("Content-Type", Req) of
-        undefined ->
-            "application/octet-stream";
-        S ->
-            S
-    end,
-    Resource = #resource{type=ContentType, data=mochiweb_request:recv_body(Req)},
-    http_store ! {self(), {put, mochiweb_request:get(path, Req), Resource}},
+    ContentType = case
+		    mochiweb_request:get_header_value("Content-Type", Req)
+		      of
+		    undefined -> "application/octet-stream";
+		    S -> S
+		  end,
+    Resource = #resource{type = ContentType,
+			 data = mochiweb_request:recv_body(Req)},
+    http_store !
+      {self(),
+       {put, mochiweb_request:get(path, Req), Resource}},
     Pid = whereis(http_store),
     receive
-        {Pid, created} ->
-            mochiweb_request:respond({201, [], "201 Created\r\n"}, Req);
-        {Pid, updated} ->
-            mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
+      {Pid, created} ->
+	  mochiweb_request:respond({201, [], "201 Created\r\n"},
+				   Req);
+      {Pid, updated} ->
+	  mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
     end.
 
 delete_resource(Req) ->
-    http_store ! {self(), {delete, mochiweb_request:get(path, Req)}},
+    http_store !
+      {self(), {delete, mochiweb_request:get(path, Req)}},
     Pid = whereis(http_store),
     receive
-        {Pid, ok} ->
-            mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
+      {Pid, ok} ->
+	  mochiweb_request:respond({200, [], "200 OK\r\n"}, Req)
     end.
 
-loop(#sd{http=Http, https=Https} = SD) ->
+loop(#sd{http = Http, https = Https} = SD) ->
     receive
-        stop ->
-            ok = mochiweb_http:stop(Http),
-            ok = mochiweb_http:stop(Https),
-            exit(normal);
-        {From, {put, Key, Val}} ->
-            Exists = ets:member(?MODULE, Key),
-            ets:insert(?MODULE, {Key, Val}),
-            case Exists of
-                true ->
-                    From ! {self(), updated};
-                false ->
-                    From ! {self(), created}
-            end;
-        {From, {delete, Key}} ->
-            ets:delete(?MODULE, Key),
-            From ! {self(), ok};
-        _ ->
-            ignore
+      stop ->
+	  ok = mochiweb_http:stop(Http),
+	  ok = mochiweb_http:stop(Https),
+	  exit(normal);
+      {From, {put, Key, Val}} ->
+	  Exists = ets:member(?MODULE, Key),
+	  ets:insert(?MODULE, {Key, Val}),
+	  case Exists of
+	    true -> From ! {self(), updated};
+	    false -> From ! {self(), created}
+	  end;
+      {From, {delete, Key}} ->
+	  ets:delete(?MODULE, Key), From ! {self(), ok};
+      _ -> ignore
     end,
-    ?MODULE:loop(SD).
-
+    (?MODULE):loop(SD).
diff --git a/examples/keepalive/keepalive.erl b/examples/keepalive/keepalive.erl
index 51a7c3a..f6f4e53 100644
--- a/examples/keepalive/keepalive.erl
+++ b/examples/keepalive/keepalive.erl
@@ -18,64 +18,62 @@
 %% response.  if you do that then control flow returns to the proper place,
 %% and keep alives work like they would if you hadn't hibernated.
 
--export([ start/1, loop/1
-        ]).
+-export([loop/1, start/1]).
 
 %% internal export (so hibernate can reach it)
--export([ resume/3
-        ]).
+-export([resume/3]).
 
 -define(LOOP, {?MODULE, loop}).
 
 start(Options = [{port, _Port}]) ->
-    mochiweb_http:start([{name, ?MODULE}, {loop, ?LOOP} | Options]).
+    mochiweb_http:start([{name, ?MODULE}, {loop, ?LOOP}
+			 | Options]).
 
 loop(Req) ->
     Path = mochiweb_request:get(path, Req),
     case string:tokens(Path, "/") of
-        ["longpoll" | RestOfPath] ->
-            %% the "reentry" is a continuation -- what @mochiweb_http@
-            %% needs to do to start its loop back at the top
-            Reentry = mochiweb_http:reentry(?LOOP),
-
-            %% here we could send a message to some other process and hope
-            %% to get an interesting message back after a while.  for
-            %% simplicity let's just send ourselves a message after a few
-            %% seconds
-            erlang:send_after(2000, self(), "honk honk"),
-
-            %% since we expect to wait for a long time before getting a
-            %% reply, let's hibernate.  memory usage will be minimized, so
-            %% we won't be wasting memory just sitting in a @receive@
-            proc_lib:hibernate(?MODULE, resume, [Req, RestOfPath, Reentry]),
-
-            %% we'll never reach this point, and this function @loop/1@
-            %% won't ever return control to @mochiweb_http@.  luckily
-            %% @resume/3@ will take care of that.
-            io:format("not gonna happen~n", []);
-
-        _ ->
-            ok(Req, io_lib:format("some other page: ~p", [Path]))
+      ["longpoll" | RestOfPath] ->
+	  %% the "reentry" is a continuation -- what @mochiweb_http@
+	  %% needs to do to start its loop back at the top
+	  Reentry = mochiweb_http:reentry(?LOOP),
+	  %% here we could send a message to some other process and hope
+	  %% to get an interesting message back after a while.  for
+	  %% simplicity let's just send ourselves a message after a few
+	  %% seconds
+	  erlang:send_after(2000, self(), "honk honk"),
+	  %% since we expect to wait for a long time before getting a
+	  %% reply, let's hibernate.  memory usage will be minimized, so
+	  %% we won't be wasting memory just sitting in a @receive@
+	  proc_lib:hibernate(?MODULE, resume,
+			     [Req, RestOfPath, Reentry]),
+	  %% we'll never reach this point, and this function @loop/1@
+	  %% won't ever return control to @mochiweb_http@.  luckily
+	  %% @resume/3@ will take care of that.
+	  io:format("not gonna happen~n", []);
+      _ ->
+	  ok(Req, io_lib:format("some other page: ~p", [Path]))
     end,
-
     io:format("restarting loop normally in ~p~n", [Path]),
     ok.
 
 %% this is the function that's called when a message arrives.
 resume(Req, RestOfPath, Reentry) ->
     receive
-        Msg ->
-            Text = io_lib:format("wake up message: ~p~nrest of path: ~p", [Msg, RestOfPath]),
-            ok(Req, Text)
+      Msg ->
+	  Text =
+	      io_lib:format("wake up message: ~p~nrest of path: ~p",
+			    [Msg, RestOfPath]),
+	  ok(Req, Text)
     end,
-
     %% if we didn't call @Reentry@ here then the function would finish and the
     %% process would exit.  calling @Reentry@ takes care of returning control
     %% to @mochiweb_http@
-    io:format("reentering loop via continuation in ~p~n", [mochiweb_request:get(path, Req)]),
+    io:format("reentering loop via continuation in "
+	      "~p~n",
+	      [mochiweb_request:get(path, Req)]),
     Reentry(Req).
 
 ok(Req, Response) ->
-    mochiweb_request:ok(
-        {_ContentType = "text/plain", _Headers = [], Response},
-        Req).
+    mochiweb_request:ok({_ContentType = "text/plain",
+			 _Headers = [], Response},
+			Req).
diff --git a/src/mochifmt.erl b/src/mochifmt.erl
index 1aa01c3..e7b9b59 100644
--- a/src/mochifmt.erl
+++ b/src/mochifmt.erl
@@ -23,28 +23,31 @@
 %%      (<a href="http://www.python.org/dev/peps/pep-3101/">PEP 3101</a>).
 %%
 -module(mochifmt).
+
 -author('bob@mochimedia.com').
 
--export([format/2, format_field/2, convert_field/2, get_value/2, get_field/2]).
--export([tokenize/1, format/3, get_field/3, format_field/3]).
+-export([convert_field/2, format/2, format_field/2,
+	 get_field/2, get_value/2]).
+
+-export([format/3, format_field/3, get_field/3,
+	 tokenize/1]).
+
 -export([bformat/2, bformat/3]).
+
 -export([f/2, f/3]).
 
--record(conversion, {length, precision, ctype, align, fill_char, sign}).
+-record(conversion,
+	{length, precision, ctype, align, fill_char, sign}).
 
 %% @spec tokenize(S::string()) -> tokens()
 %% @doc Tokenize a format string into mochifmt's internal format.
-tokenize(S) ->
-    {?MODULE, tokenize(S, "", [])}.
+tokenize(S) -> {?MODULE, tokenize(S, "", [])}.
 
 %% @spec convert_field(Arg, Conversion::conversion()) -> term()
 %% @doc Process Arg according to the given explicit conversion specifier.
-convert_field(Arg, "") ->
-    Arg;
-convert_field(Arg, "r") ->
-    repr(Arg);
-convert_field(Arg, "s") ->
-    str(Arg).
+convert_field(Arg, "") -> Arg;
+convert_field(Arg, "r") -> repr(Arg);
+convert_field(Arg, "s") -> str(Arg).
 
 %% @spec get_value(Key::string(), Args::args()) -> term()
 %% @doc Get the Key from Args. If Args is a tuple then convert Key to
@@ -55,47 +58,43 @@ convert_field(Arg, "s") ->
 get_value(Key, Args) when is_tuple(Args) ->
     element(1 + list_to_integer(Key), Args);
 get_value(Key, Args) when is_list(Args) ->
-    try lists:nth(1 + list_to_integer(Key), Args)
-    catch error:_ ->
-            {_K, V} = proplist_lookup(Key, Args),
-            V
+    try lists:nth(1 + list_to_integer(Key), Args) catch
+      error:_ -> {_K, V} = proplist_lookup(Key, Args), V
     end.
 
 %% @spec get_field(Key::string(), Args) -> term()
 %% @doc Consecutively call get_value/2 on parts of Key delimited by ".",
 %%      replacing Args with the result of the previous get_value. This
 %%      is used to implement formats such as {0.0}.
-get_field(Key, Args) ->
-    get_field(Key, Args, ?MODULE).
+get_field(Key, Args) -> get_field(Key, Args, ?MODULE).
 
 %% @spec get_field(Key::string(), Args, Module) -> term()
 %% @doc Consecutively call Module:get_value/2 on parts of Key delimited by ".",
 %%      replacing Args with the result of the previous get_value. This
 %%      is used to implement formats such as {0.0}.
 get_field(Key, Args, Module) ->
-    {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end, Key),
+    {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end,
+				   Key),
     Res = mod_get_value(Name, Args, Module),
     case Next of
-        "" ->
-            Res;
-        "." ++ S1 ->
-            get_field(S1, Res, Module)
+      "" -> Res;
+      "." ++ S1 -> get_field(S1, Res, Module)
     end.
 
 mod_get_value(Name, Args, Module) ->
-    try tuple_apply(Module, get_value, [Name, Args])
-    catch error:undef -> get_value(Name, Args)
+    try tuple_apply(Module, get_value, [Name, Args]) catch
+      error:undef -> get_value(Name, Args)
     end.
 
 tuple_apply(Module, F, Args) when is_atom(Module) ->
     erlang:apply(Module, F, Args);
-tuple_apply(Module, F, Args) when is_tuple(Module), is_atom(element(1, Module)) ->
+tuple_apply(Module, F, Args)
+    when is_tuple(Module), is_atom(element(1, Module)) ->
     erlang:apply(element(1, Module), F, Args ++ [Module]).
 
 %% @spec format(Format::string(), Args) -> iolist()
 %% @doc Format Args with Format.
-format(Format, Args) ->
-    format(Format, Args, ?MODULE).
+format(Format, Args) -> format(Format, Args, ?MODULE).
 
 %% @spec format(Format::string(), Args, Module) -> iolist()
 %% @doc Format Args with Format using Module.
@@ -117,17 +116,14 @@ format_field(Arg, Format, _Module) ->
 
 %% @spec f(Format::string(), Args) -> string()
 %% @doc Format Args with Format and return a string().
-f(Format, Args) ->
-    f(Format, Args, ?MODULE).
+f(Format, Args) -> f(Format, Args, ?MODULE).
 
 %% @spec f(Format::string(), Args, Module) -> string()
 %% @doc Format Args with Format using Module and return a string().
 f(Format, Args, Module) ->
     case lists:member(${, Format) of
-        true ->
-            binary_to_list(bformat(Format, Args, Module));
-        false ->
-            Format
+      true -> binary_to_list(bformat(Format, Args, Module));
+      false -> Format
     end.
 
 %% @spec bformat(Format::string(), Args) -> binary()
@@ -142,25 +138,22 @@ bformat(Format, Args, Module) ->
 
 %% Internal API
 
-add_raw("", Acc) ->
-    Acc;
-add_raw(S, Acc) ->
-    [{raw, lists:reverse(S)} | Acc].
+add_raw("", Acc) -> Acc;
+add_raw(S, Acc) -> [{raw, lists:reverse(S)} | Acc].
 
-tokenize([], S, Acc) ->
-    lists:reverse(add_raw(S, Acc));
+tokenize([], S, Acc) -> lists:reverse(add_raw(S, Acc));
 tokenize("{{" ++ Rest, S, Acc) ->
     tokenize(Rest, "{" ++ S, Acc);
 tokenize("{" ++ Rest, S, Acc) ->
     {Format, Rest1} = tokenize_format(Rest),
-    tokenize(Rest1, "", [{format, make_format(Format)} | add_raw(S, Acc)]);
+    tokenize(Rest1, "",
+	     [{format, make_format(Format)} | add_raw(S, Acc)]);
 tokenize("}}" ++ Rest, S, Acc) ->
     tokenize(Rest, "}" ++ S, Acc);
 tokenize([C | Rest], S, Acc) ->
     tokenize(Rest, [C | S], Acc).
 
-tokenize_format(S) ->
-    tokenize_format(S, 1, []).
+tokenize_format(S) -> tokenize_format(S, 1, []).
 
 tokenize_format("}" ++ Rest, 1, Acc) ->
     {lists:reverse(Acc), Rest};
@@ -172,90 +165,96 @@ tokenize_format([C | Rest], N, Acc) ->
     tokenize_format(Rest, N, [C | Acc]).
 
 make_format(S) ->
-    {Name0, Spec} = case lists:splitwith(fun (C) -> C =/= $: end, S) of
-                        {_, ""} ->
-                            {S, ""};
-                        {SN, ":" ++ SS} ->
-                            {SN, SS}
-                    end,
-    {Name, Transform} = case lists:splitwith(fun (C) -> C =/= $! end, Name0) of
-                            {_, ""} ->
-                                {Name0, ""};
-                            {TN, "!" ++ TT} ->
-                                {TN, TT}
-                        end,
+    {Name0, Spec} = case lists:splitwith(fun (C) -> C =/= $:
+					 end,
+					 S)
+			of
+		      {_, ""} -> {S, ""};
+		      {SN, ":" ++ SS} -> {SN, SS}
+		    end,
+    {Name, Transform} = case lists:splitwith(fun (C) ->
+						     C =/= $!
+					     end,
+					     Name0)
+			    of
+			  {_, ""} -> {Name0, ""};
+			  {TN, "!" ++ TT} -> {TN, TT}
+			end,
     {Name, Transform, Spec}.
 
 proplist_lookup(S, P) ->
-    A = try list_to_existing_atom(S)
-        catch error:_ -> make_ref() end,
-    B = try list_to_binary(S)
-        catch error:_ -> make_ref() end,
+    A = try list_to_existing_atom(S) catch
+	  error:_ -> make_ref()
+	end,
+    B = try list_to_binary(S) catch
+	  error:_ -> make_ref()
+	end,
     proplist_lookup2({S, A, B}, P).
 
 proplist_lookup2({KS, KA, KB}, [{K, V} | _])
-  when KS =:= K orelse KA =:= K orelse KB =:= K ->
+    when KS =:= K orelse KA =:= K orelse KB =:= K ->
     {K, V};
 proplist_lookup2(Keys, [_ | Rest]) ->
     proplist_lookup2(Keys, Rest).
 
-format2([], _Args, _Module, Acc) ->
-    lists:reverse(Acc);
+format2([], _Args, _Module, Acc) -> lists:reverse(Acc);
 format2([{raw, S} | Rest], Args, Module, Acc) ->
     format2(Rest, Args, Module, [S | Acc]);
-format2([{format, {Key, Convert, Format0}} | Rest], Args, Module, Acc) ->
+format2([{format, {Key, Convert, Format0}} | Rest],
+	Args, Module, Acc) ->
     Format = f(Format0, Args, Module),
     V = case Module of
-            ?MODULE ->
-                V0 = get_field(Key, Args),
-                V1 = convert_field(V0, Convert),
-                format_field(V1, Format);
-            _ ->
-                V0 = try tuple_apply(Module, get_field, [Key, Args])
-                     catch error:undef -> get_field(Key, Args, Module) end,
-                V1 = try tuple_apply(Module, convert_field, [V0, Convert])
-                     catch error:undef -> convert_field(V0, Convert) end,
-                try tuple_apply(Module, format_field, [V1, Format])
-                catch error:undef -> format_field(V1, Format, Module) end
-        end,
+	  ?MODULE ->
+	      V0 = get_field(Key, Args),
+	      V1 = convert_field(V0, Convert),
+	      format_field(V1, Format);
+	  _ ->
+	      V0 = try tuple_apply(Module, get_field, [Key, Args])
+		   catch
+		     error:undef -> get_field(Key, Args, Module)
+		   end,
+	      V1 = try tuple_apply(Module, convert_field,
+				   [V0, Convert])
+		   catch
+		     error:undef -> convert_field(V0, Convert)
+		   end,
+	      try tuple_apply(Module, format_field, [V1, Format])
+	      catch
+		error:undef -> format_field(V1, Format, Module)
+	      end
+	end,
     format2(Rest, Args, Module, [V | Acc]).
 
-default_ctype(_Arg, C=#conversion{ctype=N}) when N =/= undefined ->
+default_ctype(_Arg, C = #conversion{ctype = N})
+    when N =/= undefined ->
     C;
 default_ctype(Arg, C) when is_integer(Arg) ->
-    C#conversion{ctype=decimal};
+    C#conversion{ctype = decimal};
 default_ctype(Arg, C) when is_float(Arg) ->
-    C#conversion{ctype=general};
-default_ctype(_Arg, C) ->
-    C#conversion{ctype=string}.
+    C#conversion{ctype = general};
+default_ctype(_Arg, C) -> C#conversion{ctype = string}.
 
-fix_padding(Arg, #conversion{length=undefined}) ->
+fix_padding(Arg, #conversion{length = undefined}) ->
     Arg;
-fix_padding(Arg, F=#conversion{length=Length, fill_char=Fill0, align=Align0,
-                               ctype=Type}) ->
+fix_padding(Arg,
+	    F = #conversion{length = Length, fill_char = Fill0,
+			    align = Align0, ctype = Type}) ->
     Padding = Length - iolist_size(Arg),
     Fill = case Fill0 of
-               undefined ->
-                   $\s;
-               _ ->
-                   Fill0
-           end,
+	     undefined -> $\s;
+	     _ -> Fill0
+	   end,
     Align = case Align0 of
-                undefined ->
-                    case Type of
-                        string ->
-                            left;
-                        _ ->
-                            right
-                    end;
-                _ ->
-                    Align0
-            end,
+	      undefined ->
+		  case Type of
+		    string -> left;
+		    _ -> right
+		  end;
+	      _ -> Align0
+	    end,
     case Padding > 0 of
-        true ->
-            do_padding(Arg, Padding, Fill, Align, F);
-        false ->
-            Arg
+      true -> do_padding(Arg, Padding, Fill, Align, F);
+      false -> Arg
     end.
 
 do_padding(Arg, Padding, Fill, right, _F) ->
@@ -263,31 +262,31 @@ do_padding(Arg, Padding, Fill, right, _F) ->
 do_padding(Arg, Padding, Fill, center, _F) ->
     LPadding = lists:duplicate(Padding div 2, Fill),
     RPadding = case Padding band 1 of
-                   1 ->
-                       [Fill | LPadding];
-                   _ ->
-                       LPadding
-               end,
+		 1 -> [Fill | LPadding];
+		 _ -> LPadding
+	       end,
     [LPadding, Arg, RPadding];
 do_padding([$- | Arg], Padding, Fill, sign_right, _F) ->
     [[$- | lists:duplicate(Padding, Fill)], Arg];
-do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=$-}) ->
+do_padding(Arg, Padding, Fill, sign_right,
+	   #conversion{sign = $-}) ->
     [lists:duplicate(Padding, Fill), Arg];
-do_padding([S | Arg], Padding, Fill, sign_right, #conversion{sign=S}) ->
+do_padding([S | Arg], Padding, Fill, sign_right,
+	   #conversion{sign = S}) ->
     [[S | lists:duplicate(Padding, Fill)], Arg];
-do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=undefined}) ->
+do_padding(Arg, Padding, Fill, sign_right,
+	   #conversion{sign = undefined}) ->
     [lists:duplicate(Padding, Fill), Arg];
 do_padding(Arg, Padding, Fill, left, _F) ->
     [Arg | lists:duplicate(Padding, Fill)].
 
-fix_sign(Arg, #conversion{sign=$+}) when Arg >= 0 ->
+fix_sign(Arg, #conversion{sign = $+}) when Arg >= 0 ->
     [$+, Arg];
-fix_sign(Arg, #conversion{sign=$\s}) when Arg >= 0 ->
+fix_sign(Arg, #conversion{sign = $\s}) when Arg >= 0 ->
     [$\s, Arg];
-fix_sign(Arg, _F) ->
-    Arg.
+fix_sign(Arg, _F) -> Arg.
 
-ctype($\%) -> percent;
+ctype($%) -> percent;
 ctype($s) -> string;
 ctype($b) -> bin;
 ctype($o) -> oct;
@@ -304,107 +303,123 @@ align($>) -> right;
 align($^) -> center;
 align($=) -> sign_right.
 
-convert2(Arg, F=#conversion{ctype=percent}) ->
-    [convert2(100.0 * Arg, F#conversion{ctype=fixed}), $\%];
-convert2(Arg, #conversion{ctype=string}) ->
-    str(Arg);
-convert2(Arg, #conversion{ctype=bin}) ->
+convert2(Arg, F = #conversion{ctype = percent}) ->
+    [convert2(1.0e+2 * Arg, F#conversion{ctype = fixed}),
+     $%];
+convert2(Arg, #conversion{ctype = string}) -> str(Arg);
+convert2(Arg, #conversion{ctype = bin}) ->
     erlang:integer_to_list(Arg, 2);
-convert2(Arg, #conversion{ctype=oct}) ->
+convert2(Arg, #conversion{ctype = oct}) ->
     erlang:integer_to_list(Arg, 8);
-convert2(Arg, #conversion{ctype=upper_hex}) ->
+convert2(Arg, #conversion{ctype = upper_hex}) ->
     erlang:integer_to_list(Arg, 16);
-convert2(Arg, #conversion{ctype=hex}) ->
+convert2(Arg, #conversion{ctype = hex}) ->
     string:to_lower(erlang:integer_to_list(Arg, 16));
-convert2(Arg, #conversion{ctype=char}) when Arg < 16#80 ->
+convert2(Arg, #conversion{ctype = char})
+    when Arg < 128 ->
     [Arg];
-convert2(Arg, #conversion{ctype=char}) ->
+convert2(Arg, #conversion{ctype = char}) ->
     xmerl_ucs:to_utf8(Arg);
-convert2(Arg, #conversion{ctype=decimal}) ->
+convert2(Arg, #conversion{ctype = decimal}) ->
     integer_to_list(Arg);
-convert2(Arg, #conversion{ctype=general, precision=undefined}) ->
-    try mochinum:digits(Arg)
-    catch error:undef -> io_lib:format("~g", [Arg]) end;
-convert2(Arg, #conversion{ctype=fixed, precision=undefined}) ->
+convert2(Arg,
+	 #conversion{ctype = general, precision = undefined}) ->
+    try mochinum:digits(Arg) catch
+      error:undef -> io_lib:format("~g", [Arg])
+    end;
+convert2(Arg,
+	 #conversion{ctype = fixed, precision = undefined}) ->
     io_lib:format("~f", [Arg]);
-convert2(Arg, #conversion{ctype=exp, precision=undefined}) ->
+convert2(Arg,
+	 #conversion{ctype = exp, precision = undefined}) ->
     io_lib:format("~e", [Arg]);
-convert2(Arg, #conversion{ctype=general, precision=P}) ->
+convert2(Arg,
+	 #conversion{ctype = general, precision = P}) ->
     io_lib:format("~." ++ integer_to_list(P) ++ "g", [Arg]);
-convert2(Arg, #conversion{ctype=fixed, precision=P}) ->
+convert2(Arg,
+	 #conversion{ctype = fixed, precision = P}) ->
     io_lib:format("~." ++ integer_to_list(P) ++ "f", [Arg]);
-convert2(Arg, #conversion{ctype=exp, precision=P}) ->
+convert2(Arg,
+	 #conversion{ctype = exp, precision = P}) ->
     io_lib:format("~." ++ integer_to_list(P) ++ "e", [Arg]).
 
-str(A) when is_atom(A) ->
-    atom_to_list(A);
-str(I) when is_integer(I) ->
-    integer_to_list(I);
+str(A) when is_atom(A) -> atom_to_list(A);
+str(I) when is_integer(I) -> integer_to_list(I);
 str(F) when is_float(F) ->
-    try mochinum:digits(F)
-    catch error:undef -> io_lib:format("~g", [F]) end;
-str(L) when is_list(L) ->
-    L;
-str(B) when is_binary(B) ->
-    B;
-str(P) ->
-    repr(P).
+    try mochinum:digits(F) catch
+      error:undef -> io_lib:format("~g", [F])
+    end;
+str(L) when is_list(L) -> L;
+str(B) when is_binary(B) -> B;
+str(P) -> repr(P).
 
 repr(P) when is_float(P) ->
-    try mochinum:digits(P)
-    catch error:undef -> float_to_list(P) end;
-repr(P) ->
-    io_lib:format("~p", [P]).
+    try mochinum:digits(P) catch
+      error:undef -> float_to_list(P)
+    end;
+repr(P) -> io_lib:format("~p", [P]).
 
 parse_std_conversion(S) ->
     parse_std_conversion(S, #conversion{}).
 
-parse_std_conversion("", Acc) ->
-    Acc;
+parse_std_conversion("", Acc) -> Acc;
 parse_std_conversion([Fill, Align | Spec], Acc)
-  when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
-    parse_std_conversion(Spec, Acc#conversion{fill_char=Fill,
-                                              align=align(Align)});
+    when Align =:= $< orelse
+	   Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
+    parse_std_conversion(Spec,
+			 Acc#conversion{fill_char = Fill,
+					align = align(Align)});
 parse_std_conversion([Align | Spec], Acc)
-  when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
-    parse_std_conversion(Spec, Acc#conversion{align=align(Align)});
+    when Align =:= $< orelse
+	   Align =:= $> orelse Align =:= $= orelse Align =:= $^ ->
+    parse_std_conversion(Spec,
+			 Acc#conversion{align = align(Align)});
 parse_std_conversion([Sign | Spec], Acc)
-  when Sign =:= $+ orelse Sign =:= $- orelse Sign =:= $\s ->
-    parse_std_conversion(Spec, Acc#conversion{sign=Sign});
+    when Sign =:= $+ orelse
+	   Sign =:= $- orelse Sign =:= $\s ->
+    parse_std_conversion(Spec, Acc#conversion{sign = Sign});
 parse_std_conversion("0" ++ Spec, Acc) ->
     Align = case Acc#conversion.align of
-                undefined ->
-                    sign_right;
-                A ->
-                    A
-            end,
-    parse_std_conversion(Spec, Acc#conversion{fill_char=$0, align=Align});
-parse_std_conversion(Spec=[D|_], Acc) when D >= $0 andalso D =< $9 ->
-    {W, Spec1} = lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec),
-    parse_std_conversion(Spec1, Acc#conversion{length=list_to_integer(W)});
+	      undefined -> sign_right;
+	      A -> A
+	    end,
+    parse_std_conversion(Spec,
+			 Acc#conversion{fill_char = $0, align = Align});
+parse_std_conversion(Spec = [D | _], Acc)
+    when D >= $0 andalso D =< $9 ->
+    {W, Spec1} = lists:splitwith(fun (C) ->
+					 C >= $0 andalso C =< $9
+				 end,
+				 Spec),
+    parse_std_conversion(Spec1,
+			 Acc#conversion{length = list_to_integer(W)});
 parse_std_conversion([$. | Spec], Acc) ->
-    case lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec) of
-        {"", Spec1} ->
-            parse_std_conversion(Spec1, Acc);
-        {P, Spec1} ->
-            parse_std_conversion(Spec1,
-                                 Acc#conversion{precision=list_to_integer(P)})
+    case lists:splitwith(fun (C) -> C >= $0 andalso C =< $9
+			 end,
+			 Spec)
+	of
+      {"", Spec1} -> parse_std_conversion(Spec1, Acc);
+      {P, Spec1} ->
+	  parse_std_conversion(Spec1,
+			       Acc#conversion{precision = list_to_integer(P)})
     end;
 parse_std_conversion([Type], Acc) ->
-    parse_std_conversion("", Acc#conversion{ctype=ctype(Type)}).
-
+    parse_std_conversion("",
+			 Acc#conversion{ctype = ctype(Type)}).
 
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
 
 tokenize_test() ->
     {?MODULE, [{raw, "ABC"}]} = tokenize("ABC"),
     {?MODULE, [{format, {"0", "", ""}}]} = tokenize("{0}"),
-    {?MODULE, [{raw, "ABC"}, {format, {"1", "", ""}}, {raw, "DEF"}]} =
-        tokenize("ABC{1}DEF"),
+    {?MODULE,
+     [{raw, "ABC"}, {format, {"1", "", ""}}, {raw, "DEF"}]} =
+	tokenize("ABC{1}DEF"),
     ok.
 
 format_test() ->
@@ -413,26 +428,31 @@ format_test() ->
     <<"   4">> = bformat("{0:{0}}", [4]),
     <<"4   ">> = bformat("{0:4}", ["4"]),
     <<"4   ">> = bformat("{0:{0}}", ["4"]),
-    <<"1.2yoDEF">> = bformat("{2}{0}{1}{3}", {yo, "DE", 1.2, <<"F">>}),
-    <<"cafebabe">> = bformat("{0:x}", {16#cafebabe}),
-    <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}),
-    <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}),
-    <<"755">> = bformat("{0:o}", {8#755}),
+    <<"1.2yoDEF">> = bformat("{2}{0}{1}{3}",
+			     {yo, "DE", 1.19999999999999995559, <<"F">>}),
+    <<"cafebabe">> = bformat("{0:x}", {3405691582}),
+    <<"CAFEBABE">> = bformat("{0:X}", {3405691582}),
+    <<"CAFEBABE">> = bformat("{0:X}", {3405691582}),
+    <<"755">> = bformat("{0:o}", {493}),
     <<"a">> = bformat("{0:c}", {97}),
     %% Horizontal ellipsis
-    <<226, 128, 166>> = bformat("{0:c}", {16#2026}),
+    <<226, 128, 166>> = bformat("{0:c}", {8230}),
     <<"11">> = bformat("{0:b}", {3}),
     <<"11">> = bformat("{0:b}", [3]),
     <<"11">> = bformat("{three:b}", [{three, 3}]),
     <<"11">> = bformat("{three:b}", [{"three", 3}]),
     <<"11">> = bformat("{three:b}", [{<<"three">>, 3}]),
     <<"\"foo\"">> = bformat("{0!r}", {"foo"}),
-    <<"2008-5-4">> = bformat("{0.0}-{0.1}-{0.2}", {{2008,5,4}}),
-    <<"2008-05-04">> = bformat("{0.0:04}-{0.1:02}-{0.2:02}", {{2008,5,4}}),
+    <<"2008-5-4">> = bformat("{0.0}-{0.1}-{0.2}",
+			     {{2008, 5, 4}}),
+    <<"2008-05-04">> = bformat("{0.0:04}-{0.1:02}-{0.2:02}",
+			       {{2008, 5, 4}}),
     <<"foo6bar-6">> = bformat("foo{1}{0}-{1}", {bar, 6}),
-    <<"-'atom test'-">> = bformat("-{arg!r}-", [{arg, 'atom test'}]),
-    <<"2008-05-04">> = bformat("{0.0:0{1.0}}-{0.1:0{1.1}}-{0.2:0{1.2}}",
-                               {{2008,5,4}, {4, 2, 2}}),
+    <<"-'atom test'-">> = bformat("-{arg!r}-",
+				  [{arg, 'atom test'}]),
+    <<"2008-05-04">> =
+	bformat("{0.0:0{1.0}}-{0.1:0{1.1}}-{0.2:0{1.2}}",
+		{{2008, 5, 4}, {4, 2, 2}}),
     ok.
 
 std_test() ->
@@ -441,13 +461,16 @@ std_test() ->
     ok.
 
 records_test() ->
-    M = mochifmt_records:new([{conversion, record_info(fields, conversion)}]),
-    R = #conversion{length=long, precision=hard, sign=peace},
+    M = mochifmt_records:new([{conversion,
+			       record_info(fields, conversion)}]),
+    R = #conversion{length = long, precision = hard,
+		    sign = peace},
     long = mochifmt_records:get_value("length", R, M),
     hard = mochifmt_records:get_value("precision", R, M),
     peace = mochifmt_records:get_value("sign", R, M),
     <<"long hard">> = bformat("{length} {precision}", R, M),
-    <<"long hard">> = bformat("{0.length} {0.precision}", [R], M),
+    <<"long hard">> = bformat("{0.length} {0.precision}",
+			      [R], M),
     ok.
 
 -endif.
diff --git a/src/mochiweb_acceptor.erl b/src/mochiweb_acceptor.erl
index 1b53552..2fed6bd 100644
--- a/src/mochiweb_acceptor.erl
+++ b/src/mochiweb_acceptor.erl
@@ -22,11 +22,12 @@
 %% @doc MochiWeb acceptor.
 
 -module(mochiweb_acceptor).
+
 -author('bob@mochimedia.com').
 
 -include("internal.hrl").
 
--export([start_link/3, start_link/4, init/4]).
+-export([init/4, start_link/3, start_link/4]).
 
 -define(EMFILE_SLEEP_MSEC, 100).
 
@@ -34,43 +35,40 @@ start_link(Server, Listen, Loop) ->
     start_link(Server, Listen, Loop, []).
 
 start_link(Server, Listen, Loop, Opts) ->
-    proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop, Opts]).
+    proc_lib:spawn_link(?MODULE, init,
+			[Server, Listen, Loop, Opts]).
 
 do_accept(Server, Listen) ->
     T1 = os:timestamp(),
     case mochiweb_socket:transport_accept(Listen) of
-        {ok, Socket} ->
-            gen_server:cast(Server, {accepted, self(), timer:now_diff(os:timestamp(), T1)}),
-            mochiweb_socket:finish_accept(Socket);
-        Other ->
-            Other
+      {ok, Socket} ->
+	  gen_server:cast(Server,
+			  {accepted, self(),
+			   timer:now_diff(os:timestamp(), T1)}),
+	  mochiweb_socket:finish_accept(Socket);
+      Other -> Other
     end.
 
 init(Server, Listen, Loop, Opts) ->
     case catch do_accept(Server, Listen) of
-        {ok, Socket} ->
-            call_loop(Loop, Socket, Opts);
-        {error, Err} when Err =:= closed orelse
-                          Err =:= esslaccept orelse
-                          Err =:= timeout ->
-            exit(normal);
-        Other ->
-            %% Mitigate out of file descriptor scenario by sleeping for a
-            %% short time to slow error rate
-            case Other of
-                {error, emfile} ->
-                    receive
-                    after ?EMFILE_SLEEP_MSEC ->
-                            ok
-                    end;
-                _ ->
-                    ok
-            end,
-            error_logger:error_report(
-              [{application, mochiweb},
-               "Accept failed error",
-               lists:flatten(io_lib:format("~p", [Other]))]),
-            exit({error, accept_failed})
+      {ok, Socket} -> call_loop(Loop, Socket, Opts);
+      {error, Err}
+	  when Err =:= closed orelse
+		 Err =:= esslaccept orelse Err =:= timeout ->
+	  exit(normal);
+      Other ->
+	  %% Mitigate out of file descriptor scenario by sleeping for a
+	  %% short time to slow error rate
+	  case Other of
+	    {error, emfile} ->
+		receive  after ?EMFILE_SLEEP_MSEC -> ok end;
+	    _ -> ok
+	  end,
+	  error_logger:error_report([{application, mochiweb},
+				     "Accept failed error",
+				     lists:flatten(io_lib:format("~p",
+								 [Other]))]),
+	  exit({error, accept_failed})
     end.
 
 call_loop({M, F}, Socket, Opts) when is_atom(M) ->
@@ -79,5 +77,4 @@ call_loop({M, F, [A1]}, Socket, Opts) when is_atom(M) ->
     M:F(Socket, Opts, A1);
 call_loop({M, F, A}, Socket, Opts) when is_atom(M) ->
     erlang:apply(M, F, [Socket, Opts | A]);
-call_loop(Loop, Socket, Opts) ->
-    Loop(Socket, Opts).
+call_loop(Loop, Socket, Opts) -> Loop(Socket, Opts).
diff --git a/src/mochiweb_http.erl b/src/mochiweb_http.erl
index 6854b6a..aff95aa 100644
--- a/src/mochiweb_http.erl
+++ b/src/mochiweb_http.erl
@@ -22,38 +22,47 @@
 %% @doc HTTP server.
 
 -module(mochiweb_http).
+
 -author('bob@mochimedia.com').
+
 -export([start/1, start_link/1, stop/0, stop/1]).
+
 -export([loop/3]).
+
 -export([after_response/2, reentry/1]).
+
 -export([parse_range_request/1, range_skip_length/2]).
 
--define(REQUEST_RECV_TIMEOUT, 300000).   %% timeout waiting for request line
--define(HEADERS_RECV_TIMEOUT, 30000).    %% timeout waiting for headers
+-define(REQUEST_RECV_TIMEOUT,
+	300000).   %% timeout waiting for request line
+
+-define(HEADERS_RECV_TIMEOUT,
+	30000).    %% timeout waiting for headers
 
 -define(MAX_HEADERS, 1000).
--define(DEFAULTS, [{name, ?MODULE},
-                   {port, 8888}]).
+
+-define(DEFAULTS, [{name, ?MODULE}, {port, 8888}]).
 
 -ifdef(gen_tcp_r15b_workaround).
-r15b_workaround() -> true.
--else.
+
 r15b_workaround() -> false.
--endif.
 
+-else.
+
+r15b_workaround() -> false.
 
+-endif.
 
 parse_options(Options) ->
     {loop, HttpLoop} = proplists:lookup(loop, Options),
     Loop = {?MODULE, loop, [HttpLoop]},
-    Options1 = [{loop, Loop} | proplists:delete(loop, Options)],
+    Options1 = [{loop, Loop} | proplists:delete(loop,
+						Options)],
     mochilists:set_defaults(?DEFAULTS, Options1).
 
-stop() ->
-    mochiweb_socket_server:stop(?MODULE).
+stop() -> mochiweb_socket_server:stop(?MODULE).
 
-stop(Name) ->
-    mochiweb_socket_server:stop(Name).
+stop(Name) -> mochiweb_socket_server:stop(Name).
 
 %% @spec start(Options) -> ServerRet
 %%     Options = [option()]
@@ -76,240 +85,263 @@ start_link(Options) ->
 
 ensure_started(M) when is_atom(M) ->
     case M:start() of
-        {ok, _Pid} ->
-            ok;
-        {error, {already_started, _Pid}} ->
-            ok
+      {ok, _Pid} -> ok;
+      {error, {already_started, _Pid}} -> ok
     end.
 
 loop(Socket, Opts, Body) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, http}])),
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 http}])),
     request(Socket, Opts, Body).
 
 request(Socket, Opts, Body) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{active, once}])),
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{active,
+								 once}])),
     receive
-        {Protocol, _, {http_request, Method, Path, Version}} when Protocol == http orelse Protocol == ssl ->
-            ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, httph}])),
-            headers(Socket, Opts, {Method, Path, Version}, [], Body, 0);
-        {Protocol, _, {http_error, "\r\n"}} when Protocol == http orelse Protocol == ssl ->
-            request(Socket, Opts, Body);
-        {Protocol, _, {http_error, "\n"}} when Protocol == http orelse Protocol == ssl ->
-            request(Socket, Opts, Body);
-        {tcp_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {tcp_error, _, emsgsize} = Other ->
-            handle_invalid_msg_request(Other, Socket, Opts);
-        {ssl_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal)
-    after ?REQUEST_RECV_TIMEOUT ->
-        mochiweb_socket:close(Socket),
-        exit(normal)
+      {Protocol, _, {http_request, Method, Path, Version}}
+	  when Protocol == http orelse Protocol == ssl ->
+	  ok =
+	      mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+								     [{packet,
+								       httph}])),
+	  headers(Socket, Opts, {Method, Path, Version}, [], Body,
+		  0);
+      {Protocol, _, {http_error, "\r\n"}}
+	  when Protocol == http orelse Protocol == ssl ->
+	  request(Socket, Opts, Body);
+      {Protocol, _, {http_error, "\n"}}
+	  when Protocol == http orelse Protocol == ssl ->
+	  request(Socket, Opts, Body);
+      {tcp_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {tcp_error, _, emsgsize} = Other ->
+	  handle_invalid_msg_request(Other, Socket, Opts);
+      {ssl_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal)
+      after ?REQUEST_RECV_TIMEOUT ->
+		mochiweb_socket:close(Socket), exit(normal)
     end.
 
 reentry(Body) ->
-    fun (Req) ->
-            ?MODULE:after_response(Body, Req)
-    end.
+    fun (Req) -> (?MODULE):after_response(Body, Req) end.
 
-headers(Socket, Opts, Request, Headers, _Body, ?MAX_HEADERS) ->
+headers(Socket, Opts, Request, Headers, _Body,
+	?MAX_HEADERS) ->
     %% Too many headers sent, bad request.
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, raw}])),
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 raw}])),
     handle_invalid_request(Socket, Opts, Request, Headers);
-headers(Socket, Opts, Request, Headers, Body, HeaderCount) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{active, once}])),
+headers(Socket, Opts, Request, Headers, Body,
+	HeaderCount) ->
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{active,
+								 once}])),
     receive
-        {Protocol, _, http_eoh} when Protocol == http orelse Protocol == ssl ->
-            Req = new_request(Socket, Opts, Request, Headers),
-            call_body(Body, Req),
-            ?MODULE:after_response(Body, Req);
-        {Protocol, _, {http_header, _, Name, _, Value}} when Protocol == http orelse Protocol == ssl ->
-            headers(Socket, Opts, Request, [{Name, Value} | Headers], Body,
-                    1 + HeaderCount);
-        {tcp_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {tcp_error, _, emsgsize} = Other ->
-            handle_invalid_msg_request(Other, Socket, Opts, Request, Headers)
-    after ?HEADERS_RECV_TIMEOUT ->
-        mochiweb_socket:close(Socket),
-        exit(normal)
+      {Protocol, _, http_eoh}
+	  when Protocol == http orelse Protocol == ssl ->
+	  Req = new_request(Socket, Opts, Request, Headers),
+	  call_body(Body, Req),
+	  (?MODULE):after_response(Body, Req);
+      {Protocol, _, {http_header, _, Name, _, Value}}
+	  when Protocol == http orelse Protocol == ssl ->
+	  headers(Socket, Opts, Request,
+		  [{Name, Value} | Headers], Body, 1 + HeaderCount);
+      {tcp_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {tcp_error, _, emsgsize} = Other ->
+	  handle_invalid_msg_request(Other, Socket, Opts, Request,
+				     Headers)
+      after ?HEADERS_RECV_TIMEOUT ->
+		mochiweb_socket:close(Socket), exit(normal)
     end.
 
 call_body({M, F, A}, Req) when is_atom(M) ->
     erlang:apply(M, F, [Req | A]);
-call_body({M, F}, Req) when is_atom(M) ->
-    M:F(Req);
-call_body(Body, Req) ->
-    Body(Req).
+call_body({M, F}, Req) when is_atom(M) -> M:F(Req);
+call_body(Body, Req) -> Body(Req).
+
+-spec handle_invalid_msg_request(term(), term(),
+				 term()) -> no_return().
 
--spec handle_invalid_msg_request(term(), term(), term()) -> no_return().
 handle_invalid_msg_request(Msg, Socket, Opts) ->
-    handle_invalid_msg_request(Msg, Socket, Opts, {'GET', {abs_path, "/"}, {0,9}}, []).
+    handle_invalid_msg_request(Msg, Socket, Opts,
+			       {'GET', {abs_path, "/"}, {0, 9}}, []).
+
+-spec handle_invalid_msg_request(term(), term(), term(),
+				 term(), term()) -> no_return().
 
--spec handle_invalid_msg_request(term(), term(), term(), term(), term()) -> no_return().
-handle_invalid_msg_request(Msg, Socket, Opts, Request, RevHeaders) ->
+handle_invalid_msg_request(Msg, Socket, Opts, Request,
+			   RevHeaders) ->
     case {Msg, r15b_workaround()} of
-        {{tcp_error,_,emsgsize}, true} ->
-            %% R15B02 returns this then closes the socket, so close and exit
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        _ ->
-            handle_invalid_request(Socket, Opts, Request, RevHeaders)
+      {{tcp_error, _, emsgsize}, true} ->
+	  %% R15B02 returns this then closes the socket, so close and exit
+	  mochiweb_socket:close(Socket),
+	  exit(normal);
+      _ ->
+	  handle_invalid_request(Socket, Opts, Request,
+				 RevHeaders)
     end.
 
--spec handle_invalid_request(term(), term(), term(), term()) -> no_return().
-handle_invalid_request(Socket, Opts, Request, RevHeaders) ->
-    {ReqM, _} = Req = new_request(Socket, Opts, Request, RevHeaders),
+-spec handle_invalid_request(term(), term(), term(),
+			     term()) -> no_return().
+
+handle_invalid_request(Socket, Opts, Request,
+		       RevHeaders) ->
+    {ReqM, _} = Req = new_request(Socket, Opts, Request,
+				  RevHeaders),
     ReqM:respond({400, [], []}, Req),
     mochiweb_socket:close(Socket),
     exit(normal).
 
 new_request(Socket, Opts, Request, RevHeaders) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, raw}])),
-    mochiweb:new_request({Socket, Opts, Request, lists:reverse(RevHeaders)}).
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 raw}])),
+    mochiweb:new_request({Socket, Opts, Request,
+			  lists:reverse(RevHeaders)}).
 
 after_response(Body, {ReqM, _} = Req) ->
     Socket = ReqM:get(socket, Req),
     case ReqM:should_close(Req) of
-        true ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        false ->
-            ReqM:cleanup(Req),
-            erlang:garbage_collect(),
-            ?MODULE:loop(Socket, mochiweb_request:get(opts, Req), Body)
+      true -> mochiweb_socket:close(Socket), exit(normal);
+      false ->
+	  ReqM:cleanup(Req),
+	  erlang:garbage_collect(),
+	  (?MODULE):loop(Socket, mochiweb_request:get(opts, Req),
+			 Body)
     end.
 
 parse_range_request(RawRange) when is_list(RawRange) ->
-    try
-        "bytes=" ++ RangeString = RawRange,
-        RangeTokens = [string:strip(R) || R <- string:tokens(RangeString, ",")],
-        Ranges = [R || R <- RangeTokens, string:len(R) > 0],
-        lists:map(fun ("-" ++ V)  ->
-                          {none, list_to_integer(V)};
-                      (R) ->
-                          case string:tokens(R, "-") of
-                              [S1, S2] ->
-                                  {list_to_integer(S1), list_to_integer(S2)};
-                              [S] ->
-                                  {list_to_integer(S), none}
-                          end
-                  end,
-                  Ranges)
+    try "bytes=" ++ RangeString = RawRange,
+	RangeTokens = [string:strip(R)
+		       || R <- string:tokens(RangeString, ",")],
+	Ranges = [R || R <- RangeTokens, string:len(R) > 0],
+	[parse_range_request_1(V1) || V1 <- Ranges]
     catch
-        _:_ ->
-            fail
+      _:_ -> fail
+    end.
+
+parse_range_request_1("-" ++ V) ->
+    {none, list_to_integer(V)};
+parse_range_request_1(R) ->
+    case string:tokens(R, "-") of
+      [S1, S2] -> {list_to_integer(S1), list_to_integer(S2)};
+      [S] -> {list_to_integer(S), none}
     end.
 
 range_skip_length(Spec, Size) ->
     case Spec of
-        {none, R} when R =< Size, R >= 0 ->
-            {Size - R, R};
-        {none, _OutOfRange} ->
-            {0, Size};
-        {R, none} when R >= 0, R < Size ->
-            {R, Size - R};
-        {_OutOfRange, none} ->
-            invalid_range;
-        {Start, End} when Start >= 0, Start < Size, Start =< End ->
-            {Start, erlang:min(End + 1, Size) - Start};
-        {_InvalidStart, _InvalidEnd} ->
-            invalid_range
+      {none, R} when R =< Size, R >= 0 -> {Size - R, R};
+      {none, _OutOfRange} -> {0, Size};
+      {R, none} when R >= 0, R < Size -> {R, Size - R};
+      {_OutOfRange, none} -> invalid_range;
+      {Start, End}
+	  when Start >= 0, Start < Size, Start =< End ->
+	  {Start, erlang:min(End + 1, Size) - Start};
+      {_InvalidStart, _InvalidEnd} -> invalid_range
     end.
 
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
 
 range_test() ->
     %% valid, single ranges
-    ?assertEqual([{20, 30}], parse_range_request("bytes=20-30")),
-    ?assertEqual([{20, none}], parse_range_request("bytes=20-")),
-    ?assertEqual([{none, 20}], parse_range_request("bytes=-20")),
-
+    ?assertEqual([{20, 30}],
+		 (parse_range_request("bytes=20-30"))),
+    ?assertEqual([{20, none}],
+		 (parse_range_request("bytes=20-"))),
+    ?assertEqual([{none, 20}],
+		 (parse_range_request("bytes=-20"))),
     %% trivial single range
-    ?assertEqual([{0, none}], parse_range_request("bytes=0-")),
-
+    ?assertEqual([{0, none}],
+		 (parse_range_request("bytes=0-"))),
     %% invalid, single ranges
-    ?assertEqual(fail, parse_range_request("")),
-    ?assertEqual(fail, parse_range_request("garbage")),
-    ?assertEqual(fail, parse_range_request("bytes=-20-30")),
-
+    ?assertEqual(fail, (parse_range_request(""))),
+    ?assertEqual(fail, (parse_range_request("garbage"))),
+    ?assertEqual(fail,
+		 (parse_range_request("bytes=-20-30"))),
     %% valid, multiple range
-    ?assertEqual(
-       [{20, 30}, {50, 100}, {110, 200}],
-       parse_range_request("bytes=20-30,50-100,110-200")),
-    ?assertEqual(
-       [{20, none}, {50, 100}, {none, 200}],
-       parse_range_request("bytes=20-,50-100,-200")),
-
+    ?assertEqual([{20, 30}, {50, 100}, {110, 200}],
+		 (parse_range_request("bytes=20-30,50-100,110-200"))),
+    ?assertEqual([{20, none}, {50, 100}, {none, 200}],
+		 (parse_range_request("bytes=20-,50-100,-200"))),
     %% valid, multiple range with whitespace
-    ?assertEqual(
-       [{20, 30}, {50, 100}, {110, 200}],
-       parse_range_request("bytes=20-30, 50-100 , 110-200")),
-
+    ?assertEqual([{20, 30}, {50, 100}, {110, 200}],
+		 (parse_range_request("bytes=20-30, 50-100 , 110-200"))),
     %% valid, multiple range with extra commas
-    ?assertEqual(
-       [{20, 30}, {50, 100}, {110, 200}],
-       parse_range_request("bytes=20-30,,50-100,110-200")),
-    ?assertEqual(
-       [{20, 30}, {50, 100}, {110, 200}],
-       parse_range_request("bytes=20-30, ,50-100,,,110-200")),
-
+    ?assertEqual([{20, 30}, {50, 100}, {110, 200}],
+		 (parse_range_request("bytes=20-30,,50-100,110-200"))),
+    ?assertEqual([{20, 30}, {50, 100}, {110, 200}],
+		 (parse_range_request("bytes=20-30, ,50-100,,,110-200"))),
     %% no ranges
-    ?assertEqual([], parse_range_request("bytes=")),
+    ?assertEqual([], (parse_range_request("bytes="))),
     ok.
 
 range_skip_length_test() ->
-    Body = <<"012345678901234567890123456789012345678901234567890123456789">>,
+    Body = <<"012345678901234567890123456789012345678901234"
+	     "567890123456789">>,
     BodySize = byte_size(Body), %% 60
     BodySize = 60,
-
     %% these values assume BodySize =:= 60
-    ?assertEqual({1,9}, range_skip_length({1,9}, BodySize)), %% 1-9
-    ?assertEqual({10,10}, range_skip_length({10,19}, BodySize)), %% 10-19
-    ?assertEqual({40, 20}, range_skip_length({none, 20}, BodySize)), %% -20
-    ?assertEqual({30, 30}, range_skip_length({30, none}, BodySize)), %% 30-
-
+    ?assertEqual({1, 9},
+		 (range_skip_length({1, 9}, BodySize))), %% 1-9
+    ?assertEqual({10, 10},
+		 (range_skip_length({10, 19}, BodySize))), %% 10-19
+    ?assertEqual({40, 20},
+		 (range_skip_length({none, 20}, BodySize))), %% -20
+    ?assertEqual({30, 30},
+		 (range_skip_length({30, none}, BodySize))), %% 30-
     %% valid edge cases for range_skip_length
-    ?assertEqual({BodySize, 0}, range_skip_length({none, 0}, BodySize)),
-    ?assertEqual({0, BodySize}, range_skip_length({none, BodySize}, BodySize)),
-    ?assertEqual({0, BodySize}, range_skip_length({0, none}, BodySize)),
-    ?assertEqual({0, BodySize}, range_skip_length({0, BodySize + 1}, BodySize)),
+    ?assertEqual({BodySize, 0},
+		 (range_skip_length({none, 0}, BodySize))),
+    ?assertEqual({0, BodySize},
+		 (range_skip_length({none, BodySize}, BodySize))),
+    ?assertEqual({0, BodySize},
+		 (range_skip_length({0, none}, BodySize))),
+    ?assertEqual({0, BodySize},
+		 (range_skip_length({0, BodySize + 1}, BodySize))),
     BodySizeLess1 = BodySize - 1,
     ?assertEqual({BodySizeLess1, 1},
-                 range_skip_length({BodySize - 1, none}, BodySize)),
+		 (range_skip_length({BodySize - 1, none}, BodySize))),
     ?assertEqual({BodySizeLess1, 1},
-                 range_skip_length({BodySize - 1, BodySize+5}, BodySize)),
+		 (range_skip_length({BodySize - 1, BodySize + 5},
+				    BodySize))),
     ?assertEqual({BodySizeLess1, 1},
-                 range_skip_length({BodySize - 1, BodySize}, BodySize)),
-
+		 (range_skip_length({BodySize - 1, BodySize},
+				    BodySize))),
     %% out of range, return whole thing
     ?assertEqual({0, BodySize},
-                 range_skip_length({none, BodySize + 1}, BodySize)),
+		 (range_skip_length({none, BodySize + 1}, BodySize))),
     ?assertEqual({0, BodySize},
-                 range_skip_length({none, -1}, BodySize)),
+		 (range_skip_length({none, -1}, BodySize))),
     ?assertEqual({0, BodySize},
-                 range_skip_length({0, BodySize + 1}, BodySize)),
-
+		 (range_skip_length({0, BodySize + 1}, BodySize))),
     %% invalid ranges
     ?assertEqual(invalid_range,
-                 range_skip_length({-1, 30}, BodySize)),
+		 (range_skip_length({-1, 30}, BodySize))),
     ?assertEqual(invalid_range,
-                 range_skip_length({-1, BodySize + 1}, BodySize)),
+		 (range_skip_length({-1, BodySize + 1}, BodySize))),
     ?assertEqual(invalid_range,
-                 range_skip_length({BodySize, 40}, BodySize)),
+		 (range_skip_length({BodySize, 40}, BodySize))),
     ?assertEqual(invalid_range,
-                 range_skip_length({-1, none}, BodySize)),
+		 (range_skip_length({-1, none}, BodySize))),
     ?assertEqual(invalid_range,
-                 range_skip_length({BodySize, none}, BodySize)),
+		 (range_skip_length({BodySize, none}, BodySize))),
     ?assertEqual(invalid_range,
-                 range_skip_length({BodySize + 1, BodySize + 5}, BodySize)),
+		 (range_skip_length({BodySize + 1, BodySize + 5},
+				    BodySize))),
     ok.
 
 -endif.
diff --git a/src/mochiweb_multipart.erl b/src/mochiweb_multipart.erl
index 46b7090..21b23bb 100644
--- a/src/mochiweb_multipart.erl
+++ b/src/mochiweb_multipart.erl
@@ -22,16 +22,21 @@
 %% @doc Utilities for parsing multipart/form-data.
 
 -module(mochiweb_multipart).
+
 -author('bob@mochimedia.com').
 
 -export([parse_form/1, parse_form/2]).
+
 -export([parse_multipart_request/2]).
+
 -export([parts_to_body/3, parts_to_multipart_body/4]).
+
 -export([default_file_handler/2]).
 
 -define(CHUNKSIZE, 4096).
 
--record(mp, {state, boundary, length, buffer, callback, req}).
+-record(mp,
+	{state, boundary, length, buffer, callback, req}).
 
 %% TODO: DOCUMENT THIS MODULE.
 %% @type key() = atom() | string() | binary().
@@ -47,28 +52,30 @@
 %%                     Size::integer()) -> {[header()], iolist()}
 %% @doc Return {[header()], iolist()} representing the body for the given
 %%      parts, may be a single part or multipart.
-parts_to_body([{Start, End, Body}], ContentType, Size) ->
+parts_to_body([{Start, End, Body}], ContentType,
+	      Size) ->
     HeaderList = [{"Content-Type", ContentType},
-                  {"Content-Range",
-                   ["bytes ",
-                    mochiweb_util:make_io(Start), "-", mochiweb_util:make_io(End),
-                    "/", mochiweb_util:make_io(Size)]}],
+		  {"Content-Range",
+		   ["bytes ", mochiweb_util:make_io(Start), "-",
+		    mochiweb_util:make_io(End), "/",
+		    mochiweb_util:make_io(Size)]}],
     {HeaderList, Body};
-parts_to_body(BodyList, ContentType, Size) when is_list(BodyList) ->
+parts_to_body(BodyList, ContentType, Size)
+    when is_list(BodyList) ->
     parts_to_multipart_body(BodyList, ContentType, Size,
-                            mochihex:to_hex(crypto:strong_rand_bytes(8))).
+			    mochihex:to_hex(crypto:strong_rand_bytes(8))).
 
 %% @spec parts_to_multipart_body([bodypart()], ContentType::string(),
 %%                               Size::integer(), Boundary::string()) ->
 %%           {[header()], iolist()}
 %% @doc Return {[header()], iolist()} representing the body for the given
 %%      parts, always a multipart response.
-parts_to_multipart_body(BodyList, ContentType, Size, Boundary) ->
+parts_to_multipart_body(BodyList, ContentType, Size,
+			Boundary) ->
     HeaderList = [{"Content-Type",
-                   ["multipart/byteranges; ",
-                    "boundary=", Boundary]}],
-    MultiPartBody = multipart_body(BodyList, ContentType, Boundary, Size),
-
+		   ["multipart/byteranges; ", "boundary=", Boundary]}],
+    MultiPartBody = multipart_body(BodyList, ContentType,
+				   Boundary, Size),
     {HeaderList, MultiPartBody}.
 
 %% @spec multipart_body([bodypart()], ContentType::string(),
@@ -76,14 +83,15 @@ parts_to_multipart_body(BodyList, ContentType, Size, Boundary) ->
 %% @doc Return the representation of a multipart body for the given [bodypart()].
 multipart_body([], _ContentType, Boundary, _Size) ->
     ["--", Boundary, "--\r\n"];
-multipart_body([{Start, End, Body} | BodyList], ContentType, Boundary, Size) ->
-    ["--", Boundary, "\r\n",
-     "Content-Type: ", ContentType, "\r\n",
-     "Content-Range: ",
-         "bytes ", mochiweb_util:make_io(Start), "-", mochiweb_util:make_io(End),
-             "/", mochiweb_util:make_io(Size), "\r\n\r\n",
-     Body, "\r\n"
-     | multipart_body(BodyList, ContentType, Boundary, Size)].
+multipart_body([{Start, End, Body} | BodyList],
+	       ContentType, Boundary, Size) ->
+    ["--", Boundary, "\r\n", "Content-Type: ", ContentType,
+     "\r\n", "Content-Range: ", "bytes ",
+     mochiweb_util:make_io(Start), "-",
+     mochiweb_util:make_io(End), "/",
+     mochiweb_util:make_io(Size), "\r\n\r\n", Body, "\r\n"
+     | multipart_body(BodyList, ContentType, Boundary,
+		      Size)].
 
 %% @spec parse_form(request()) -> [{string(), string() | formfile()}]
 %% @doc Parse a multipart form from the given request using the in-memory
@@ -94,168 +102,196 @@ parse_form(Req) ->
 %% @spec parse_form(request(), F::file_handler()) -> [{string(), string() | term()}]
 %% @doc Parse a multipart form from the given request using the given file_handler().
 parse_form(Req, FileHandler) ->
-    Callback = fun (Next) -> parse_form_outer(Next, FileHandler, []) end,
+    Callback = fun (Next) ->
+		       parse_form_outer(Next, FileHandler, [])
+	       end,
     {_, _, Res} = parse_multipart_request(Req, Callback),
     Res.
 
-parse_form_outer(eof, _, Acc) ->
-    lists:reverse(Acc);
+parse_form_outer(eof, _, Acc) -> lists:reverse(Acc);
 parse_form_outer({headers, H}, FileHandler, State) ->
-    {"form-data", H1} = proplists:get_value("content-disposition", H),
+    {"form-data", H1} =
+	proplists:get_value("content-disposition", H),
     Name = proplists:get_value("name", H1),
     Filename = proplists:get_value("filename", H1),
     case Filename of
-        undefined ->
-            fun (Next) ->
-                    parse_form_value(Next, {Name, []}, FileHandler, State)
-            end;
-        _ ->
-            ContentType = proplists:get_value("content-type", H),
-            Handler = FileHandler(Filename, ContentType),
-            fun (Next) ->
-                    parse_form_file(Next, {Name, Handler}, FileHandler, State)
-            end
+      undefined ->
+	  fun (Next) ->
+		  parse_form_value(Next, {Name, []}, FileHandler, State)
+	  end;
+      _ ->
+	  ContentType = proplists:get_value("content-type", H),
+	  Handler = FileHandler(Filename, ContentType),
+	  fun (Next) ->
+		  parse_form_file(Next, {Name, Handler}, FileHandler,
+				  State)
+	  end
     end.
 
-parse_form_value(body_end, {Name, Acc}, FileHandler, State) ->
-    Value = binary_to_list(iolist_to_binary(lists:reverse(Acc))),
+parse_form_value(body_end, {Name, Acc}, FileHandler,
+		 State) ->
+    Value =
+	binary_to_list(iolist_to_binary(lists:reverse(Acc))),
     State1 = [{Name, Value} | State],
-    fun (Next) -> parse_form_outer(Next, FileHandler, State1) end;
-parse_form_value({body, Data}, {Name, Acc}, FileHandler, State) ->
+    fun (Next) ->
+	    parse_form_outer(Next, FileHandler, State1)
+    end;
+parse_form_value({body, Data}, {Name, Acc}, FileHandler,
+		 State) ->
     Acc1 = [Data | Acc],
-    fun (Next) -> parse_form_value(Next, {Name, Acc1}, FileHandler, State) end.
+    fun (Next) ->
+	    parse_form_value(Next, {Name, Acc1}, FileHandler, State)
+    end.
 
-parse_form_file(body_end, {Name, Handler}, FileHandler, State) ->
+parse_form_file(body_end, {Name, Handler}, FileHandler,
+		State) ->
     Value = Handler(eof),
     State1 = [{Name, Value} | State],
-    fun (Next) -> parse_form_outer(Next, FileHandler, State1) end;
-parse_form_file({body, Data}, {Name, Handler}, FileHandler, State) ->
+    fun (Next) ->
+	    parse_form_outer(Next, FileHandler, State1)
+    end;
+parse_form_file({body, Data}, {Name, Handler},
+		FileHandler, State) ->
     H1 = Handler(Data),
-    fun (Next) -> parse_form_file(Next, {Name, H1}, FileHandler, State) end.
+    fun (Next) ->
+	    parse_form_file(Next, {Name, H1}, FileHandler, State)
+    end.
 
 default_file_handler(Filename, ContentType) ->
     default_file_handler_1(Filename, ContentType, []).
 
 default_file_handler_1(Filename, ContentType, Acc) ->
-    fun(eof) ->
-            Value = iolist_to_binary(lists:reverse(Acc)),
-            {Filename, ContentType, Value};
-       (Next) ->
-            default_file_handler_1(Filename, ContentType, [Next | Acc])
+    fun (eof) ->
+	    Value = iolist_to_binary(lists:reverse(Acc)),
+	    {Filename, ContentType, Value};
+	(Next) ->
+	    default_file_handler_1(Filename, ContentType,
+				   [Next | Acc])
     end.
 
 parse_multipart_request({ReqM, _} = Req, Callback) ->
     %% TODO: Support chunked?
-    Length = list_to_integer(ReqM:get_combined_header_value("content-length", Req)),
-    Boundary = iolist_to_binary(
-                 get_boundary(ReqM:get_header_value("content-type", Req))),
+    Length =
+	list_to_integer(ReqM:get_combined_header_value("content-length",
+						       Req)),
+    Boundary =
+	iolist_to_binary(get_boundary(ReqM:get_header_value("content-type",
+							    Req))),
     Prefix = <<"\r\n--", Boundary/binary>>,
     BS = byte_size(Boundary),
     Chunk = read_chunk(Req, Length),
     Length1 = Length - byte_size(Chunk),
-    <<"--", Boundary:BS/binary, "\r\n", Rest/binary>> = Chunk,
-    feed_mp(headers, flash_multipart_hack(#mp{boundary=Prefix,
-                                              length=Length1,
-                                              buffer=Rest,
-                                              callback=Callback,
-                                              req=Req})).
-
-parse_headers(<<>>) ->
-    [];
-parse_headers(Binary) ->
-    parse_headers(Binary, []).
+    <<"--", Boundary:BS/binary, "\r\n", Rest/binary>> =
+	Chunk,
+    feed_mp(headers,
+	    flash_multipart_hack(#mp{boundary = Prefix,
+				     length = Length1, buffer = Rest,
+				     callback = Callback, req = Req})).
+
+parse_headers(<<>>) -> [];
+parse_headers(Binary) -> parse_headers(Binary, []).
 
 parse_headers(Binary, Acc) ->
     case find_in_binary(<<"\r\n">>, Binary) of
-        {exact, N} ->
-            <<Line:N/binary, "\r\n", Rest/binary>> = Binary,
-            parse_headers(Rest, [split_header(Line) | Acc]);
-        not_found ->
-            lists:reverse([split_header(Binary) | Acc])
+      {exact, N} ->
+	  <<Line:N/binary, "\r\n", Rest/binary>> = Binary,
+	  parse_headers(Rest, [split_header(Line) | Acc]);
+      not_found -> lists:reverse([split_header(Binary) | Acc])
     end.
 
 split_header(Line) ->
-    {Name, [$: | Value]} = lists:splitwith(fun (C) -> C =/= $: end,
-                                           binary_to_list(Line)),
+    {Name, [$: | Value]} = lists:splitwith(fun (C) ->
+						   C =/= $:
+					   end,
+					   binary_to_list(Line)),
     {string:to_lower(string:strip(Name)),
      mochiweb_util:parse_header(Value)}.
 
 read_chunk({ReqM, _} = Req, Length) when Length > 0 ->
     case Length of
-        Length when Length < ?CHUNKSIZE ->
-            ReqM:recv(Length, Req);
-        _ ->
-            ReqM:recv(?CHUNKSIZE, Req)
+      Length when Length < (?CHUNKSIZE) ->
+	  ReqM:recv(Length, Req);
+      _ -> ReqM:recv(?CHUNKSIZE, Req)
     end.
 
-read_more(State=#mp{length=Length, buffer=Buffer, req=Req}) ->
+read_more(State = #mp{length = Length, buffer = Buffer,
+		      req = Req}) ->
     Data = read_chunk(Req, Length),
     Buffer1 = <<Buffer/binary, Data/binary>>,
-    flash_multipart_hack(State#mp{length=Length - byte_size(Data),
-                                  buffer=Buffer1}).
+    flash_multipart_hack(State#mp{length =
+				      Length - byte_size(Data),
+				  buffer = Buffer1}).
 
-flash_multipart_hack(State=#mp{length=0, buffer=Buffer, boundary=Prefix}) ->
+flash_multipart_hack(State = #mp{length = 0,
+				 buffer = Buffer, boundary = Prefix}) ->
     %% http://code.google.com/p/mochiweb/issues/detail?id=22
     %% Flash doesn't terminate multipart with \r\n properly so we fix it up here
     PrefixSize = size(Prefix),
     case size(Buffer) - (2 + PrefixSize) of
-        Seek when Seek >= 0 ->
-            case Buffer of
-                <<_:Seek/binary, Prefix:PrefixSize/binary, "--">> ->
-                    Buffer1 = <<Buffer/binary, "\r\n">>,
-                    State#mp{buffer=Buffer1};
-                _ ->
-                    State
-            end;
-        _ ->
-            State
+      Seek when Seek >= 0 ->
+	  case Buffer of
+	    <<_:Seek/binary, Prefix:PrefixSize/binary, "--">> ->
+		Buffer1 = <<Buffer/binary, "\r\n">>,
+		State#mp{buffer = Buffer1};
+	    _ -> State
+	  end;
+      _ -> State
     end;
-flash_multipart_hack(State) ->
-    State.
-
-feed_mp(headers, State=#mp{buffer=Buffer, callback=Callback}) ->
-    {State1, P} = case find_in_binary(<<"\r\n\r\n">>, Buffer) of
-                      {exact, N} ->
-                          {State, N};
-                      _ ->
-                          S1 = read_more(State),
-                          %% Assume headers must be less than ?CHUNKSIZE
-                          {exact, N} = find_in_binary(<<"\r\n\r\n">>,
-                                                      S1#mp.buffer),
-                          {S1, N}
-                  end,
-    <<Headers:P/binary, "\r\n\r\n", Rest/binary>> = State1#mp.buffer,
-    NextCallback = Callback({headers, parse_headers(Headers)}),
-    feed_mp(body, State1#mp{buffer=Rest,
-                            callback=NextCallback});
-feed_mp(body, State=#mp{boundary=Prefix, buffer=Buffer, callback=Callback}) ->
+flash_multipart_hack(State) -> State.
+
+feed_mp(headers,
+	State = #mp{buffer = Buffer, callback = Callback}) ->
+    {State1, P} = case find_in_binary(<<"\r\n\r\n">>,
+				      Buffer)
+		      of
+		    {exact, N} -> {State, N};
+		    _ ->
+			S1 = read_more(State),
+			%% Assume headers must be less than ?CHUNKSIZE
+			{exact, N} = find_in_binary(<<"\r\n\r\n">>,
+						    S1#mp.buffer),
+			{S1, N}
+		  end,
+    <<Headers:P/binary, "\r\n\r\n", Rest/binary>> =
+	State1#mp.buffer,
+    NextCallback = Callback({headers,
+			     parse_headers(Headers)}),
+    feed_mp(body,
+	    State1#mp{buffer = Rest, callback = NextCallback});
+feed_mp(body,
+	State = #mp{boundary = Prefix, buffer = Buffer,
+		    callback = Callback}) ->
     Boundary = find_boundary(Prefix, Buffer),
     case Boundary of
-        {end_boundary, Start, Skip} ->
-            <<Data:Start/binary, _:Skip/binary, Rest/binary>> = Buffer,
-            C1 = Callback({body, Data}),
-            C2 = C1(body_end),
-            {State#mp.length, Rest, C2(eof)};
-        {next_boundary, Start, Skip} ->
-            <<Data:Start/binary, _:Skip/binary, Rest/binary>> = Buffer,
-            C1 = Callback({body, Data}),
-            feed_mp(headers, State#mp{callback=C1(body_end),
-                                      buffer=Rest});
-        {maybe, Start} ->
-            <<Data:Start/binary, Rest/binary>> = Buffer,
-            feed_mp(body, read_more(State#mp{callback=Callback({body, Data}),
-                                             buffer=Rest}));
-        not_found ->
-            {Data, Rest} = {Buffer, <<>>},
-            feed_mp(body, read_more(State#mp{callback=Callback({body, Data}),
-                                             buffer=Rest}))
+      {end_boundary, Start, Skip} ->
+	  <<Data:Start/binary, _:Skip/binary, Rest/binary>> =
+	      Buffer,
+	  C1 = Callback({body, Data}),
+	  C2 = C1(body_end),
+	  {State#mp.length, Rest, C2(eof)};
+      {next_boundary, Start, Skip} ->
+	  <<Data:Start/binary, _:Skip/binary, Rest/binary>> =
+	      Buffer,
+	  C1 = Callback({body, Data}),
+	  feed_mp(headers,
+		  State#mp{callback = C1(body_end), buffer = Rest});
+      {maybe, Start} ->
+	  <<Data:Start/binary, Rest/binary>> = Buffer,
+	  feed_mp(body,
+		  read_more(State#mp{callback = Callback({body, Data}),
+				     buffer = Rest}));
+      not_found ->
+	  {Data, Rest} = {Buffer, <<>>},
+	  feed_mp(body,
+		  read_more(State#mp{callback = Callback({body, Data}),
+				     buffer = Rest}))
     end.
 
 get_boundary(ContentType) ->
-    {"multipart/form-data", Opts} = mochiweb_util:parse_header(ContentType),
+    {"multipart/form-data", Opts} =
+	mochiweb_util:parse_header(ContentType),
     case proplists:get_value("boundary", Opts) of
-        S when is_list(S) ->
-            S
+      S when is_list(S) -> S
     end.
 
 %% @spec find_in_binary(Pattern::binary(), Data::binary()) ->
@@ -265,323 +301,332 @@ find_in_binary(P, Data) when size(P) > 0 ->
     PS = size(P),
     DS = size(Data),
     case DS - PS of
-        Last when Last < 0 ->
-            partial_find(P, Data, 0, DS);
-        Last ->
-            case binary:match(Data, P) of
-                {Pos, _} -> {exact, Pos};
-                nomatch -> partial_find(P, Data, Last+1, PS-1)
-            end
+      Last when Last < 0 -> partial_find(P, Data, 0, DS);
+      Last ->
+	  case binary:match(Data, P) of
+	    {Pos, _} -> {exact, Pos};
+	    nomatch -> partial_find(P, Data, Last + 1, PS - 1)
+	  end
     end.
 
-partial_find(_B, _D, _N, 0) ->
-    not_found;
+partial_find(_B, _D, _N, 0) -> not_found;
 partial_find(B, D, N, K) ->
     <<B1:K/binary, _/binary>> = B,
     case D of
-        <<_Skip:N/binary, B1:K/binary>> ->
-            {partial, N, K};
-        _ ->
-            partial_find(B, D, 1 + N, K - 1)
+      <<_Skip:N/binary, B1:K/binary>> -> {partial, N, K};
+      _ -> partial_find(B, D, 1 + N, K - 1)
     end.
 
 find_boundary(Prefix, Data) ->
     case find_in_binary(Prefix, Data) of
-        {exact, Skip} ->
-            PrefixSkip = Skip + size(Prefix),
-            case Data of
-                <<_:PrefixSkip/binary, "\r\n", _/binary>> ->
-                    {next_boundary, Skip, size(Prefix) + 2};
-                <<_:PrefixSkip/binary, "--\r\n", _/binary>> ->
-                    {end_boundary, Skip, size(Prefix) + 4};
-                _ when size(Data) < PrefixSkip + 4 ->
-                    %% Underflow
-                    {maybe, Skip};
-                _ ->
-                    %% False positive
-                    not_found
-            end;
-        {partial, Skip, Length} when (Skip + Length) =:= size(Data) ->
-            %% Underflow
-            {maybe, Skip};
-        _ ->
-            not_found
+      {exact, Skip} ->
+	  PrefixSkip = Skip + size(Prefix),
+	  case Data of
+	    <<_:PrefixSkip/binary, "\r\n", _/binary>> ->
+		{next_boundary, Skip, size(Prefix) + 2};
+	    <<_:PrefixSkip/binary, "--\r\n", _/binary>> ->
+		{end_boundary, Skip, size(Prefix) + 4};
+	    _ when size(Data) < PrefixSkip + 4 ->
+		%% Underflow
+		{maybe, Skip};
+	    _ ->
+		%% False positive
+		not_found
+	  end;
+      {partial, Skip, Length}
+	  when Skip + Length =:= size(Data) ->
+	  %% Underflow
+	  {maybe, Skip};
+      _ -> not_found
     end.
 
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
 
 ssl_cert_opts() ->
     EbinDir = filename:dirname(code:which(?MODULE)),
-    CertDir = filename:join([EbinDir, "..", "support", "test-materials"]),
+    CertDir = filename:join([EbinDir, "..", "support",
+			     "test-materials"]),
     CertFile = filename:join(CertDir, "test_ssl_cert.pem"),
     KeyFile = filename:join(CertDir, "test_ssl_key.pem"),
     [{certfile, CertFile}, {keyfile, KeyFile}].
 
 with_socket_server(Transport, ServerFun, ClientFun) ->
-    ServerOpts0 = [{ip, "127.0.0.1"}, {port, 0}, {loop, ServerFun}],
+    ServerOpts0 = [{ip, "127.0.0.1"}, {port, 0},
+		   {loop, ServerFun}],
     ServerOpts = case Transport of
-        plain ->
-            ServerOpts0;
-        ssl ->
-            ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}]
-    end,
-    {ok, Server} = mochiweb_socket_server:start_link(ServerOpts),
+		   plain -> ServerOpts0;
+		   ssl ->
+		       ServerOpts0 ++
+			 [{ssl, true}, {ssl_opts, ssl_cert_opts()}]
+		 end,
+    {ok, Server} =
+	mochiweb_socket_server:start_link(ServerOpts),
     Port = mochiweb_socket_server:get(Server, port),
     ClientOpts = [binary, {active, false}],
     {ok, Client} = case Transport of
-        plain ->
-            gen_tcp:connect("127.0.0.1", Port, ClientOpts);
-        ssl ->
-            ClientOpts1 = mochiweb_test_util:ssl_client_opts(ClientOpts),
-            {ok, SslSocket} = ssl:connect("127.0.0.1", Port, ClientOpts1),
-            {ok, {ssl, SslSocket}}
-    end,
+		     plain -> gen_tcp:connect("127.0.0.1", Port, ClientOpts);
+		     ssl ->
+			 ClientOpts1 =
+			     mochiweb_test_util:ssl_client_opts(ClientOpts),
+			 {ok, SslSocket} = ssl:connect("127.0.0.1", Port,
+						       ClientOpts1),
+			 {ok, {ssl, SslSocket}}
+		   end,
     Res = (catch ClientFun(Client)),
     mochiweb_socket_server:stop(Server),
     Res.
 
 fake_request(Socket, ContentType, Length) ->
-    mochiweb_request:new(Socket,
-                         'POST',
-                         "/multipart",
-                         {1,1},
-                         mochiweb_headers:make(
-                           [{"content-type", ContentType},
-                            {"content-length", Length}])).
-
-test_callback({body, <<>>}, Rest=[body_end | _]) ->
+    mochiweb_request:new(Socket, 'POST', "/multipart",
+			 {1, 1},
+			 mochiweb_headers:make([{"content-type", ContentType},
+						{"content-length", Length}])).
+
+test_callback({body, <<>>}, Rest = [body_end | _]) ->
     %% When expecting the body_end we might get an empty binary
     fun (Next) -> test_callback(Next, Rest) end;
-test_callback({body, Got}, [{body, Expect} | Rest]) when Got =/= Expect ->
+test_callback({body, Got}, [{body, Expect} | Rest])
+    when Got =/= Expect ->
     %% Partial response
     GotSize = size(Got),
     <<Got:GotSize/binary, Expect1/binary>> = Expect,
-    fun (Next) -> test_callback(Next, [{body, Expect1} | Rest]) end;
+    fun (Next) ->
+	    test_callback(Next, [{body, Expect1} | Rest])
+    end;
 test_callback(Got, [Expect | Rest]) ->
     ?assertEqual(Got, Expect),
     case Rest of
-        [] ->
-            ok;
-        _ ->
-            fun (Next) -> test_callback(Next, Rest) end
+      [] -> ok;
+      _ -> fun (Next) -> test_callback(Next, Rest) end
     end.
 
-parse3_http_test() ->
-    parse3(plain).
+parse3_http_test() -> parse3(plain).
 
-parse3_https_test() ->
-    parse3(ssl).
+parse3_https_test() -> parse3(ssl).
 
 parse3(Transport) ->
-    ContentType = "multipart/form-data; boundary=---------------------------7386909285754635891697677882",
-    BinContent = <<"-----------------------------7386909285754635891697677882\r\nContent-Disposition: form-data; name=\"hidden\"\r\n\r\nmultipart message\r\n-----------------------------7386909285754635891697677882\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test_file.txt\"\r\nContent-Type: text/plain\r\n\r\nWoo multiline text file\n\nLa la la\r\n-----------------------------7386909285754635891697677882--\r\n">>,
+    ContentType =
+	"multipart/form-data; boundary=---------------"
+	"------------7386909285754635891697677882",
+    BinContent =
+	<<"-----------------------------7386909285754635"
+	  "891697677882\r\nContent-Disposition: "
+	  "form-data; name=\"hidden\"\r\n\r\nmultipart "
+	  "message\r\n-----------------------------73869"
+	  "09285754635891697677882\r\nContent-Dispositio"
+	  "n: form-data; name=\"file\"; filename=\"test_"
+	  "file.txt\"\r\nContent-Type: text/plain\r\n\r\n"
+	  "Woo multiline text file\n\nLa la la\r\n------"
+	  "-----------------------7386909285754635891697"
+	  "677882--\r\n">>,
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "hidden"}]}}]},
-              {body, <<"multipart message">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "file"}, {"filename", "test_file.txt"}]}},
-                {"content-type", {"text/plain", []}}]},
-              {body, <<"Woo multiline text file\n\nLa la la">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "hidden"}]}}]},
+	      {body, <<"multipart message">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "file"}, {"filename", "test_file.txt"}]}},
+		{"content-type", {"text/plain", []}}]},
+	      {body, <<"Woo multiline text file\n\nLa la la">>},
+	      body_end, eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
-parse2_http_test() ->
-    parse2(plain).
+parse2_http_test() -> parse2(plain).
 
-parse2_https_test() ->
-    parse2(ssl).
+parse2_https_test() -> parse2(ssl).
 
 parse2(Transport) ->
-    ContentType = "multipart/form-data; boundary=---------------------------6072231407570234361599764024",
-    BinContent = <<"-----------------------------6072231407570234361599764024\r\nContent-Disposition: form-data; name=\"hidden\"\r\n\r\nmultipart message\r\n-----------------------------6072231407570234361599764024\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----------------------------6072231407570234361599764024--\r\n">>,
+    ContentType =
+	"multipart/form-data; boundary=---------------"
+	"------------6072231407570234361599764024",
+    BinContent =
+	<<"-----------------------------6072231407570234"
+	  "361599764024\r\nContent-Disposition: "
+	  "form-data; name=\"hidden\"\r\n\r\nmultipart "
+	  "message\r\n-----------------------------60722"
+	  "31407570234361599764024\r\nContent-Dispositio"
+	  "n: form-data; name=\"file\"; filename=\"\"\r\n"
+	  "Content-Type: application/octet-stream\r\n\r\n\r\n"
+	  "-----------------------------6072231407570234"
+	  "361599764024--\r\n">>,
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "hidden"}]}}]},
-              {body, <<"multipart message">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "file"}, {"filename", ""}]}},
-                {"content-type", {"application/octet-stream", []}}]},
-              {body, <<>>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "hidden"}]}}]},
+	      {body, <<"multipart message">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "file"}, {"filename", ""}]}},
+		{"content-type", {"application/octet-stream", []}}]},
+	      {body, <<>>}, body_end, eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
-parse_form_http_test() ->
-    do_parse_form(plain).
+parse_form_http_test() -> do_parse_form(plain).
 
-parse_form_https_test() ->
-    do_parse_form(ssl).
+parse_form_https_test() -> do_parse_form(ssl).
 
 do_parse_form(Transport) ->
     ContentType = "multipart/form-data; boundary=AaB03x",
     "AaB03x" = get_boundary(ContentType),
-    Content = mochiweb_util:join(
-                ["--AaB03x",
-                 "Content-Disposition: form-data; name=\"submit-name\"",
-                 "",
-                 "Larry",
-                 "--AaB03x",
-                 "Content-Disposition: form-data; name=\"files\";"
-                 ++ "filename=\"file1.txt\"",
-                 "Content-Type: text/plain",
-                 "",
-                 "... contents of file1.txt ...",
-                 "--AaB03x--",
-                 ""], "\r\n"),
+    Content = mochiweb_util:join(["--AaB03x",
+				  "Content-Disposition: form-data; name=\"submit"
+				  "-name\"",
+				  "", "Larry", "--AaB03x",
+				  "Content-Disposition: form-data; name=\"files\";"
+				    ++ "filename=\"file1.txt\"",
+				  "Content-Type: text/plain", "",
+				  "... contents of file1.txt ...", "--AaB03x--",
+				  ""],
+				 "\r\n"),
     BinContent = iolist_to_binary(Content),
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_form(Req),
-                        [{"submit-name", "Larry"},
-                         {"files", {"file1.txt", {"text/plain",[]},
-                                    <<"... contents of file1.txt ...">>}
-                         }] = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_form(Req),
+			[{"submit-name", "Larry"},
+			 {"files",
+			  {"file1.txt", {"text/plain", []},
+			   <<"... contents of file1.txt ...">>}}] =
+			    Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
-parse_http_test() ->
-    do_parse(plain).
+parse_http_test() -> do_parse(plain).
 
-parse_https_test() ->
-    do_parse(ssl).
+parse_https_test() -> do_parse(ssl).
 
 do_parse(Transport) ->
     ContentType = "multipart/form-data; boundary=AaB03x",
     "AaB03x" = get_boundary(ContentType),
-    Content = mochiweb_util:join(
-                ["--AaB03x",
-                 "Content-Disposition: form-data; name=\"submit-name\"",
-                 "",
-                 "Larry",
-                 "--AaB03x",
-                 "Content-Disposition: form-data; name=\"files\";"
-                 ++ "filename=\"file1.txt\"",
-                 "Content-Type: text/plain",
-                 "",
-                 "... contents of file1.txt ...",
-                 "--AaB03x--",
-                 ""], "\r\n"),
+    Content = mochiweb_util:join(["--AaB03x",
+				  "Content-Disposition: form-data; name=\"submit"
+				  "-name\"",
+				  "", "Larry", "--AaB03x",
+				  "Content-Disposition: form-data; name=\"files\";"
+				    ++ "filename=\"file1.txt\"",
+				  "Content-Type: text/plain", "",
+				  "... contents of file1.txt ...", "--AaB03x--",
+				  ""],
+				 "\r\n"),
     BinContent = iolist_to_binary(Content),
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "submit-name"}]}}]},
-              {body, <<"Larry">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}},
-                 {"content-type", {"text/plain", []}}]},
-              {body, <<"... contents of file1.txt ...">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "submit-name"}]}}]},
+	      {body, <<"Larry">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "files"}, {"filename", "file1.txt"}]}},
+		{"content-type", {"text/plain", []}}]},
+	      {body, <<"... contents of file1.txt ...">>}, body_end,
+	      eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
 parse_partial_body_boundary_http_test() ->
-   parse_partial_body_boundary(plain).
+    parse_partial_body_boundary(plain).
 
 parse_partial_body_boundary_https_test() ->
-   parse_partial_body_boundary(ssl).
+    parse_partial_body_boundary(ssl).
 
 parse_partial_body_boundary(Transport) ->
     Boundary = string:copies("$", 2048),
-    ContentType = "multipart/form-data; boundary=" ++ Boundary,
-    ?assertEqual(Boundary, get_boundary(ContentType)),
-    Content = mochiweb_util:join(
-                ["--" ++ Boundary,
-                 "Content-Disposition: form-data; name=\"submit-name\"",
-                 "",
-                 "Larry",
-                 "--" ++ Boundary,
-                 "Content-Disposition: form-data; name=\"files\";"
-                 ++ "filename=\"file1.txt\"",
-                 "Content-Type: text/plain",
-                 "",
-                 "... contents of file1.txt ...",
-                 "--" ++ Boundary ++ "--",
-                 ""], "\r\n"),
+    ContentType = "multipart/form-data; boundary=" ++
+		    Boundary,
+    ?assertEqual(Boundary, (get_boundary(ContentType))),
+    Content = mochiweb_util:join(["--" ++ Boundary,
+				  "Content-Disposition: form-data; name=\"submit"
+				  "-name\"",
+				  "", "Larry", "--" ++ Boundary,
+				  "Content-Disposition: form-data; name=\"files\";"
+				    ++ "filename=\"file1.txt\"",
+				  "Content-Type: text/plain", "",
+				  "... contents of file1.txt ...",
+				  "--" ++ Boundary ++ "--", ""],
+				 "\r\n"),
     BinContent = iolist_to_binary(Content),
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "submit-name"}]}}]},
-              {body, <<"Larry">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}},
-                {"content-type", {"text/plain", []}}
-               ]},
-              {body, <<"... contents of file1.txt ...">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "submit-name"}]}}]},
+	      {body, <<"Larry">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "files"}, {"filename", "file1.txt"}]}},
+		{"content-type", {"text/plain", []}}]},
+	      {body, <<"... contents of file1.txt ...">>}, body_end,
+	      eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
 parse_large_header_http_test() ->
@@ -593,64 +638,69 @@ parse_large_header_https_test() ->
 parse_large_header(Transport) ->
     ContentType = "multipart/form-data; boundary=AaB03x",
     "AaB03x" = get_boundary(ContentType),
-    Content = mochiweb_util:join(
-                ["--AaB03x",
-                 "Content-Disposition: form-data; name=\"submit-name\"",
-                 "",
-                 "Larry",
-                 "--AaB03x",
-                 "Content-Disposition: form-data; name=\"files\";"
-                 ++ "filename=\"file1.txt\"",
-                 "Content-Type: text/plain",
-                 "x-large-header: " ++ string:copies("%", 4096),
-                 "",
-                 "... contents of file1.txt ...",
-                 "--AaB03x--",
-                 ""], "\r\n"),
+    Content = mochiweb_util:join(["--AaB03x",
+				  "Content-Disposition: form-data; name=\"submit"
+				  "-name\"",
+				  "", "Larry", "--AaB03x",
+				  "Content-Disposition: form-data; name=\"files\";"
+				    ++ "filename=\"file1.txt\"",
+				  "Content-Type: text/plain",
+				  "x-large-header: " ++
+				    string:copies("%", 4096),
+				  "", "... contents of file1.txt ...",
+				  "--AaB03x--", ""],
+				 "\r\n"),
     BinContent = iolist_to_binary(Content),
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "submit-name"}]}}]},
-              {body, <<"Larry">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}},
-                {"content-type", {"text/plain", []}},
-                {"x-large-header", {string:copies("%", 4096), []}}
-               ]},
-              {body, <<"... contents of file1.txt ...">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "submit-name"}]}}]},
+	      {body, <<"Larry">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "files"}, {"filename", "file1.txt"}]}},
+		{"content-type", {"text/plain", []}},
+		{"x-large-header", {string:copies("%", 4096), []}}]},
+	      {body, <<"... contents of file1.txt ...">>}, body_end,
+	      eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
 find_boundary_test() ->
     B = <<"\r\n--X">>,
-    {next_boundary, 0, 7} = find_boundary(B, <<"\r\n--X\r\nRest">>),
-    {next_boundary, 1, 7} = find_boundary(B, <<"!\r\n--X\r\nRest">>),
-    {end_boundary, 0, 9} = find_boundary(B, <<"\r\n--X--\r\nRest">>),
-    {end_boundary, 1, 9} = find_boundary(B, <<"!\r\n--X--\r\nRest">>),
+    {next_boundary, 0, 7} = find_boundary(B,
+					  <<"\r\n--X\r\nRest">>),
+    {next_boundary, 1, 7} = find_boundary(B,
+					  <<"!\r\n--X\r\nRest">>),
+    {end_boundary, 0, 9} = find_boundary(B,
+					 <<"\r\n--X--\r\nRest">>),
+    {end_boundary, 1, 9} = find_boundary(B,
+					 <<"!\r\n--X--\r\nRest">>),
     not_found = find_boundary(B, <<"--X\r\nRest">>),
     {maybe, 0} = find_boundary(B, <<"\r\n--X\r">>),
     {maybe, 1} = find_boundary(B, <<"!\r\n--X\r">>),
-    P = <<"\r\n-----------------------------16037454351082272548568224146">>,
-    B0 = <<55,212,131,77,206,23,216,198,35,87,252,118,252,8,25,211,132,229,
-          182,42,29,188,62,175,247,243,4,4,0,59, 13,10,45,45,45,45,45,45,45,
-          45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
-          49,54,48,51,55,52,53,52,51,53,49>>,
+    P = <<"\r\n-----------------------------160374543510"
+	  "82272548568224146">>,
+    B0 = <<55, 212, 131, 77, 206, 23, 216, 198, 35, 87, 252,
+	   118, 252, 8, 25, 211, 132, 229, 182, 42, 29, 188, 62,
+	   175, 247, 243, 4, 4, 0, 59, 13, 10, 45, 45, 45, 45, 45,
+	   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 49, 54, 48, 51,
+	   55, 52, 53, 52, 51, 53, 49>>,
     {maybe, 30} = find_boundary(P, B0),
     not_found = find_boundary(B, <<"\r\n--XJOPKE">>),
     ok.
@@ -660,231 +710,262 @@ find_in_binary_test() ->
     {exact, 1} = find_in_binary(<<"oo">>, <<"foobarbaz">>),
     {exact, 8} = find_in_binary(<<"z">>, <<"foobarbaz">>),
     not_found = find_in_binary(<<"q">>, <<"foobarbaz">>),
-    {partial, 7, 2} = find_in_binary(<<"azul">>, <<"foobarbaz">>),
-    {exact, 0} = find_in_binary(<<"foobarbaz">>, <<"foobarbaz">>),
-    {partial, 0, 3} = find_in_binary(<<"foobar">>, <<"foo">>),
-    {partial, 1, 3} = find_in_binary(<<"foobar">>, <<"afoo">>),
+    {partial, 7, 2} = find_in_binary(<<"azul">>,
+				     <<"foobarbaz">>),
+    {exact, 0} = find_in_binary(<<"foobarbaz">>,
+				<<"foobarbaz">>),
+    {partial, 0, 3} = find_in_binary(<<"foobar">>,
+				     <<"foo">>),
+    {partial, 1, 3} = find_in_binary(<<"foobar">>,
+				     <<"afoo">>),
     ok.
 
-flash_parse_http_test() ->
-    flash_parse(plain).
+flash_parse_http_test() -> flash_parse(plain).
 
-flash_parse_https_test() ->
-    flash_parse(ssl).
+flash_parse_https_test() -> flash_parse(ssl).
 
 flash_parse(Transport) ->
-    ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
-    "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" = get_boundary(ContentType),
-    BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\nhello\n\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Dis [...]
+    ContentType =
+	"multipart/form-data; boundary=----------ei4GI"
+	"3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
+    "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" =
+	get_boundary(ContentType),
+    BinContent =
+	<<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\n"
+	  "Content-Disposition: form-data; name=\"Filena"
+	  "me\"\r\n\r\nhello.txt\r\n------------ei4GI3GI"
+	  "3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition"
+	  ": form-data; name=\"success_action_status\"\r\n\r\n"
+	  "201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei"
+	  "4Ij5\r\nContent-Disposition: form-data; "
+	  "name=\"file\"; filename=\"hello.txt\"\r\nCont"
+	  "ent-Type: application/octet-stream\r\n\r\nhel"
+	  "lo\n\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5e"
+	  "i4Ij5\r\nContent-Disposition: form-data; "
+	  "name=\"Upload\"\r\n\r\nSubmit Query\r\n------"
+	  "------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>,
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Filename"}]}}]},
-              {body, <<"hello.txt">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "success_action_status"}]}}]},
-              {body, <<"201">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}},
-                {"content-type", {"application/octet-stream", []}}]},
-              {body, <<"hello\n">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Upload"}]}}]},
-              {body, <<"Submit Query">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Filename"}]}}]},
+	      {body, <<"hello.txt">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "success_action_status"}]}}]},
+	      {body, <<"201">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "file"}, {"filename", "hello.txt"}]}},
+		{"content-type", {"application/octet-stream", []}}]},
+	      {body, <<"hello\n">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Upload"}]}}]},
+	      {body, <<"Submit Query">>}, body_end, eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
-flash_parse2_http_test() ->
-    flash_parse2(plain).
+flash_parse2_http_test() -> flash_parse2(plain).
 
-flash_parse2_https_test() ->
-    flash_parse2(ssl).
+flash_parse2_https_test() -> flash_parse2(ssl).
 
 flash_parse2(Transport) ->
-    ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
-    "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" = get_boundary(ContentType),
+    ContentType =
+	"multipart/form-data; boundary=----------ei4GI"
+	"3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
+    "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" =
+	get_boundary(ContentType),
     Chunk = iolist_to_binary(string:copies("%", 4096)),
-    BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n", Chunk/binary, "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\n [...]
+    BinContent =
+	<<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\n"
+	  "Content-Disposition: form-data; name=\"Filena"
+	  "me\"\r\n\r\nhello.txt\r\n------------ei4GI3GI"
+	  "3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition"
+	  ": form-data; name=\"success_action_status\"\r\n\r\n"
+	  "201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei"
+	  "4Ij5\r\nContent-Disposition: form-data; "
+	  "name=\"file\"; filename=\"hello.txt\"\r\nCont"
+	  "ent-Type: application/octet-stream\r\n\r\n",
+	  Chunk/binary,
+	  "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij"
+	  "5\r\nContent-Disposition: form-data; "
+	  "name=\"Upload\"\r\n\r\nSubmit Query\r\n------"
+	  "------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>,
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Filename"}]}}]},
-              {body, <<"hello.txt">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "success_action_status"}]}}]},
-              {body, <<"201">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}},
-                {"content-type", {"application/octet-stream", []}}]},
-              {body, Chunk},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Upload"}]}}]},
-              {body, <<"Submit Query">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Filename"}]}}]},
+	      {body, <<"hello.txt">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "success_action_status"}]}}]},
+	      {body, <<"201">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "file"}, {"filename", "hello.txt"}]}},
+		{"content-type", {"application/octet-stream", []}}]},
+	      {body, Chunk}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Upload"}]}}]},
+	      {body, <<"Submit Query">>}, body_end, eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
-    ok = with_socket_server(Transport, ServerFun, ClientFun),
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
+    ok = with_socket_server(Transport, ServerFun,
+			    ClientFun),
     ok.
 
 parse_headers_test() ->
-    ?assertEqual([], parse_headers(<<>>)).
+    ?assertEqual([], (parse_headers(<<>>))).
 
 flash_multipart_hack_test() ->
     Buffer = <<"prefix-">>,
     Prefix = <<"prefix">>,
-    State = #mp{length=0, buffer=Buffer, boundary=Prefix},
-    ?assertEqual(State,
-                 flash_multipart_hack(State)).
+    State = #mp{length = 0, buffer = Buffer,
+		boundary = Prefix},
+    ?assertEqual(State, (flash_multipart_hack(State))).
 
 parts_to_body_single_test() ->
     {HL, B} = parts_to_body([{0, 5, <<"01234">>}],
-                            "text/plain",
-                            10),
-    [{"Content-Range", Range},
-     {"Content-Type", Type}] = lists:sort(HL),
-    ?assertEqual(
-       <<"bytes 0-5/10">>,
-       iolist_to_binary(Range)),
-    ?assertEqual(
-       <<"text/plain">>,
-       iolist_to_binary(Type)),
-    ?assertEqual(
-       <<"01234">>,
-       iolist_to_binary(B)),
+			    "text/plain", 10),
+    [{"Content-Range", Range}, {"Content-Type", Type}] =
+	lists:sort(HL),
+    ?assertEqual(<<"bytes 0-5/10">>,
+		 (iolist_to_binary(Range))),
+    ?assertEqual(<<"text/plain">>,
+		 (iolist_to_binary(Type))),
+    ?assertEqual(<<"01234">>, (iolist_to_binary(B))),
     ok.
 
 parts_to_body_multi_test() ->
-    {[{"Content-Type", Type}],
-     _B} = parts_to_body([{0, 5, <<"01234">>}, {5, 10, <<"56789">>}],
-                        "text/plain",
-                        10),
-    ?assertMatch(
-       <<"multipart/byteranges; boundary=", _/binary>>,
-       iolist_to_binary(Type)),
+    {[{"Content-Type", Type}], _B} = parts_to_body([{0, 5,
+						     <<"01234">>},
+						    {5, 10, <<"56789">>}],
+						   "text/plain", 10),
+    ?assertMatch(<<"multipart/byteranges; boundary=",
+		   _/binary>>,
+		 (iolist_to_binary(Type))),
     ok.
 
 parts_to_multipart_body_test() ->
-    {[{"Content-Type", V}], B} = parts_to_multipart_body(
-                                   [{0, 5, <<"01234">>}, {5, 10, <<"56789">>}],
-                                   "text/plain",
-                                   10,
-                                   "BOUNDARY"),
-    MB = multipart_body(
-           [{0, 5, <<"01234">>}, {5, 10, <<"56789">>}],
-           "text/plain",
-           "BOUNDARY",
-           10),
-    ?assertEqual(
-       <<"multipart/byteranges; boundary=BOUNDARY">>,
-       iolist_to_binary(V)),
-    ?assertEqual(
-       iolist_to_binary(MB),
-       iolist_to_binary(B)),
+    {[{"Content-Type", V}], B} =
+	parts_to_multipart_body([{0, 5, <<"01234">>},
+				 {5, 10, <<"56789">>}],
+				"text/plain", 10, "BOUNDARY"),
+    MB = multipart_body([{0, 5, <<"01234">>},
+			 {5, 10, <<"56789">>}],
+			"text/plain", "BOUNDARY", 10),
+    ?assertEqual(<<"multipart/byteranges; boundary=BOUNDARY">>,
+		 (iolist_to_binary(V))),
+    ?assertEqual((iolist_to_binary(MB)),
+		 (iolist_to_binary(B))),
     ok.
 
 multipart_body_test() ->
-    ?assertEqual(
-       <<"--BOUNDARY--\r\n">>,
-       iolist_to_binary(multipart_body([], "text/plain", "BOUNDARY", 0))),
-    ?assertEqual(
-       <<"--BOUNDARY\r\n"
-         "Content-Type: text/plain\r\n"
-         "Content-Range: bytes 0-5/10\r\n\r\n"
-         "01234\r\n"
-         "--BOUNDARY\r\n"
-         "Content-Type: text/plain\r\n"
-         "Content-Range: bytes 5-10/10\r\n\r\n"
-         "56789\r\n"
-         "--BOUNDARY--\r\n">>,
-       iolist_to_binary(multipart_body([{0, 5, <<"01234">>}, {5, 10, <<"56789">>}],
-                                       "text/plain",
-                                       "BOUNDARY",
-                                       10))),
+    ?assertEqual(<<"--BOUNDARY--\r\n">>,
+		 (iolist_to_binary(multipart_body([], "text/plain",
+						  "BOUNDARY", 0)))),
+    ?assertEqual(<<"--BOUNDARY\r\nContent-Type: text/plain\r\nCon"
+		   "tent-Range: bytes 0-5/10\r\n\r\n01234\r\n--BO"
+		   "UNDARY\r\nContent-Type: text/plain\r\nContent"
+		   "-Range: bytes 5-10/10\r\n\r\n56789\r\n--BOUND"
+		   "ARY--\r\n">>,
+		 (iolist_to_binary(multipart_body([{0, 5, <<"01234">>},
+						   {5, 10, <<"56789">>}],
+						  "text/plain", "BOUNDARY",
+						  10)))),
     ok.
 
 %% @todo Move somewhere more appropriate than in the test suite
 
 multipart_parsing_benchmark_test() ->
-  run_multipart_parsing_benchmark(1).
+    run_multipart_parsing_benchmark(1).
 
 run_multipart_parsing_benchmark(0) -> ok;
 run_multipart_parsing_benchmark(N) ->
-     multipart_parsing_benchmark(),
-     run_multipart_parsing_benchmark(N-1).
+    multipart_parsing_benchmark(),
+    run_multipart_parsing_benchmark(N - 1).
 
 multipart_parsing_benchmark() ->
-    ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
-    Chunk = binary:copy(<<"This Is_%Some=Quite0Long4String2Used9For7BenchmarKing.5">>, 102400),
-    BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n", Chunk/binary, "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\n [...]
+    ContentType =
+	"multipart/form-data; boundary=----------ei4GI"
+	"3GI3Ij5Ef1ae0KM7Ij5ei4Ij5",
+    Chunk =
+	binary:copy(<<"This Is_%Some=Quite0Long4String2Used9For7Benc"
+		      "hmarKing.5">>,
+		    102400),
+    BinContent =
+	<<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\n"
+	  "Content-Disposition: form-data; name=\"Filena"
+	  "me\"\r\n\r\nhello.txt\r\n------------ei4GI3GI"
+	  "3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition"
+	  ": form-data; name=\"success_action_status\"\r\n\r\n"
+	  "201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei"
+	  "4Ij5\r\nContent-Disposition: form-data; "
+	  "name=\"file\"; filename=\"hello.txt\"\r\nCont"
+	  "ent-Type: application/octet-stream\r\n\r\n",
+	  Chunk/binary,
+	  "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij"
+	  "5\r\nContent-Disposition: form-data; "
+	  "name=\"Upload\"\r\n\r\nSubmit Query\r\n------"
+	  "------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>,
     Expect = [{headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Filename"}]}}]},
-              {body, <<"hello.txt">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "success_action_status"}]}}]},
-              {body, <<"201">>},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}},
-                {"content-type", {"application/octet-stream", []}}]},
-              {body, Chunk},
-              body_end,
-              {headers,
-               [{"content-disposition",
-                 {"form-data", [{"name", "Upload"}]}}]},
-              {body, <<"Submit Query">>},
-              body_end,
-              eof],
-    TestCallback = fun (Next) -> test_callback(Next, Expect) end,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Filename"}]}}]},
+	      {body, <<"hello.txt">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "success_action_status"}]}}]},
+	      {body, <<"201">>}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data",
+		  [{"name", "file"}, {"filename", "hello.txt"}]}},
+		{"content-type", {"application/octet-stream", []}}]},
+	      {body, Chunk}, body_end,
+	      {headers,
+	       [{"content-disposition",
+		 {"form-data", [{"name", "Upload"}]}}]},
+	      {body, <<"Submit Query">>}, body_end, eof],
+    TestCallback = fun (Next) -> test_callback(Next, Expect)
+		   end,
     ServerFun = fun (Socket, _Opts) ->
-                        ok = mochiweb_socket:send(Socket, BinContent),
-                        exit(normal)
-                end,
+			ok = mochiweb_socket:send(Socket, BinContent),
+			exit(normal)
+		end,
     ClientFun = fun (Socket) ->
-                        Req = fake_request(Socket, ContentType,
-                                           byte_size(BinContent)),
-                        Res = parse_multipart_request(Req, TestCallback),
-                        {0, <<>>, ok} = Res,
-                        ok
-                end,
+			Req = fake_request(Socket, ContentType,
+					   byte_size(BinContent)),
+			Res = parse_multipart_request(Req, TestCallback),
+			{0, <<>>, ok} = Res,
+			ok
+		end,
     ok = with_socket_server(plain, ServerFun, ClientFun),
     ok.
+
 -endif.
diff --git a/src/mochiweb_request.erl b/src/mochiweb_request.erl
index 3889d33..a1d2d6e 100644
--- a/src/mochiweb_request.erl
+++ b/src/mochiweb_request.erl
@@ -22,33 +22,57 @@
 %% @doc MochiWeb HTTP Request abstraction.
 
 -module(mochiweb_request).
+
 -author('bob@mochimedia.com').
 
 -include_lib("kernel/include/file.hrl").
+
 -include("internal.hrl").
 
 -define(QUIP, "Any of you quaids got a smint?").
 
 -export([new/5, new/6]).
--export([get_header_value/2, get_primary_header_value/2, get_combined_header_value/2, get/2, dump/1]).
--export([send/2, recv/2, recv/3, recv_body/1, recv_body/2, stream_body/4, stream_body/5]).
--export([start_response/2, start_response_length/2, start_raw_response/2]).
--export([respond/2, ok/2]).
+
+-export([dump/1, get/2, get_combined_header_value/2,
+	 get_header_value/2, get_primary_header_value/2]).
+
+-export([recv/2, recv/3, recv_body/1, recv_body/2,
+	 send/2, stream_body/4, stream_body/5]).
+
+-export([start_raw_response/2, start_response/2,
+	 start_response_length/2]).
+
+-export([ok/2, respond/2]).
+
 -export([not_found/1, not_found/2]).
+
 -export([parse_post/1, parse_qs/1]).
--export([should_close/1, cleanup/1]).
--export([parse_cookie/1, get_cookie_value/2]).
+
+-export([cleanup/1, should_close/1]).
+
+-export([get_cookie_value/2, parse_cookie/1]).
+
 -export([serve_file/3, serve_file/4]).
+
 -export([accepted_encodings/2]).
--export([accepts_content_type/2, accepted_content_types/2]).
+
+-export([accepted_content_types/2,
+	 accepts_content_type/2]).
 
 -define(SAVE_QS, mochiweb_request_qs).
+
 -define(SAVE_PATH, mochiweb_request_path).
+
 -define(SAVE_RECV, mochiweb_request_recv).
+
 -define(SAVE_BODY, mochiweb_request_body).
+
 -define(SAVE_BODY_LENGTH, mochiweb_request_body_length).
+
 -define(SAVE_POST, mochiweb_request_post).
+
 -define(SAVE_COOKIE, mochiweb_request_cookie).
+
 -define(SAVE_FORCE_CLOSE, mochiweb_request_force_close).
 
 %% @type key() = atom() | string() | binary()
@@ -62,7 +86,7 @@
 -define(IDLE_TIMEOUT, 300000).
 
 % Maximum recv_body() length of 1MB
--define(MAX_RECV_BODY, (1024*1024)).
+-define(MAX_RECV_BODY, 1024 * 1024).
 
 %% @spec new(Socket, Method, RawPath, Version, headers()) -> request()
 %% @doc Create a new request instance.
@@ -72,17 +96,27 @@ new(Socket, Method, RawPath, Version, Headers) ->
 %% @spec new(Socket, Opts, Method, RawPath, Version, headers()) -> request()
 %% @doc Create a new request instance.
 new(Socket, Opts, Method, RawPath, Version, Headers) ->
-    {?MODULE, [Socket, Opts, Method, RawPath, Version, Headers]}.
+    {?MODULE,
+     [Socket, Opts, Method, RawPath, Version, Headers]}.
 
 %% @spec get_header_value(K, request()) -> undefined | Value
 %% @doc Get the value of a given request header.
-get_header_value(K, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, Headers]}) ->
+get_header_value(K,
+		 {?MODULE,
+		  [_Socket, _Opts, _Method, _RawPath, _Version,
+		   Headers]}) ->
     mochiweb_headers:get_value(K, Headers).
 
-get_primary_header_value(K, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, Headers]}) ->
+get_primary_header_value(K,
+			 {?MODULE,
+			  [_Socket, _Opts, _Method, _RawPath, _Version,
+			   Headers]}) ->
     mochiweb_headers:get_primary_value(K, Headers).
 
-get_combined_header_value(K, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, Headers]}) ->
+get_combined_header_value(K,
+			  {?MODULE,
+			   [_Socket, _Opts, _Method, _RawPath, _Version,
+			    Headers]}) ->
     mochiweb_headers:get_combined_value(K, Headers).
 
 %% @type field() = socket | scheme | method | raw_path | version | headers | peer | path | body_length | range
@@ -93,246 +127,303 @@ get_combined_header_value(K, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Vers
 %%      an ssl socket will be returned as <code>{ssl, SslSocket}</code>.
 %%      You can use <code>SslSocket</code> with the <code>ssl</code>
 %%      application, eg: <code>ssl:peercert(SslSocket)</code>.
-get(socket, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
+get(socket,
+    {?MODULE,
+     [Socket, _Opts, _Method, _RawPath, _Version,
+      _Headers]}) ->
     Socket;
-get(scheme, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
+get(scheme,
+    {?MODULE,
+     [Socket, _Opts, _Method, _RawPath, _Version,
+      _Headers]}) ->
     case mochiweb_socket:type(Socket) of
-        plain ->
-            http;
-        ssl ->
-            https
+      plain -> http;
+      ssl -> https
     end;
-get(method, {?MODULE, [_Socket, _Opts, Method, _RawPath, _Version, _Headers]}) ->
+get(method,
+    {?MODULE,
+     [_Socket, _Opts, Method, _RawPath, _Version,
+      _Headers]}) ->
     Method;
-get(raw_path, {?MODULE, [_Socket, _Opts, _Method, RawPath, _Version, _Headers]}) ->
+get(raw_path,
+    {?MODULE,
+     [_Socket, _Opts, _Method, RawPath, _Version,
+      _Headers]}) ->
     RawPath;
-get(version, {?MODULE, [_Socket, _Opts, _Method, _RawPath, Version, _Headers]}) ->
+get(version,
+    {?MODULE,
+     [_Socket, _Opts, _Method, _RawPath, Version,
+      _Headers]}) ->
     Version;
-get(headers, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, Headers]}) ->
+get(headers,
+    {?MODULE,
+     [_Socket, _Opts, _Method, _RawPath, _Version,
+      Headers]}) ->
     Headers;
-get(peer, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+get(peer,
+    {?MODULE,
+     [Socket, _Opts, _Method, _RawPath, _Version,
+      _Headers]} =
+	THIS) ->
     case mochiweb_socket:peername(Socket) of
-        {ok, {Addr={10, _, _, _}, _Port}} ->
-            case get_header_value("x-forwarded-for", THIS) of
-                undefined ->
-                    inet_parse:ntoa(Addr);
-                Hosts ->
-                    string:strip(lists:last(string:tokens(Hosts, ",")))
-            end;
-        %% Copied this syntax from webmachine contributor Steve Vinoski
-        {ok, {Addr={172, Second, _, _}, _Port}} when (Second > 15) andalso (Second < 32) ->
-            case get_header_value("x-forwarded-for", THIS) of
-                undefined ->
-                    inet_parse:ntoa(Addr);
-                Hosts ->
-                    string:strip(lists:last(string:tokens(Hosts, ",")))
-            end;
-        %% According to RFC 6598, contributor Gerald Xv
-        {ok, {Addr={100, Second, _, _}, _Port}} when (Second > 63) andalso (Second < 128) ->
-            case get_header_value("x-forwarded-for", THIS) of
-                undefined ->
-                    inet_parse:ntoa(Addr);
-                Hosts ->
-                    string:strip(lists:last(string:tokens(Hosts, ",")))
-            end;
-        {ok, {Addr={192, 168, _, _}, _Port}} ->
-            case get_header_value("x-forwarded-for", THIS) of
-                undefined ->
-                    inet_parse:ntoa(Addr);
-                Hosts ->
-                    string:strip(lists:last(string:tokens(Hosts, ",")))
-            end;
-        {ok, {{127, 0, 0, 1}, _Port}} ->
-            case get_header_value("x-forwarded-for", THIS) of
-                undefined ->
-                    "127.0.0.1";
-                Hosts ->
-                    string:strip(lists:last(string:tokens(Hosts, ",")))
-            end;
-        {ok, {Addr, _Port}} ->
-            inet_parse:ntoa(Addr);
-        {error, enotconn} ->
-            exit(normal)
+      {ok, {Addr = {10, _, _, _}, _Port}} ->
+	  case get_header_value("x-forwarded-for", THIS) of
+	    undefined -> inet_parse:ntoa(Addr);
+	    Hosts ->
+		string:strip(lists:last(string:tokens(Hosts, ",")))
+	  end;
+      %% Copied this syntax from webmachine contributor Steve Vinoski
+      {ok, {Addr = {172, Second, _, _}, _Port}}
+	  when Second > 15 andalso Second < 32 ->
+	  case get_header_value("x-forwarded-for", THIS) of
+	    undefined -> inet_parse:ntoa(Addr);
+	    Hosts ->
+		string:strip(lists:last(string:tokens(Hosts, ",")))
+	  end;
+      %% According to RFC 6598, contributor Gerald Xv
+      {ok, {Addr = {100, Second, _, _}, _Port}}
+	  when Second > 63 andalso Second < 128 ->
+	  case get_header_value("x-forwarded-for", THIS) of
+	    undefined -> inet_parse:ntoa(Addr);
+	    Hosts ->
+		string:strip(lists:last(string:tokens(Hosts, ",")))
+	  end;
+      {ok, {Addr = {192, 168, _, _}, _Port}} ->
+	  case get_header_value("x-forwarded-for", THIS) of
+	    undefined -> inet_parse:ntoa(Addr);
+	    Hosts ->
+		string:strip(lists:last(string:tokens(Hosts, ",")))
+	  end;
+      {ok, {{127, 0, 0, 1}, _Port}} ->
+	  case get_header_value("x-forwarded-for", THIS) of
+	    undefined -> "127.0.0.1";
+	    Hosts ->
+		string:strip(lists:last(string:tokens(Hosts, ",")))
+	  end;
+      {ok, {Addr, _Port}} -> inet_parse:ntoa(Addr);
+      {error, enotconn} -> exit(normal)
     end;
-get(path, {?MODULE, [_Socket, _Opts, _Method, RawPath, _Version, _Headers]}) ->
+get(path,
+    {?MODULE,
+     [_Socket, _Opts, _Method, RawPath, _Version,
+      _Headers]}) ->
     case erlang:get(?SAVE_PATH) of
-        undefined ->
-            {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath),
-            Path = mochiweb_util:normalize_path(mochiweb_util:unquote(Path0)),
-            put(?SAVE_PATH, Path),
-            Path;
-        Cached ->
-            Cached
+      undefined ->
+	  {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath),
+	  Path =
+	      mochiweb_util:normalize_path(mochiweb_util:unquote(Path0)),
+	  put(?SAVE_PATH, Path),
+	  Path;
+      Cached -> Cached
     end;
-get(body_length, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+get(body_length,
+    {?MODULE,
+     [_Socket, _Opts, _Method, _RawPath, _Version,
+      _Headers]} =
+	THIS) ->
     case erlang:get(?SAVE_BODY_LENGTH) of
-        undefined ->
-            BodyLength = body_length(THIS),
-            put(?SAVE_BODY_LENGTH, {cached, BodyLength}),
-            BodyLength;
-        {cached, Cached} ->
-            Cached
+      undefined ->
+	  BodyLength = body_length(THIS),
+	  put(?SAVE_BODY_LENGTH, {cached, BodyLength}),
+	  BodyLength;
+      {cached, Cached} -> Cached
     end;
-get(range, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+get(range,
+    {?MODULE,
+     [_Socket, _Opts, _Method, _RawPath, _Version,
+      _Headers]} =
+	THIS) ->
     case get_header_value(range, THIS) of
-        undefined ->
-            undefined;
-        RawRange ->
-            mochiweb_http:parse_range_request(RawRange)
+      undefined -> undefined;
+      RawRange -> mochiweb_http:parse_range_request(RawRange)
     end;
-get(opts, {?MODULE, [_Socket, Opts, _Method, _RawPath, _Version, _Headers]}) ->
+get(opts,
+    {?MODULE,
+     [_Socket, Opts, _Method, _RawPath, _Version,
+      _Headers]}) ->
     Opts.
 
 %% @spec dump(request()) -> {mochiweb_request, [{atom(), term()}]}
 %% @doc Dump the internal representation to a "human readable" set of terms
 %%      for debugging/inspection purposes.
-dump({?MODULE, [_Socket, Opts, Method, RawPath, Version, Headers]}) ->
-    {?MODULE, [{method, Method},
-               {version, Version},
-               {raw_path, RawPath},
-               {opts, Opts},
-               {headers, mochiweb_headers:to_list(Headers)}]}.
+dump({?MODULE,
+      [_Socket, Opts, Method, RawPath, Version, Headers]}) ->
+    {?MODULE,
+     [{method, Method}, {version, Version},
+      {raw_path, RawPath}, {opts, Opts},
+      {headers, mochiweb_headers:to_list(Headers)}]}.
 
 %% @spec send(iodata(), request()) -> ok
 %% @doc Send data over the socket.
-send(Data, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
+send(Data,
+     {?MODULE,
+      [Socket, _Opts, _Method, _RawPath, _Version,
+       _Headers]}) ->
     case mochiweb_socket:send(Socket, Data) of
-        ok ->
-            ok;
-        _ ->
-            exit(normal)
+      ok -> ok;
+      _ -> exit(normal)
     end.
 
 %% @spec recv(integer(), request()) -> binary()
 %% @doc Receive Length bytes from the client as a binary, with the default
 %%      idle timeout.
-recv(Length, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+recv(Length,
+     {?MODULE,
+      [_Socket, _Opts, _Method, _RawPath, _Version,
+       _Headers]} =
+	 THIS) ->
     recv(Length, ?IDLE_TIMEOUT, THIS).
 
 %% @spec recv(integer(), integer(), request()) -> binary()
 %% @doc Receive Length bytes from the client as a binary, with the given
 %%      Timeout in msec.
-recv(Length, Timeout, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
+recv(Length, Timeout,
+     {?MODULE,
+      [Socket, _Opts, _Method, _RawPath, _Version,
+       _Headers]}) ->
     case mochiweb_socket:recv(Socket, Length, Timeout) of
-        {ok, Data} ->
-            put(?SAVE_RECV, true),
-            Data;
-        _ ->
-            exit(normal)
+      {ok, Data} -> put(?SAVE_RECV, true), Data;
+      _ -> exit(normal)
     end.
 
 %% @spec body_length(request()) -> undefined | chunked | unknown_transfer_encoding | integer()
 %% @doc  Infer body length from transfer-encoding and content-length headers.
-body_length({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+body_length({?MODULE,
+	     [_Socket, _Opts, _Method, _RawPath, _Version,
+	      _Headers]} =
+		THIS) ->
     case get_header_value("transfer-encoding", THIS) of
-        undefined ->
-            case get_combined_header_value("content-length", THIS) of
-                undefined ->
-                    undefined;
-                Length ->
-                    list_to_integer(Length)
-            end;
-        "chunked" ->
-            chunked;
-        Unknown ->
-            {unknown_transfer_encoding, Unknown}
+      undefined ->
+	  case get_combined_header_value("content-length", THIS)
+	      of
+	    undefined -> undefined;
+	    Length -> list_to_integer(Length)
+	  end;
+      "chunked" -> chunked;
+      Unknown -> {unknown_transfer_encoding, Unknown}
     end.
 
-
 %% @spec recv_body(request()) -> binary()
 %% @doc Receive the body of the HTTP request (defined by Content-Length).
 %%      Will only receive up to the default max-body length of 1MB.
-recv_body({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+recv_body({?MODULE,
+	   [_Socket, _Opts, _Method, _RawPath, _Version,
+	    _Headers]} =
+	      THIS) ->
     recv_body(?MAX_RECV_BODY, THIS).
 
 %% @spec recv_body(integer(), request()) -> binary()
 %% @doc Receive the body of the HTTP request (defined by Content-Length).
 %%      Will receive up to MaxBody bytes.
-recv_body(MaxBody, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+recv_body(MaxBody,
+	  {?MODULE,
+	   [_Socket, _Opts, _Method, _RawPath, _Version,
+	    _Headers]} =
+	      THIS) ->
     case erlang:get(?SAVE_BODY) of
-        undefined ->
-            % we could use a sane constant for max chunk size
-            Body = stream_body(?MAX_RECV_BODY, fun
-                ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) ->
-                    iolist_to_binary(lists:reverse(BinAcc));
-                ({Length, Bin}, {LengthAcc, BinAcc}) ->
-                    NewLength = Length + LengthAcc,
-                    if NewLength > MaxBody ->
-                        exit({body_too_large, chunked});
-                    true ->
-                        {NewLength, [Bin | BinAcc]}
-                    end
-                end, {0, []}, MaxBody, THIS),
-            put(?SAVE_BODY, Body),
-            Body;
-        Cached -> Cached
+      undefined ->
+	  % we could use a sane constant for max chunk size
+	  Body = stream_body(?MAX_RECV_BODY,
+			     fun ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) ->
+				     iolist_to_binary(lists:reverse(BinAcc));
+				 ({Length, Bin}, {LengthAcc, BinAcc}) ->
+				     NewLength = Length + LengthAcc,
+				     if NewLength > MaxBody ->
+					    exit({body_too_large, chunked});
+					true -> {NewLength, [Bin | BinAcc]}
+				     end
+			     end,
+			     {0, []}, MaxBody, THIS),
+	  put(?SAVE_BODY, Body),
+	  Body;
+      Cached -> Cached
     end.
 
-stream_body(MaxChunkSize, ChunkFun, FunState, {?MODULE,[_Socket,_Opts,_Method,_RawPath,_Version,_Headers]}=THIS) ->
-    stream_body(MaxChunkSize, ChunkFun, FunState, undefined, THIS).
-
-stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength,
-            {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+stream_body(MaxChunkSize, ChunkFun, FunState,
+	    {?MODULE,
+	     [_Socket, _Opts, _Method, _RawPath, _Version,
+	      _Headers]} =
+		THIS) ->
+    stream_body(MaxChunkSize, ChunkFun, FunState, undefined,
+		THIS).
+
+stream_body(MaxChunkSize, ChunkFun, FunState,
+	    MaxBodyLength,
+	    {?MODULE,
+	     [_Socket, _Opts, _Method, _RawPath, _Version,
+	      _Headers]} =
+		THIS) ->
     Expect = case get_header_value("expect", THIS) of
-                 undefined ->
-                     undefined;
-                 Value when is_list(Value) ->
-                     string:to_lower(Value)
-             end,
+	       undefined -> undefined;
+	       Value when is_list(Value) -> string:to_lower(Value)
+	     end,
     case Expect of
-        "100-continue" ->
-            _ = start_raw_response({100, gb_trees:empty()}, THIS),
-            ok;
-        _Else ->
-            ok
+      "100-continue" ->
+	  _ = start_raw_response({100, gb_trees:empty()}, THIS),
+	  ok;
+      _Else -> ok
     end,
     case body_length(THIS) of
-        undefined ->
-            undefined;
-        {unknown_transfer_encoding, Unknown} ->
-            exit({unknown_transfer_encoding, Unknown});
-        chunked ->
-            % In this case the MaxBody is actually used to
-            % determine the maximum allowed size of a single
-            % chunk.
-            stream_chunked_body(MaxChunkSize, ChunkFun, FunState, THIS);
-        0 ->
-            <<>>;
-        Length when is_integer(Length) ->
-            case MaxBodyLength of
-            MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length ->
-                exit({body_too_large, content_length});
-            _ ->
-                stream_unchunked_body(MaxChunkSize,Length, ChunkFun, FunState, THIS)
-            end
+      undefined -> undefined;
+      {unknown_transfer_encoding, Unknown} ->
+	  exit({unknown_transfer_encoding, Unknown});
+      chunked ->
+	  % In this case the MaxBody is actually used to
+	  % determine the maximum allowed size of a single
+	  % chunk.
+	  stream_chunked_body(MaxChunkSize, ChunkFun, FunState,
+			      THIS);
+      0 -> <<>>;
+      Length when is_integer(Length) ->
+	  case MaxBodyLength of
+	    MaxBodyLength
+		when is_integer(MaxBodyLength),
+		     MaxBodyLength < Length ->
+		exit({body_too_large, content_length});
+	    _ ->
+		stream_unchunked_body(MaxChunkSize, Length, ChunkFun,
+				      FunState, THIS)
+	  end
     end.
 
-
 %% @spec start_response({integer(), ioheaders()}, request()) -> response()
 %% @doc Start the HTTP response by sending the Code HTTP response and
 %%      ResponseHeaders. The server will set header defaults such as Server
 %%      and Date if not present in ResponseHeaders.
-start_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+start_response({Code, ResponseHeaders},
+	       {?MODULE,
+		[_Socket, _Opts, _Method, _RawPath, _Version,
+		 _Headers]} =
+		   THIS) ->
     start_raw_response({Code, ResponseHeaders}, THIS).
 
 %% @spec start_raw_response({integer(), headers()}, request()) -> response()
 %% @doc Start the HTTP response by sending the Code HTTP response and
 %%      ResponseHeaders.
-start_raw_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    {Header, Response} = format_response_header({Code, ResponseHeaders}, THIS),
+start_raw_response({Code, ResponseHeaders},
+		   {?MODULE,
+		    [_Socket, _Opts, _Method, _RawPath, _Version,
+		     _Headers]} =
+		       THIS) ->
+    {Header, Response} = format_response_header({Code,
+						 ResponseHeaders},
+						THIS),
     send(Header, THIS),
     Response.
 
-
 %% @spec start_response_length({integer(), ioheaders(), integer()}, request()) -> response()
 %% @doc Start the HTTP response by sending the Code HTTP response and
 %%      ResponseHeaders including a Content-Length of Length. The server
 %%      will set header defaults such as Server
 %%      and Date if not present in ResponseHeaders.
 start_response_length({Code, ResponseHeaders, Length},
-                      {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+		      {?MODULE,
+		       [_Socket, _Opts, _Method, _RawPath, _Version,
+			_Headers]} =
+			  THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
-    HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse),
+    HResponse1 = mochiweb_headers:enter("Content-Length",
+					Length, HResponse),
     start_response({Code, HResponse1}, THIS).
 
 %% @spec format_response_header({integer(), ioheaders()} | {integer(), ioheaders(), integer()}, request()) -> iolist()
@@ -340,23 +431,37 @@ start_response_length({Code, ResponseHeaders, Length},
 %%      ResponseHeaders including an optional Content-Length of Length. The server
 %%      will set header defaults such as Server
 %%      and Date if not present in ResponseHeaders.
-format_response_header({Code, ResponseHeaders}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, Version, _Headers]}=THIS) ->
+format_response_header({Code, ResponseHeaders},
+		       {?MODULE,
+			[_Socket, _Opts, _Method, _RawPath, Version,
+			 _Headers]} =
+			   THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
-    HResponse1 = mochiweb_headers:default_from_list(server_headers(), HResponse),
+    HResponse1 =
+	mochiweb_headers:default_from_list(server_headers(),
+					   HResponse),
     HResponse2 = case should_close(THIS) of
-                     true ->
-                         mochiweb_headers:enter("Connection", "close", HResponse1);
-                     false ->
-                         HResponse1
-                 end,
-    End = [[mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">>]
-           || {K, V} <- mochiweb_headers:to_list(HResponse2)],
-    Response = mochiweb:new_response({THIS, Code, HResponse2}),
-    {[make_version(Version), make_code(Code), <<"\r\n">> | [End, <<"\r\n">>]], Response};
+		   true ->
+		       mochiweb_headers:enter("Connection", "close",
+					      HResponse1);
+		   false -> HResponse1
+		 end,
+    End = [[mochiweb_util:make_io(K), <<": ">>, V,
+	    <<"\r\n">>]
+	   || {K, V} <- mochiweb_headers:to_list(HResponse2)],
+    Response = mochiweb:new_response({THIS, Code,
+				      HResponse2}),
+    {[make_version(Version), make_code(Code), <<"\r\n">>,
+      End, <<"\r\n">>],
+     Response};
 format_response_header({Code, ResponseHeaders, Length},
-                       {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+		       {?MODULE,
+			[_Socket, _Opts, _Method, _RawPath, _Version,
+			 _Headers]} =
+			   THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
-    HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse),
+    HResponse1 = mochiweb_headers:enter("Content-Length",
+					Length, HResponse),
     format_response_header({Code, HResponse1}, THIS).
 
 %% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}, request()) -> response()
@@ -365,293 +470,391 @@ format_response_header({Code, ResponseHeaders, Length},
 %%      will be set by the Body length, and the server will insert header
 %%      defaults.
 respond({Code, ResponseHeaders, {file, IoDevice}},
-        {?MODULE, [_Socket, _Opts, Method, _RawPath, _Version, _Headers]}=THIS) ->
+	{?MODULE,
+	 [_Socket, _Opts, Method, _RawPath, _Version,
+	  _Headers]} =
+	    THIS) ->
     Length = mochiweb_io:iodevice_size(IoDevice),
-    Response = start_response_length({Code, ResponseHeaders, Length}, THIS),
+    Response = start_response_length({Code, ResponseHeaders,
+				      Length},
+				     THIS),
     case Method of
-        'HEAD' ->
-            ok;
-        _ ->
-            mochiweb_io:iodevice_stream(
-              fun (Body) -> send(Body, THIS) end,
-              IoDevice)
+      'HEAD' -> ok;
+      _ ->
+	  mochiweb_io:iodevice_stream(fun (Body) ->
+					      send(Body, THIS)
+				      end,
+				      IoDevice)
     end,
     Response;
-respond({Code, ResponseHeaders, chunked}, {?MODULE, [_Socket, _Opts, Method, _RawPath, Version, _Headers]}=THIS) ->
+respond({Code, ResponseHeaders, chunked},
+	{?MODULE,
+	 [_Socket, _Opts, Method, _RawPath, Version, _Headers]} =
+	    THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
     HResponse1 = case Method of
-                     'HEAD' ->
-                         %% This is what Google does, http://www.google.com/
-                         %% is chunked but HEAD gets Content-Length: 0.
-                         %% The RFC is ambiguous so emulating Google is smart.
-                         mochiweb_headers:enter("Content-Length", "0",
-                                                HResponse);
-                     _ when Version >= {1, 1} ->
-                         %% Only use chunked encoding for HTTP/1.1
-                         mochiweb_headers:enter("Transfer-Encoding", "chunked",
-                                                HResponse);
-                     _ ->
-                         %% For pre-1.1 clients we send the data as-is
-                         %% without a Content-Length header and without
-                         %% chunk delimiters. Since the end of the document
-                         %% is now ambiguous we must force a close.
-                         put(?SAVE_FORCE_CLOSE, true),
-                         HResponse
-                 end,
+		   'HEAD' ->
+		       %% This is what Google does, http://www.google.com/
+		       %% is chunked but HEAD gets Content-Length: 0.
+		       %% The RFC is ambiguous so emulating Google is smart.
+		       mochiweb_headers:enter("Content-Length", "0",
+					      HResponse);
+		   _ when Version >= {1, 1} ->
+		       %% Only use chunked encoding for HTTP/1.1
+		       mochiweb_headers:enter("Transfer-Encoding", "chunked",
+					      HResponse);
+		   _ ->
+		       %% For pre-1.1 clients we send the data as-is
+		       %% without a Content-Length header and without
+		       %% chunk delimiters. Since the end of the document
+		       %% is now ambiguous we must force a close.
+		       put(?SAVE_FORCE_CLOSE, true),
+		       HResponse
+		 end,
     start_response({Code, HResponse1}, THIS);
-respond({Code, ResponseHeaders, Body}, {?MODULE, [_Socket, _Opts, Method, _RawPath, _Version, _Headers]}=THIS) ->
-    {Header, Response} = format_response_header({Code, ResponseHeaders, iolist_size(Body)}, THIS),
+respond({Code, ResponseHeaders, Body},
+	{?MODULE,
+	 [_Socket, _Opts, Method, _RawPath, _Version,
+	  _Headers]} =
+	    THIS) ->
+    {Header, Response} = format_response_header({Code,
+						 ResponseHeaders,
+						 iolist_size(Body)},
+						THIS),
     case Method of
-        'HEAD' -> send(Header, THIS);
-        _      -> send([Header, Body], THIS)
+      'HEAD' -> send(Header, THIS);
+      _ -> send([Header, Body], THIS)
     end,
     Response.
 
 %% @spec not_found(request()) -> response()
 %% @doc Alias for <code>not_found([])</code>.
-not_found({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+not_found({?MODULE,
+	   [_Socket, _Opts, _Method, _RawPath, _Version,
+	    _Headers]} =
+	      THIS) ->
     not_found([], THIS).
 
 %% @spec not_found(ExtraHeaders, request()) -> response()
 %% @doc Alias for <code>respond({404, [{"Content-Type", "text/plain"}
 %% | ExtraHeaders], &lt;&lt;"Not found."&gt;&gt;})</code>.
-not_found(ExtraHeaders, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders],
-             <<"Not found.">>}, THIS).
+not_found(ExtraHeaders,
+	  {?MODULE,
+	   [_Socket, _Opts, _Method, _RawPath, _Version,
+	    _Headers]} =
+	      THIS) ->
+    respond({404,
+	     [{"Content-Type", "text/plain"} | ExtraHeaders],
+	     <<"Not found.">>},
+	    THIS).
 
 %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}, request()) ->
 %%           response()
 %% @doc respond({200, [{"Content-Type", ContentType} | Headers], Body}).
-ok({ContentType, Body}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+ok({ContentType, Body},
+   {?MODULE,
+    [_Socket, _Opts, _Method, _RawPath, _Version,
+     _Headers]} =
+       THIS) ->
     ok({ContentType, [], Body}, THIS);
-ok({ContentType, ResponseHeaders, Body}, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+ok({ContentType, ResponseHeaders, Body},
+   {?MODULE,
+    [_Socket, _Opts, _Method, _RawPath, _Version,
+     _Headers]} =
+       THIS) ->
     HResponse = mochiweb_headers:make(ResponseHeaders),
     case get(range, THIS) of
-        X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked ->
-            %% http://code.google.com/p/mochiweb/issues/detail?id=54
-            %% Range header not supported when chunked, return 200 and provide
-            %% full response.
-            HResponse1 = mochiweb_headers:enter("Content-Type", ContentType,
-                                                HResponse),
-            respond({200, HResponse1, Body}, THIS);
-        Ranges ->
-            {PartList, Size} = range_parts(Body, Ranges),
-            case PartList of
-                [] -> %% no valid ranges
-                    HResponse1 = mochiweb_headers:enter("Content-Type",
-                                                        ContentType,
-                                                        HResponse),
-                    %% could be 416, for now we'll just return 200
-                    respond({200, HResponse1, Body}, THIS);
-                PartList ->
-                    {RangeHeaders, RangeBody} =
-                        mochiweb_multipart:parts_to_body(PartList, ContentType, Size),
-                    HResponse1 = mochiweb_headers:enter_from_list(
-                                   [{"Accept-Ranges", "bytes"} |
-                                    RangeHeaders],
-                                   HResponse),
-                    respond({206, HResponse1, RangeBody}, THIS)
-            end
+      X
+	  when (X =:= undefined orelse X =:= fail) orelse
+		 Body =:= chunked ->
+	  %% http://code.google.com/p/mochiweb/issues/detail?id=54
+	  %% Range header not supported when chunked, return 200 and provide
+	  %% full response.
+	  HResponse1 = mochiweb_headers:enter("Content-Type",
+					      ContentType, HResponse),
+	  respond({200, HResponse1, Body}, THIS);
+      Ranges ->
+	  {PartList, Size} = range_parts(Body, Ranges),
+	  case PartList of
+	    [] -> %% no valid ranges
+		HResponse1 = mochiweb_headers:enter("Content-Type",
+						    ContentType, HResponse),
+		%% could be 416, for now we'll just return 200
+		respond({200, HResponse1, Body}, THIS);
+	    PartList ->
+		{RangeHeaders, RangeBody} =
+		    mochiweb_multipart:parts_to_body(PartList, ContentType,
+						     Size),
+		HResponse1 =
+		    mochiweb_headers:enter_from_list([{"Accept-Ranges",
+						       "bytes"}
+						      | RangeHeaders],
+						     HResponse),
+		respond({206, HResponse1, RangeBody}, THIS)
+	  end
     end.
 
 %% @spec should_close(request()) -> bool()
 %% @doc Return true if the connection must be closed. If false, using
 %%      Keep-Alive should be safe.
-should_close({?MODULE, [_Socket, _Opts, _Method, _RawPath, Version, _Headers]}=THIS) ->
-    ForceClose = erlang:get(?SAVE_FORCE_CLOSE) =/= undefined,
+should_close({?MODULE,
+	      [_Socket, _Opts, _Method, _RawPath, Version,
+	       _Headers]} =
+		 THIS) ->
+    ForceClose = erlang:get(?SAVE_FORCE_CLOSE) =/=
+		   undefined,
     DidNotRecv = erlang:get(?SAVE_RECV) =:= undefined,
-    ForceClose orelse Version < {1, 0}
-        %% Connection: close
-        orelse is_close(get_header_value("connection", THIS))
-        %% HTTP 1.0 requires Connection: Keep-Alive
-        orelse (Version =:= {1, 0}
-                andalso get_header_value("connection", THIS) =/= "Keep-Alive")
-        %% unread data left on the socket, can't safely continue
-        orelse (DidNotRecv
-                andalso get_combined_header_value("content-length", THIS) =/= undefined
-                andalso list_to_integer(get_combined_header_value("content-length", THIS)) > 0)
-        orelse (DidNotRecv
-                andalso get_header_value("transfer-encoding", THIS) =:= "chunked").
-
-is_close("close") ->
-    true;
-is_close(S=[_C, _L, _O, _S, _E]) ->
+    ForceClose orelse
+      Version < {1, 0}
+	%% Connection: close
+	orelse
+	is_close(get_header_value("connection", THIS))
+	  %% HTTP 1.0 requires Connection: Keep-Alive
+	  orelse
+	  Version =:= {1, 0} andalso
+	    get_header_value("connection", THIS) =/= "Keep-Alive"
+	    %% unread data left on the socket, can't safely continue
+	    orelse
+	    DidNotRecv andalso
+	      get_combined_header_value("content-length", THIS) =/=
+		undefined
+		andalso
+		list_to_integer(get_combined_header_value("content-length",
+							  THIS))
+		  > 0
+	      orelse
+	      DidNotRecv andalso
+		get_header_value("transfer-encoding", THIS) =:=
+		  "chunked".
+
+is_close("close") -> true;
+is_close(S = [_C, _L, _O, _S, _E]) ->
     string:to_lower(S) =:= "close";
-is_close(_) ->
-    false.
+is_close(_) -> false.
 
 %% @spec cleanup(request()) -> ok
 %% @doc Clean up any junk in the process dictionary, required before continuing
 %%      a Keep-Alive request.
-cleanup({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
-    L = [?SAVE_QS, ?SAVE_PATH, ?SAVE_RECV, ?SAVE_BODY, ?SAVE_BODY_LENGTH,
-         ?SAVE_POST, ?SAVE_COOKIE, ?SAVE_FORCE_CLOSE],
-    lists:foreach(fun(K) ->
-                          erase(K)
-                  end, L),
+cleanup({?MODULE,
+	 [_Socket, _Opts, _Method, _RawPath, _Version,
+	  _Headers]}) ->
+    L = [?SAVE_QS, ?SAVE_PATH, ?SAVE_RECV, ?SAVE_BODY,
+	 ?SAVE_BODY_LENGTH, ?SAVE_POST, ?SAVE_COOKIE,
+	 ?SAVE_FORCE_CLOSE],
+    lists:foreach(fun (K) -> erase(K) end, L),
     ok.
 
 %% @spec parse_qs(request()) -> [{Key::string(), Value::string()}]
 %% @doc Parse the query string of the URL.
-parse_qs({?MODULE, [_Socket, _Opts, _Method, RawPath, _Version, _Headers]}) ->
+parse_qs({?MODULE,
+	  [_Socket, _Opts, _Method, RawPath, _Version,
+	   _Headers]}) ->
     case erlang:get(?SAVE_QS) of
-        undefined ->
-            {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath),
-            Parsed = mochiweb_util:parse_qs(QueryString),
-            put(?SAVE_QS, Parsed),
-            Parsed;
-        Cached ->
-            Cached
+      undefined ->
+	  {_, QueryString, _} =
+	      mochiweb_util:urlsplit_path(RawPath),
+	  Parsed = mochiweb_util:parse_qs(QueryString),
+	  put(?SAVE_QS, Parsed),
+	  Parsed;
+      Cached -> Cached
     end.
 
 %% @spec get_cookie_value(Key::string, request()) -> string() | undefined
 %% @doc Get the value of the given cookie.
-get_cookie_value(Key, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+get_cookie_value(Key,
+		 {?MODULE,
+		  [_Socket, _Opts, _Method, _RawPath, _Version,
+		   _Headers]} =
+		     THIS) ->
     proplists:get_value(Key, parse_cookie(THIS)).
 
 %% @spec parse_cookie(request()) -> [{Key::string(), Value::string()}]
 %% @doc Parse the cookie header.
-parse_cookie({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+parse_cookie({?MODULE,
+	      [_Socket, _Opts, _Method, _RawPath, _Version,
+	       _Headers]} =
+		 THIS) ->
     case erlang:get(?SAVE_COOKIE) of
-        undefined ->
-            Cookies = case get_header_value("cookie", THIS) of
-                          undefined ->
-                              [];
-                          Value ->
-                              mochiweb_cookies:parse_cookie(Value)
-                      end,
-            put(?SAVE_COOKIE, Cookies),
-            Cookies;
-        Cached ->
-            Cached
+      undefined ->
+	  Cookies = case get_header_value("cookie", THIS) of
+		      undefined -> [];
+		      Value -> mochiweb_cookies:parse_cookie(Value)
+		    end,
+	  put(?SAVE_COOKIE, Cookies),
+	  Cookies;
+      Cached -> Cached
     end.
 
 %% @spec parse_post(request()) -> [{Key::string(), Value::string()}]
 %% @doc Parse an application/x-www-form-urlencoded form POST. This
 %%      has the side-effect of calling recv_body().
-parse_post({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+parse_post({?MODULE,
+	    [_Socket, _Opts, _Method, _RawPath, _Version,
+	     _Headers]} =
+	       THIS) ->
     case erlang:get(?SAVE_POST) of
-        undefined ->
-            Parsed = case recv_body(THIS) of
-                         undefined ->
-                             [];
-                         Binary ->
-                             case get_primary_header_value("content-type",THIS) of
-                                 "application/x-www-form-urlencoded" ++ _ ->
-                                     mochiweb_util:parse_qs(Binary);
-                                 _ ->
-                                     []
-                             end
-                     end,
-            put(?SAVE_POST, Parsed),
-            Parsed;
-        Cached ->
-            Cached
+      undefined ->
+	  Parsed = case recv_body(THIS) of
+		     undefined -> [];
+		     Binary ->
+			 case get_primary_header_value("content-type", THIS) of
+			   "application/x-www-form-urlencoded" ++ _ ->
+			       mochiweb_util:parse_qs(Binary);
+			   _ -> []
+			 end
+		   end,
+	  put(?SAVE_POST, Parsed),
+	  Parsed;
+      Cached -> Cached
     end.
 
 %% @spec stream_chunked_body(integer(), fun(), term(), request()) -> term()
 %% @doc The function is called for each chunk.
 %%      Used internally by read_chunked_body.
 stream_chunked_body(MaxChunkSize, Fun, FunState,
-                    {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+		    {?MODULE,
+		     [_Socket, _Opts, _Method, _RawPath, _Version,
+		      _Headers]} =
+			THIS) ->
     case read_chunk_length(THIS) of
-        0 ->
-            Fun({0, read_chunk(0, THIS)}, FunState);
-        Length when Length > MaxChunkSize ->
-            NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState, THIS),
-            stream_chunked_body(MaxChunkSize, Fun, NewState, THIS);
-        Length ->
-            NewState = Fun({Length, read_chunk(Length, THIS)}, FunState),
-            stream_chunked_body(MaxChunkSize, Fun, NewState, THIS)
+      0 -> Fun({0, read_chunk(0, THIS)}, FunState);
+      Length when Length > MaxChunkSize ->
+	  NewState = read_sub_chunks(Length, MaxChunkSize, Fun,
+				     FunState, THIS),
+	  stream_chunked_body(MaxChunkSize, Fun, NewState, THIS);
+      Length ->
+	  NewState = Fun({Length, read_chunk(Length, THIS)},
+			 FunState),
+	  stream_chunked_body(MaxChunkSize, Fun, NewState, THIS)
     end.
 
-stream_unchunked_body(_MaxChunkSize, 0, Fun, FunState, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
+stream_unchunked_body(_MaxChunkSize, 0, Fun, FunState,
+		      {?MODULE,
+		       [_Socket, _Opts, _Method, _RawPath, _Version,
+			_Headers]}) ->
     Fun({0, <<>>}, FunState);
-stream_unchunked_body(MaxChunkSize, Length, Fun, FunState,
-                      {?MODULE, [_Socket, Opts, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > 0 ->
-    RecBuf = case mochilists:get_value(recbuf, Opts, ?RECBUF_SIZE) of
-        undefined -> %os controlled buffer size
-            MaxChunkSize;
-        Val  ->
-            Val
-    end,
-    PktSize=min(Length,RecBuf),
+stream_unchunked_body(MaxChunkSize, Length, Fun,
+		      FunState,
+		      {?MODULE,
+		       [_Socket, Opts, _Method, _RawPath, _Version,
+			_Headers]} =
+			  THIS)
+    when Length > 0 ->
+    RecBuf = case mochilists:get_value(recbuf, Opts,
+				       ?RECBUF_SIZE)
+		 of
+	       undefined -> %os controlled buffer size
+		   MaxChunkSize;
+	       Val -> Val
+	     end,
+    PktSize = min(Length, RecBuf),
     Bin = recv(PktSize, THIS),
     NewState = Fun({PktSize, Bin}, FunState),
-    stream_unchunked_body(MaxChunkSize, Length - PktSize, Fun, NewState, THIS).
+    stream_unchunked_body(MaxChunkSize, Length - PktSize,
+			  Fun, NewState, THIS).
 
 %% @spec read_chunk_length(request()) -> integer()
 %% @doc Read the length of the next HTTP chunk.
-read_chunk_length({?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, line}])),
+read_chunk_length({?MODULE,
+		   [Socket, _Opts, _Method, _RawPath, _Version,
+		    _Headers]}) ->
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 line}])),
     case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of
-        {ok, Header} ->
-            ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, raw}])),
-            Splitter = fun (C) ->
-                               C =/= $\r andalso C =/= $\n andalso C =/= $
-                       end,
-            {Hex, _Rest} = lists:splitwith(Splitter, binary_to_list(Header)),
-            mochihex:to_int(Hex);
-        _ ->
-            exit(normal)
+      {ok, Header} ->
+	  ok =
+	      mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+								     [{packet,
+								       raw}])),
+	  Splitter = fun (C) ->
+			     C =/= $\r andalso C =/= $\n andalso C =/= $\n
+		     end,
+	  {Hex, _Rest} = lists:splitwith(Splitter,
+					 binary_to_list(Header)),
+	  mochihex:to_int(Hex);
+      _ -> exit(normal)
     end.
 
 %% @spec read_chunk(integer(), request()) -> Chunk::binary() | [Footer::binary()]
 %% @doc Read in a HTTP chunk of the given length. If Length is 0, then read the
 %%      HTTP footers (as a list of binaries, since they're nominal).
-read_chunk(0, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, line}])),
+read_chunk(0,
+	   {?MODULE,
+	    [Socket, _Opts, _Method, _RawPath, _Version,
+	     _Headers]}) ->
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 line}])),
     F = fun (F1, Acc) ->
-                case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of
-                    {ok, <<"\r\n">>} ->
-                        Acc;
-                    {ok, Footer} ->
-                        F1(F1, [Footer | Acc]);
-                    _ ->
-                        exit(normal)
-                end
-        end,
+		case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of
+		  {ok, <<"\r\n">>} -> Acc;
+		  {ok, Footer} -> F1(F1, [Footer | Acc]);
+		  _ -> exit(normal)
+		end
+	end,
     Footers = F(F, []),
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, raw}])),
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet,
+								 raw}])),
     put(?SAVE_RECV, true),
     Footers;
-read_chunk(Length, {?MODULE, [Socket, _Opts, _Method, _RawPath, _Version, _Headers]}) ->
-    case mochiweb_socket:recv(Socket, 2 + Length, ?IDLE_TIMEOUT) of
-        {ok, <<Chunk:Length/binary, "\r\n">>} ->
-            Chunk;
-        _ ->
-            exit(normal)
+read_chunk(Length,
+	   {?MODULE,
+	    [Socket, _Opts, _Method, _RawPath, _Version,
+	     _Headers]}) ->
+    case mochiweb_socket:recv(Socket, 2 + Length,
+			      ?IDLE_TIMEOUT)
+	of
+      {ok, <<Chunk:Length/binary, "\r\n">>} -> Chunk;
+      _ -> exit(normal)
     end.
 
 read_sub_chunks(Length, MaxChunkSize, Fun, FunState,
-                {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > MaxChunkSize ->
+		{?MODULE,
+		 [_Socket, _Opts, _Method, _RawPath, _Version,
+		  _Headers]} =
+		    THIS)
+    when Length > MaxChunkSize ->
     Bin = recv(MaxChunkSize, THIS),
     NewState = Fun({size(Bin), Bin}, FunState),
-    read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState, THIS);
-
+    read_sub_chunks(Length - MaxChunkSize, MaxChunkSize,
+		    Fun, NewState, THIS);
 read_sub_chunks(Length, _MaxChunkSize, Fun, FunState,
-                {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+		{?MODULE,
+		 [_Socket, _Opts, _Method, _RawPath, _Version,
+		  _Headers]} =
+		    THIS) ->
     Fun({Length, read_chunk(Length, THIS)}, FunState).
 
 %% @spec serve_file(Path, DocRoot, request()) -> Response
 %% @doc Serve a file relative to DocRoot.
-serve_file(Path, DocRoot, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+serve_file(Path, DocRoot,
+	   {?MODULE,
+	    [_Socket, _Opts, _Method, _RawPath, _Version,
+	     _Headers]} =
+	       THIS) ->
     serve_file(Path, DocRoot, [], THIS).
 
 %% @spec serve_file(Path, DocRoot, ExtraHeaders, request()) -> Response
 %% @doc Serve a file relative to DocRoot.
-serve_file(Path, DocRoot, ExtraHeaders, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+serve_file(Path, DocRoot, ExtraHeaders,
+	   {?MODULE,
+	    [_Socket, _Opts, _Method, _RawPath, _Version,
+	     _Headers]} =
+	       THIS) ->
     case mochiweb_util:safe_relative_path(Path) of
-        undefined ->
-            not_found(ExtraHeaders, THIS);
-        RelPath ->
-            FullPath = filename:join([DocRoot, RelPath]),
-            case filelib:is_dir(FullPath) of
-                true ->
-                    maybe_redirect(RelPath, FullPath, ExtraHeaders, THIS);
-                false ->
-                    maybe_serve_file(FullPath, ExtraHeaders, THIS)
-            end
+      undefined -> not_found(ExtraHeaders, THIS);
+      RelPath ->
+	  FullPath = filename:join([DocRoot, RelPath]),
+	  case filelib:is_dir(FullPath) of
+	    true ->
+		maybe_redirect(RelPath, FullPath, ExtraHeaders, THIS);
+	    false -> maybe_serve_file(FullPath, ExtraHeaders, THIS)
+	  end
     end.
 
 %% Internal API
@@ -660,104 +863,111 @@ serve_file(Path, DocRoot, ExtraHeaders, {?MODULE, [_Socket, _Opts, _Method, _Raw
 directory_index(FullPath) ->
     filename:join([FullPath, "index.html"]).
 
-maybe_redirect([], FullPath, ExtraHeaders, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS);
-
+maybe_redirect([], FullPath, ExtraHeaders,
+	       {?MODULE,
+		[_Socket, _Opts, _Method, _RawPath, _Version,
+		 _Headers]} =
+		   THIS) ->
+    maybe_serve_file(directory_index(FullPath),
+		     ExtraHeaders, THIS);
 maybe_redirect(RelPath, FullPath, ExtraHeaders,
-               {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, Headers]}=THIS) ->
+	       {?MODULE,
+		[_Socket, _Opts, _Method, _RawPath, _Version,
+		 Headers]} =
+		   THIS) ->
     case string:right(RelPath, 1) of
-        "/" ->
-            maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS);
-        _   ->
-            Host = mochiweb_headers:get_value("host", Headers),
-            Location = "http://" ++ Host  ++ "/" ++ RelPath ++ "/",
-            LocationBin = list_to_binary(Location),
-            MoreHeaders = [{"Location", Location},
-                           {"Content-Type", "text/html"} | ExtraHeaders],
-            Top = <<"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
-            "<html><head>"
-            "<title>301 Moved Permanently</title>"
-            "</head><body>"
-            "<h1>Moved Permanently</h1>"
-            "<p>The document has moved <a href=\"">>,
-            Bottom = <<">here</a>.</p></body></html>\n">>,
-            Body = <<Top/binary, LocationBin/binary, Bottom/binary>>,
-            respond({301, MoreHeaders, Body}, THIS)
+      "/" ->
+	  maybe_serve_file(directory_index(FullPath),
+			   ExtraHeaders, THIS);
+      _ ->
+	  Host = mochiweb_headers:get_value("host", Headers),
+	  Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/",
+	  LocationBin = list_to_binary(Location),
+	  MoreHeaders = [{"Location", Location},
+			 {"Content-Type", "text/html"}
+			 | ExtraHeaders],
+	  Top = <<"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD "
+		  "HTML 2.0//EN\"><html><head><title>301 "
+		  "Moved Permanently</title></head><body><h1>Mov"
+		  "ed Permanently</h1><p>The document has "
+		  "moved <a href=\"">>,
+	  Bottom = <<">here</a>.</p></body></html>\n">>,
+	  Body = <<Top/binary, LocationBin/binary,
+		   Bottom/binary>>,
+	  respond({301, MoreHeaders, Body}, THIS)
     end.
 
-maybe_serve_file(File, ExtraHeaders, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+maybe_serve_file(File, ExtraHeaders,
+		 {?MODULE,
+		  [_Socket, _Opts, _Method, _RawPath, _Version,
+		   _Headers]} =
+		     THIS) ->
     case file:read_file_info(File) of
-        {ok, FileInfo} ->
-            LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime),
-            case get_header_value("if-modified-since", THIS) of
-                LastModified ->
-                    respond({304, ExtraHeaders, ""}, THIS);
-                _ ->
-                    case file:open(File, [raw, binary]) of
-                        {ok, IoDevice} ->
-                            ContentType = mochiweb_util:guess_mime(File),
-                            Res = ok({ContentType,
-                                      [{"last-modified", LastModified}
-                                       | ExtraHeaders],
-                                      {file, IoDevice}}, THIS),
-                            ok = file:close(IoDevice),
-                            Res;
-                        _ ->
-                            not_found(ExtraHeaders, THIS)
-                    end
-            end;
-        {error, _} ->
-            not_found(ExtraHeaders, THIS)
+      {ok, FileInfo} ->
+	  LastModified =
+	      httpd_util:rfc1123_date(FileInfo#file_info.mtime),
+	  case get_header_value("if-modified-since", THIS) of
+	    LastModified -> respond({304, ExtraHeaders, ""}, THIS);
+	    _ ->
+		case file:open(File, [raw, binary]) of
+		  {ok, IoDevice} ->
+		      ContentType = mochiweb_util:guess_mime(File),
+		      Res = ok({ContentType,
+				[{"last-modified", LastModified}
+				 | ExtraHeaders],
+				{file, IoDevice}},
+			       THIS),
+		      ok = file:close(IoDevice),
+		      Res;
+		  _ -> not_found(ExtraHeaders, THIS)
+		end
+	  end;
+      {error, _} -> not_found(ExtraHeaders, THIS)
     end.
 
 server_headers() ->
-    [{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"},
+    [{"Server", "MochiWeb/1.0 (" ++ (?QUIP) ++ ")"},
      {"Date", mochiweb_clock:rfc1123()}].
 
 make_code(X) when is_integer(X) ->
-    [integer_to_list(X), [" " | httpd_util:reason_phrase(X)]];
-make_code(Io) when is_list(Io); is_binary(Io) ->
-    Io.
+    [integer_to_list(X),
+     [" " | httpd_util:reason_phrase(X)]];
+make_code(Io) when is_list(Io); is_binary(Io) -> Io.
 
-make_version({1, 0}) ->
-    <<"HTTP/1.0 ">>;
-make_version(_) ->
-    <<"HTTP/1.1 ">>.
+make_version({1, 0}) -> <<"HTTP/1.0 ">>;
+make_version(_) -> <<"HTTP/1.1 ">>.
 
 range_parts({file, IoDevice}, Ranges) ->
     Size = mochiweb_io:iodevice_size(IoDevice),
     F = fun (Spec, Acc) ->
-                case mochiweb_http:range_skip_length(Spec, Size) of
-                    invalid_range ->
-                        Acc;
-                    V ->
-                        [V | Acc]
-                end
-        end,
+		case mochiweb_http:range_skip_length(Spec, Size) of
+		  invalid_range -> Acc;
+		  V -> [V | Acc]
+		end
+	end,
     LocNums = lists:foldr(F, [], Ranges),
     {ok, Data} = file:pread(IoDevice, LocNums),
-    Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) ->
-                                   case Length of
-                                       0 ->
-                                           {Skip, Skip, <<>>};
-                                       _ ->
-                                           {Skip, Skip + Length - 1, PartialBody}
-                                   end
-                           end,
-                           LocNums, Data),
+    Bodies = lists:zipwith(fun ({Skip, Length},
+				PartialBody) ->
+				   case Length of
+				     0 -> {Skip, Skip, <<>>};
+				     _ -> {Skip, Skip + Length - 1, PartialBody}
+				   end
+			   end,
+			   LocNums, Data),
     {Bodies, Size};
 range_parts(Body0, Ranges) ->
     Body = iolist_to_binary(Body0),
     Size = size(Body),
-    F = fun(Spec, Acc) ->
-                case mochiweb_http:range_skip_length(Spec, Size) of
-                    invalid_range ->
-                        Acc;
-                    {Skip, Length} ->
-                        <<_:Skip/binary, PartialBody:Length/binary, _/binary>> = Body,
-                        [{Skip, Skip + Length - 1, PartialBody} | Acc]
-                end
-        end,
+    F = fun (Spec, Acc) ->
+		case mochiweb_http:range_skip_length(Spec, Size) of
+		  invalid_range -> Acc;
+		  {Skip, Length} ->
+		      <<_:Skip/binary, PartialBody:Length/binary, _/binary>> =
+			  Body,
+		      [{Skip, Skip + Length - 1, PartialBody} | Acc]
+		end
+	end,
     {lists:foldr(F, [], Ranges), Size}.
 
 %% @spec accepted_encodings([encoding()], request()) -> [encoding()] | bad_accept_encoding_value
@@ -784,20 +994,23 @@ range_parts(Body0, Ranges) ->
 %%         accepted_encodings(["gzip", "deflate", "identity"]) ->
 %%            ["deflate", "gzip", "identity"]
 %%
-accepted_encodings(SupportedEncodings, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    AcceptEncodingHeader = case get_header_value("Accept-Encoding", THIS) of
-        undefined ->
-            "";
-        Value ->
-            Value
-    end,
-    case mochiweb_util:parse_qvalues(AcceptEncodingHeader) of
-        invalid_qvalue_string ->
-            bad_accept_encoding_value;
-        QList ->
-            mochiweb_util:pick_accepted_encodings(
-                QList, SupportedEncodings, "identity"
-            )
+accepted_encodings(SupportedEncodings,
+		   {?MODULE,
+		    [_Socket, _Opts, _Method, _RawPath, _Version,
+		     _Headers]} =
+		       THIS) ->
+    AcceptEncodingHeader = case
+			     get_header_value("Accept-Encoding", THIS)
+			       of
+			     undefined -> "";
+			     Value -> Value
+			   end,
+    case mochiweb_util:parse_qvalues(AcceptEncodingHeader)
+	of
+      invalid_qvalue_string -> bad_accept_encoding_value;
+      QList ->
+	  mochiweb_util:pick_accepted_encodings(QList,
+						SupportedEncodings, "identity")
     end.
 
 %% @spec accepts_content_type(string() | binary(), request()) -> boolean() | bad_accept_header
@@ -822,27 +1035,28 @@ accepted_encodings(SupportedEncodings, {?MODULE, [_Socket, _Opts, _Method, _RawP
 %%      5) For an "Accept" header with value "text/*; q=0.0, */*":
 %%         accepts_content_type("text/plain") -> false
 %%
-accepts_content_type(ContentType1, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]),
+accepts_content_type(ContentType1,
+		     {?MODULE,
+		      [_Socket, _Opts, _Method, _RawPath, _Version,
+		       _Headers]} =
+			 THIS) ->
+    ContentType = re:replace(ContentType1, "\\s", "",
+			     [global, {return, list}]),
     AcceptHeader = accept_header(THIS),
     case mochiweb_util:parse_qvalues(AcceptHeader) of
-        invalid_qvalue_string ->
-            bad_accept_header;
-        QList ->
-            [MainType, _SubType] = string:tokens(ContentType, "/"),
-            SuperType = MainType ++ "/*",
-            lists:any(
-                fun({"*/*", Q}) when Q > 0.0 ->
-                        true;
-                    ({Type, Q}) when Q > 0.0 ->
-                        Type =:= ContentType orelse Type =:= SuperType;
-                    (_) ->
-                        false
-                end,
-                QList
-            ) andalso
-            (not lists:member({ContentType, 0.0}, QList)) andalso
-            (not lists:member({SuperType, 0.0}, QList))
+      invalid_qvalue_string -> bad_accept_header;
+      QList ->
+	  [MainType, _SubType] = string:tokens(ContentType, "/"),
+	  SuperType = MainType ++ "/*",
+	  lists:any(fun ({"*/*", Q}) when Q > 0.0 -> true;
+			({Type, Q}) when Q > 0.0 ->
+			    Type =:= ContentType orelse Type =:= SuperType;
+			(_) -> false
+		    end,
+		    QList)
+	    andalso
+	    not lists:member({ContentType, 0.0}, QList) andalso
+	      not lists:member({SuperType, 0.0}, QList)
     end.
 
 %% @spec accepted_content_types([string() | binary()], request()) -> [string()] | bad_accept_header
@@ -871,57 +1085,67 @@ accepts_content_type(ContentType1, {?MODULE, [_Socket, _Opts, _Method, _RawPath,
 %%         accepts_content_types(["application/json", "text/html"]) ->
 %%             ["text/html", "application/json"]
 %%
-accepted_content_types(Types1, {?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
-    Types = lists:map(
-        fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end,
-        Types1),
+accepted_content_types(Types1,
+		       {?MODULE,
+			[_Socket, _Opts, _Method, _RawPath, _Version,
+			 _Headers]} =
+			   THIS) ->
+    Types = [accepted_content_types_1(V1) || V1 <- Types1],
     AcceptHeader = accept_header(THIS),
     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)]
+      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({?MODULE, [_Socket, _Opts, _Method, _RawPath, _Version, _Headers]}=THIS) ->
+accepted_content_types_1(T) ->
+    re:replace(T, "\\s", "", [global, {return, list}]).
+
+accept_header({?MODULE,
+	       [_Socket, _Opts, _Method, _RawPath, _Version,
+		_Headers]} =
+		  THIS) ->
     case get_header_value("Accept", THIS) of
-        undefined ->
-            "*/*";
-        Value ->
-            Value
+      undefined -> "*/*";
+      Value -> Value
     end.
 
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
+
 -endif.
diff --git a/src/mochiweb_response.erl b/src/mochiweb_response.erl
index 81325b5..2f5b544 100644
--- a/src/mochiweb_response.erl
+++ b/src/mochiweb_response.erl
@@ -22,11 +22,13 @@
 %% @doc Response abstraction.
 
 -module(mochiweb_response).
+
 -author('bob@mochimedia.com').
 
 -define(QUIP, "Any of you quaids got a smint?").
 
--export([new/3, get_header_value/2, get/2, dump/1]).
+-export([dump/1, get/2, get_header_value/2, new/3]).
+
 -export([send/2, write_chunk/2]).
 
 %% @type response(). A mochiweb_response parameterized module instance.
@@ -39,7 +41,8 @@ new(Request, Code, Headers) ->
 %% @spec get_header_value(string() | atom() | binary(), response()) ->
 %%           string() | undefined
 %% @doc Get the value of the given response header.
-get_header_value(K, {?MODULE, [_Request, _Code, Headers]}) ->
+get_header_value(K,
+		 {?MODULE, [_Request, _Code, Headers]}) ->
     mochiweb_headers:get_value(K, Headers).
 
 %% @spec get(request | code | headers, response()) -> term()
@@ -55,36 +58,38 @@ get(headers, {?MODULE, [_Request, _Code, Headers]}) ->
 %% @doc Dump the internal representation to a "human readable" set of terms
 %%      for debugging/inspection purposes.
 dump({?MODULE, [{ReqM, _} = Request, Code, Headers]}) ->
-    [{request, ReqM:dump(Request)},
-     {code, Code},
+    [{request, ReqM:dump(Request)}, {code, Code},
      {headers, mochiweb_headers:to_list(Headers)}].
 
 %% @spec send(iodata(), response()) -> ok
 %% @doc Send data over the socket if the method is not HEAD.
-send(Data, {?MODULE, [{ReqM, _} = Request, _Code, _Headers]}) ->
+send(Data,
+     {?MODULE, [{ReqM, _} = Request, _Code, _Headers]}) ->
     case ReqM:get(method, Request) of
-        'HEAD' ->
-            ok;
-        _ ->
-            ReqM:send(Data, Request)
+      'HEAD' -> ok;
+      _ -> ReqM:send(Data, Request)
     end.
 
 %% @spec write_chunk(iodata(), response()) -> ok
 %% @doc Write a chunk of a HTTP chunked response. If Data is zero length,
 %%      then the chunked response will be finished.
-write_chunk(Data, {?MODULE, [{ReqM, _} = Request, _Code, _Headers]}=THIS) ->
+write_chunk(Data,
+	    {?MODULE, [{ReqM, _} = Request, _Code, _Headers]} =
+		THIS) ->
     case ReqM:get(version, Request) of
-        Version when Version >= {1, 1} ->
-            Length = iolist_size(Data),
-            send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS);
-        _ ->
-            send(Data, THIS)
+      Version when Version >= {1, 1} ->
+	  Length = iolist_size(Data),
+	  send([io_lib:format("~.16b\r\n", [Length]), Data,
+		<<"\r\n">>],
+	       THIS);
+      _ -> send(Data, THIS)
     end.
 
-
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
+
 -endif.
diff --git a/src/mochiweb_websocket.erl b/src/mochiweb_websocket.erl
index c162980..c2e2ab6 100644
--- a/src/mochiweb_websocket.erl
+++ b/src/mochiweb_websocket.erl
@@ -1,4 +1,5 @@
 -module(mochiweb_websocket).
+
 -author('lukasz.lalik@zadane.pl').
 
 %% The MIT License (MIT)
@@ -25,43 +26,45 @@
 
 %% @doc Websockets module for Mochiweb. Based on Misultin websockets module.
 
--export([loop/5, upgrade_connection/2, request/5]).
+-export([loop/5, request/5, upgrade_connection/2]).
+
 -export([send/3]).
+
 -ifdef(TEST).
--export([make_handshake/1, hixie_handshake/7, parse_hybi_frames/3, parse_hixie_frames/2]).
+
+-export([hixie_handshake/7, make_handshake/1,
+	 parse_hixie_frames/2, parse_hybi_frames/3]).
+
 -endif.
 
 loop(Socket, Body, State, WsVersion, ReplyChannel) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, 0}, {active, once}])),
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet, 0},
+								{active,
+								 once}])),
     proc_lib:hibernate(?MODULE, request,
-                       [Socket, Body, State, WsVersion, ReplyChannel]).
+		       [Socket, Body, State, WsVersion, ReplyChannel]).
 
 request(Socket, Body, State, WsVersion, ReplyChannel) ->
     receive
-        {tcp_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {ssl_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {tcp_error, _, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {Proto, _, WsFrames} when Proto =:= tcp orelse Proto =:= ssl ->
-            case parse_frames(WsVersion, WsFrames, Socket) of
-                close ->
-                    mochiweb_socket:close(Socket),
-                    exit(normal);
-                error ->
-                    mochiweb_socket:close(Socket),
-                    exit(normal);
-                Payload ->
-                    NewState = call_body(Body, Payload, State, ReplyChannel),
-                    loop(Socket, Body, NewState, WsVersion, ReplyChannel)
-            end;
-        _ ->
-            mochiweb_socket:close(Socket),
-            exit(normal)
+      {tcp_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {ssl_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {tcp_error, _, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {Proto, _, WsFrames}
+	  when Proto =:= tcp orelse Proto =:= ssl ->
+	  case parse_frames(WsVersion, WsFrames, Socket) of
+	    close -> mochiweb_socket:close(Socket), exit(normal);
+	    error -> mochiweb_socket:close(Socket), exit(normal);
+	    Payload ->
+		NewState = call_body(Body, Payload, State,
+				     ReplyChannel),
+		loop(Socket, Body, NewState, WsVersion, ReplyChannel)
+	  end;
+      _ -> mochiweb_socket:close(Socket), exit(normal)
     end.
 
 call_body({M, F, A}, Payload, State, ReplyChannel) ->
@@ -72,63 +75,68 @@ call_body(Body, Payload, State, ReplyChannel) ->
     Body(Payload, State, ReplyChannel).
 
 send(Socket, Payload, hybi) ->
-    Prefix = <<1:1, 0:3, 1:4, (payload_length(iolist_size(Payload)))/binary>>,
+    Prefix = <<1:1, 0:3, 1:4,
+	       (payload_length(iolist_size(Payload)))/binary>>,
     mochiweb_socket:send(Socket, [Prefix, Payload]);
 send(Socket, Payload, hixie) ->
     mochiweb_socket:send(Socket, [0, Payload, 255]).
 
 upgrade_connection({ReqM, _} = Req, Body) ->
     case make_handshake(Req) of
-        {Version, Response} ->
-            ReqM:respond(Response, Req),
-            Socket = ReqM:get(socket, Req),
-            ReplyChannel = fun (Payload) ->
-                ?MODULE:send(Socket, Payload, Version)
-            end,
-            Reentry = fun (State) ->
-                ?MODULE:loop(Socket, Body, State, Version, ReplyChannel)
-            end,
-            {Reentry, ReplyChannel};
-        _ ->
-            mochiweb_socket:close(ReqM:get(socket, Req)),
-            exit(normal)
+      {Version, Response} ->
+	  ReqM:respond(Response, Req),
+	  Socket = ReqM:get(socket, Req),
+	  ReplyChannel = fun (Payload) ->
+				 (?MODULE):send(Socket, Payload, Version)
+			 end,
+	  Reentry = fun (State) ->
+			    (?MODULE):loop(Socket, Body, State, Version,
+					   ReplyChannel)
+		    end,
+	  {Reentry, ReplyChannel};
+      _ ->
+	  mochiweb_socket:close(ReqM:get(socket, Req)),
+	  exit(normal)
     end.
 
 make_handshake({ReqM, _} = Req) ->
-    SecKey  = ReqM:get_header_value("sec-websocket-key", Req),
-    Sec1Key = ReqM:get_header_value("Sec-WebSocket-Key1", Req),
-    Sec2Key = ReqM:get_header_value("Sec-WebSocket-Key2", Req),
+    SecKey = ReqM:get_header_value("sec-websocket-key",
+				   Req),
+    Sec1Key = ReqM:get_header_value("Sec-WebSocket-Key1",
+				    Req),
+    Sec2Key = ReqM:get_header_value("Sec-WebSocket-Key2",
+				    Req),
     Origin = ReqM:get_header_value(origin, Req),
-    if SecKey =/= undefined ->
-            hybi_handshake(SecKey);
+    if SecKey =/= undefined -> hybi_handshake(SecKey);
        Sec1Key =/= undefined andalso Sec2Key =/= undefined ->
-            Host = ReqM:get_header_value("Host", Req),
-            Path = ReqM:get(path, Req),
-            Body = ReqM:recv(8, Req),
-            Scheme = scheme(Req),
-            hixie_handshake(Scheme, Host, Path, Sec1Key, Sec2Key, Body, Origin);
-       true ->
-          error
+	   Host = ReqM:get_header_value("Host", Req),
+	   Path = ReqM:get(path, Req),
+	   Body = ReqM:recv(8, Req),
+	   Scheme = scheme(Req),
+	   hixie_handshake(Scheme, Host, Path, Sec1Key, Sec2Key,
+			   Body, Origin);
+       true -> error
     end.
 
 hybi_handshake(SecKey) ->
     BinKey = list_to_binary(SecKey),
-    Bin = <<BinKey/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11">>,
+    Bin = <<BinKey/binary,
+	    "258EAFA5-E914-47DA-95CA-C5AB0DC85B11">>,
     Challenge = base64:encode(crypto:hash(sha, Bin)),
-    Response = {101, [{"Connection", "Upgrade"},
-                      {"Upgrade", "websocket"},
-                      {"Sec-Websocket-Accept", Challenge}], ""},
+    Response = {101,
+		[{"Connection", "Upgrade"}, {"Upgrade", "websocket"},
+		 {"Sec-Websocket-Accept", Challenge}],
+		""},
     {hybi, Response}.
 
 scheme(Req) ->
     case mochiweb_request:get(scheme, Req) of
-        http ->
-            "ws://";
-        https ->
-            "wss://"
+      http -> "ws://";
+      https -> "wss://"
     end.
 
-hixie_handshake(Scheme, Host, Path, Key1, Key2, Body, Origin) ->
+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]),
@@ -136,116 +144,93 @@ hixie_handshake(Scheme, Host, Path, Key1, Key2, Body, Origin) ->
     Part1 = erlang:list_to_integer(Ikey1) div Blank1,
     Part2 = erlang:list_to_integer(Ikey2) div Blank2,
     Ckey = <<Part1:4/big-unsigned-integer-unit:8,
-            Part2:4/big-unsigned-integer-unit:8,
-            Body/binary>>,
+	     Part2:4/big-unsigned-integer-unit:8, Body/binary>>,
     Challenge = erlang:md5(Ckey),
     Location = lists:concat([Scheme, Host, Path]),
-    Response = {101, [{"Upgrade", "WebSocket"},
-                      {"Connection", "Upgrade"},
-                      {"Sec-WebSocket-Origin", Origin},
-                      {"Sec-WebSocket-Location", Location}],
-                Challenge},
+    Response = {101,
+		[{"Upgrade", "WebSocket"}, {"Connection", "Upgrade"},
+		 {"Sec-WebSocket-Origin", Origin},
+		 {"Sec-WebSocket-Location", Location}],
+		Challenge},
     {hixie, Response}.
 
 parse_frames(hybi, Frames, Socket) ->
     try parse_hybi_frames(Socket, Frames, []) of
-        Parsed -> process_frames(Parsed, [])
+      Parsed -> process_frames(Parsed, [])
     catch
-        _:_ -> error
+      _:_ -> error
     end;
 parse_frames(hixie, Frames, _Socket) ->
     try parse_hixie_frames(Frames, []) of
-        Payload -> Payload
+      Payload -> Payload
     catch
-        _:_ -> error
+      _:_ -> error
     end.
 
 %%
 %% Websockets internal functions for RFC6455 and hybi draft
 %%
-process_frames([], Acc) ->
-    lists:reverse(Acc);
+process_frames([], Acc) -> lists:reverse(Acc);
 process_frames([{Opcode, Payload} | Rest], Acc) ->
     case Opcode of
-        8 -> close;
-        _ ->
-            process_frames(Rest, [Payload | Acc])
+      8 -> close;
+      _ -> process_frames(Rest, [Payload | Acc])
     end.
 
-parse_hybi_frames(_, <<>>, Acc) ->
-    lists:reverse(Acc);
-parse_hybi_frames(S, <<_Fin:1,
-                      _Rsv:3,
-                      Opcode:4,
-                      _Mask:1,
-                      PayloadLen:7,
-                      MaskKey:4/binary,
-                      Payload:PayloadLen/binary-unit:8,
-                      Rest/binary>>,
-                  Acc) when PayloadLen < 126 ->
+parse_hybi_frames(_, <<>>, Acc) -> lists:reverse(Acc);
+parse_hybi_frames(S,
+		  <<_Fin:1, _Rsv:3, Opcode:4, _Mask:1, PayloadLen:7,
+		    MaskKey:4/binary, Payload:PayloadLen/binary-unit:8,
+		    Rest/binary>>,
+		  Acc)
+    when PayloadLen < 126 ->
     Payload2 = hybi_unmask(Payload, MaskKey, <<>>),
     parse_hybi_frames(S, Rest, [{Opcode, Payload2} | Acc]);
-parse_hybi_frames(S, <<_Fin:1,
-                      _Rsv:3,
-                      Opcode:4,
-                      _Mask:1,
-                      126:7,
-                      PayloadLen:16,
-                      MaskKey:4/binary,
-                      Payload:PayloadLen/binary-unit:8,
-                      Rest/binary>>,
-                  Acc) ->
+parse_hybi_frames(S,
+		  <<_Fin:1, _Rsv:3, Opcode:4, _Mask:1, 126:7,
+		    PayloadLen:16, MaskKey:4/binary,
+		    Payload:PayloadLen/binary-unit:8, Rest/binary>>,
+		  Acc) ->
     Payload2 = hybi_unmask(Payload, MaskKey, <<>>),
     parse_hybi_frames(S, Rest, [{Opcode, Payload2} | Acc]);
-parse_hybi_frames(Socket, <<_Fin:1,
-                           _Rsv:3,
-                           _Opcode:4,
-                           _Mask:1,
-                           126:7,
-                           _PayloadLen:16,
-                           _MaskKey:4/binary,
-                           _/binary-unit:8>> = PartFrame,
-                  Acc) ->
-    ok = mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket, [{packet, 0}, {active, once}])),
+parse_hybi_frames(Socket,
+		  <<_Fin:1, _Rsv:3, _Opcode:4, _Mask:1, 126:7,
+		    _PayloadLen:16, _MaskKey:4/binary, _/binary-unit:8>> =
+		      PartFrame,
+		  Acc) ->
+    ok =
+	mochiweb_socket:exit_if_closed(mochiweb_socket:setopts(Socket,
+							       [{packet, 0},
+								{active,
+								 once}])),
     receive
-        {tcp_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {ssl_closed, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {tcp_error, _, _} ->
-            mochiweb_socket:close(Socket),
-            exit(normal);
-        {Proto, _, Continuation} when Proto =:= tcp orelse Proto =:= ssl ->
-            parse_hybi_frames(Socket, <<PartFrame/binary, Continuation/binary>>,
-                              Acc);
-        _ ->
-            mochiweb_socket:close(Socket),
-            exit(normal)
-    after
-        5000 ->
-            mochiweb_socket:close(Socket),
-            exit(normal)
+      {tcp_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {ssl_closed, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {tcp_error, _, _} ->
+	  mochiweb_socket:close(Socket), exit(normal);
+      {Proto, _, Continuation}
+	  when Proto =:= tcp orelse Proto =:= ssl ->
+	  parse_hybi_frames(Socket,
+			    <<PartFrame/binary, Continuation/binary>>, Acc);
+      _ -> mochiweb_socket:close(Socket), exit(normal)
+      after 5000 ->
+		mochiweb_socket:close(Socket), exit(normal)
     end;
-parse_hybi_frames(S, <<_Fin:1,
-                      _Rsv:3,
-                      Opcode:4,
-                      _Mask:1,
-                      127:7,
-                      0:1,
-                      PayloadLen:63,
-                      MaskKey:4/binary,
-                      Payload:PayloadLen/binary-unit:8,
-                      Rest/binary>>,
-                  Acc) ->
+parse_hybi_frames(S,
+		  <<_Fin:1, _Rsv:3, Opcode:4, _Mask:1, 127:7, 0:1,
+		    PayloadLen:63, MaskKey:4/binary,
+		    Payload:PayloadLen/binary-unit:8, Rest/binary>>,
+		  Acc) ->
     Payload2 = hybi_unmask(Payload, MaskKey, <<>>),
     parse_hybi_frames(S, Rest, [{Opcode, Payload2} | Acc]).
 
 %% Unmasks RFC 6455 message
 hybi_unmask(<<O:32, Rest/bits>>, MaskKey, Acc) ->
     <<MaskKey2:32>> = MaskKey,
-    hybi_unmask(Rest, MaskKey, <<Acc/binary, (O bxor MaskKey2):32>>);
+    hybi_unmask(Rest, MaskKey,
+		<<Acc/binary, (O bxor MaskKey2):32>>);
 hybi_unmask(<<O:24>>, MaskKey, Acc) ->
     <<MaskKey2:24, _:8>> = MaskKey,
     <<Acc/binary, (O bxor MaskKey2):24>>;
@@ -255,27 +240,25 @@ hybi_unmask(<<O:16>>, MaskKey, Acc) ->
 hybi_unmask(<<O:8>>, MaskKey, Acc) ->
     <<MaskKey2:8, _:24>> = MaskKey,
     <<Acc/binary, (O bxor MaskKey2):8>>;
-hybi_unmask(<<>>, _MaskKey, Acc) ->
-    Acc.
+hybi_unmask(<<>>, _MaskKey, Acc) -> Acc.
 
 payload_length(N) ->
     case N of
-        N when N =< 125 -> << N >>;
-        N when N =< 16#ffff -> << 126, N:16 >>;
-        N when N =< 16#7fffffffffffffff -> << 127, N:64 >>
+      N when N =< 125 -> <<N>>;
+      N when N =< 65535 -> <<126, N:16>>;
+      N when N =< 9223372036854775807 -> <<127, N:64>>
     end.
 
-
 %%
 %% Websockets internal functions for hixie-76 websocket version
 %%
 parse_hixie_frames(<<>>, Frames) ->
-  lists:reverse(Frames);
+    lists:reverse(Frames);
 parse_hixie_frames(<<0, T/binary>>, Frames) ->
-  {Frame, Rest} = parse_hixie(T, <<>>),
-  parse_hixie_frames(Rest, [Frame | Frames]).
+    {Frame, Rest} = parse_hixie(T, <<>>),
+    parse_hixie_frames(Rest, [Frame | Frames]).
 
 parse_hixie(<<255, Rest/binary>>, Buffer) ->
-  {Buffer, Rest};
+    {Buffer, Rest};
 parse_hixie(<<H, T/binary>>, Buffer) ->
-  parse_hixie(T, <<Buffer/binary, H>>).
+    parse_hixie(T, <<Buffer/binary, H>>).
diff --git a/support/templates/mochiwebapp_skel/src/mochiapp_web.erl b/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
index ecd99c5..0b586b0 100644
--- a/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
+++ b/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
@@ -3,90 +3,69 @@
 
 %% @doc Web server for {{appid}}.
 
--module({{appid}}_web).
+-module('{{appid}}_web').
+
 -author("{{author}}").
 
--export([start/1, stop/0, loop/2]).
+-export([loop/2, start/1, stop/0]).
 
 %% External API
 
 start(Options) ->
     {DocRoot, Options1} = get_option(docroot, Options),
-    Loop = fun (Req) ->
-                   ?MODULE:loop(Req, DocRoot)
-           end,
-    mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
-
-stop() ->
-    mochiweb_http:stop(?MODULE).
+    Loop = fun (Req) -> (?MODULE):loop(Req, DocRoot) end,
+    mochiweb_http:start([{name, ?MODULE}, {loop, Loop}
+			 | Options1]).
 
+stop() -> mochiweb_http:stop(?MODULE).
 
 %% OTP 21 is the first to define OTP_RELEASE and the first to support
 %% EEP-0047 direct stack trace capture.
 -ifdef(OTP_RELEASE).
--if(?OTP_RELEASE >= 21).
+
+-if((?OTP_RELEASE) >= 21).
+
 -define(HAS_DIRECT_STACKTRACE, true).
+
 -endif.
+
 -endif.
 
 -ifdef(HAS_DIRECT_STACKTRACE).
--define(CAPTURE_EXC_PRE(Type, What, Trace), Type:What:Trace).
+
+- define ( CAPTURE_EXC_PRE ( Type , What , Trace ) , Type : What : Trace ) .
+
+
 -define(CAPTURE_EXC_GET(Trace), Trace).
+
 -else.
+
 -define(CAPTURE_EXC_PRE(Type, What, Trace), Type:What).
--define(CAPTURE_EXC_GET(Trace), erlang:get_stacktrace()).
+
+-define(CAPTURE_EXC_GET(Trace),
+	erlang:get_stacktrace()).
+
 -endif.
 
-loop(Req, DocRoot) ->
-    "/" ++ Path = mochiweb_request:get(path, Req),
-    try
-        case mochiweb_request:get(method, Req) of
-            Method when Method =:= 'GET'; Method =:= 'HEAD' ->
-                case Path of
-                    "hello_world" ->
-                        mochiweb_request:respond(
-                            {200, [{"Content-Type", "text/plain"}], "Hello world!\n"},
-                            Req
-                        );
-                    _ ->
-                        mochiweb_request:serve_file(Path, DocRoot, Req)
-                end;
-            'POST' ->
-                case Path of
-                    _ ->
-                        mochiweb_request:not_found(Req)
-                end;
-            _ ->
-                mochiweb_request:respond({501, [], []}, Req)
-        end
-    catch
-        ?CAPTURE_EXC_PRE(Type, What, Trace) ->
-            Report = ["web request failed",
-                      {path, Path},
-                      {type, Type}, {what, What},
-                      {trace, ?CAPTURE_EXC_GET(Trace)}],
-            error_logger:error_report(Report),
-            mochiweb_request:respond(
-                {500, [{"Content-Type", "text/plain"}], "request failed, sorry\n"},
-                Req
-            )
-    end.
+loop ( Req , DocRoot ) -> "/" ++ Path = mochiweb_request : get ( path , Req ) , try case mochiweb_request : get ( method , Req ) of Method when Method =:= 'GET' ; Method =:= 'HEAD' -> case Path of "hello_world" -> mochiweb_request : respond ( { 200 , [ { "Content-Type" , "text/plain" } ] , "Hello world!\n" } , Req ) ; _ -> mochiweb_request : serve_file ( Path , DocRoot , Req ) end ; 'POST' -> case Path of _ -> mochiweb_request : not_found ( Req ) end ; _ -> mochiweb_request : respond ( { [...]
+
 
 %% Internal API
 
 get_option(Option, Options) ->
-    {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
+    {proplists:get_value(Option, Options),
+     proplists:delete(Option, Options)}.
 
 %%
 %% Tests
 %%
 -ifdef(TEST).
+
 -include_lib("eunit/include/eunit.hrl").
 
 you_should_write_a_test() ->
-    ?assertEqual(
-       "No, but I will!",
-       "Have you written any tests?"),
+    ?assertEqual("No, but I will!",
+		 "Have you written any tests?"),
     ok.
 
 -endif.
diff --git a/test/mochiweb_http_tests.erl b/test/mochiweb_http_tests.erl
index 8fbf0f3..d58971a 100644
--- a/test/mochiweb_http_tests.erl
+++ b/test/mochiweb_http_tests.erl
@@ -1,49 +1,51 @@
 -module(mochiweb_http_tests).
+
 -include_lib("eunit/include/eunit.hrl").
 
 -ifdef(gen_tcp_r15b_workaround).
+
 -define(SHOULD_HAVE_BUG, true).
+
 -else.
+
 -define(SHOULD_HAVE_BUG, false).
+
 -endif.
 
 has_acceptor_bug_test_() ->
-    {setup,
-     fun start_server/0,
-     fun mochiweb_http:stop/1,
+    {setup, fun start_server/0, fun mochiweb_http:stop/1,
      fun has_acceptor_bug_tests/1}.
 
 start_server() ->
     application:start(inets),
     {ok, Pid} = mochiweb_http:start_link([{port, 0},
-                                          {loop, fun responder/1}]),
+					  {loop, fun responder/1}]),
     Pid.
 
 has_acceptor_bug_tests(Server) ->
     Port = mochiweb_socket_server:get(Server, port),
     [{"1000 should be fine even with the bug",
-      ?_assertEqual(false, has_bug(Port, 1000))},
+      ?_assertEqual(false, (has_bug(Port, 1000)))},
      {"10000 should trigger the bug if present",
-      ?_assertEqual(?SHOULD_HAVE_BUG, has_bug(Port, 10000))}].
+      ?_assertEqual((?SHOULD_HAVE_BUG),
+		    (has_bug(Port, 10000)))}].
 
 responder(Req) ->
-    mochiweb_request:respond(
-        {
-            200,
-            [{"Content-Type", "text/html"}],
-            ["<html><body>Hello</body></html>"]
-        },
-        Req).
+    mochiweb_request:respond({200,
+			      [{"Content-Type", "text/html"}],
+			      ["<html><body>Hello</body></html>"]},
+			     Req).
 
 has_bug(Port, Len) ->
-  case
-    httpc:request(get, {"http://127.0.0.1:" ++ integer_to_list(Port) ++ "/",
-                        [{"X-Random", lists:duplicate(Len, $a)}]}, [], [])
-  of
-      {error, socket_closed_remotely} ->
-          true;
-      {ok, {{"HTTP/1.1", 200, "OK"}, _, "<html><body>Hello</body></html>"}} ->
-          false;
-      {ok, {{"HTTP/1.1", 400, "Bad Request"}, _, []}} ->
-          false
-  end.
+    case httpc:request(get,
+		       {"http://127.0.0.1:" ++ integer_to_list(Port) ++ "/",
+			[{"X-Random", lists:duplicate(Len, $a)}]},
+		       [], [])
+	of
+      {error, socket_closed_remotely} -> true;
+      {ok,
+       {{"HTTP/1.1", 200, "OK"}, _,
+	"<html><body>Hello</body></html>"}} ->
+	  false;
+      {ok, {{"HTTP/1.1", 400, "Bad Request"}, _, []}} -> false
+    end.
diff --git a/test/mochiweb_request_tests.erl b/test/mochiweb_request_tests.erl
index 47fe7ee..119fc81 100644
--- a/test/mochiweb_request_tests.erl
+++ b/test/mochiweb_request_tests.erl
@@ -1,182 +1,238 @@
 -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, mochiweb_request:accepts_content_type("multipart/related", Req1)),
-    ?assertEqual(true, mochiweb_request:accepts_content_type(<<"multipart/related">>, Req1)),
-
+				mochiweb_headers:make([{"Accept",
+							"multipart/related"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req1))),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type(<<"multipart/related">>,
+							Req1))),
     Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req2)),
-
+				mochiweb_headers:make([{"Accept",
+							"text/html"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req2))),
     Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req3)),
-
+				mochiweb_headers:make([{"Accept",
+							"text/html, multipart/*"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req3))),
     Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0.0"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req4)),
-
+				mochiweb_headers:make([{"Accept",
+							"text/html, multipart/*; q=0.0"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req4))),
     Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req5)),
-
+				mochiweb_headers:make([{"Accept",
+							"text/html, multipart/*; q=0"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req5))),
     Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, */*; q=0.0"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req6)),
-
+				mochiweb_headers:make([{"Accept",
+							"text/html, */*; q=0.0"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req6))),
     Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "multipart/*; q=0.0, */*"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req7)),
-
+				mochiweb_headers:make([{"Accept",
+							"multipart/*; q=0.0, */*"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req7))),
     Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/*"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req8)),
-
+				mochiweb_headers:make([{"Accept",
+							"*/*; q=0.0, multipart/*"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req8))),
     Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/related"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req9)),
-
+				mochiweb_headers:make([{"Accept",
+							"*/*; q=0.0, multipart/related"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("multipart/related",
+							Req9))),
     Req10 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html;level=1", Req10)),
-
+				 mochiweb_headers:make([{"Accept",
+							 "text/html; level=1"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("text/html;level=1",
+							Req10))),
     Req11 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1, text/html"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html", Req11)),
-
+				 mochiweb_headers:make([{"Accept",
+							 "text/html; level=1, text/html"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("text/html",
+							Req11))),
     Req12 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("text/html;level=1", Req12)),
-
+				 mochiweb_headers:make([{"Accept",
+							 "text/html; level=1; q=0.0, text/html"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("text/html;level=1",
+							Req12))),
     Req13 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])),
-    ?assertEqual(false, mochiweb_request:accepts_content_type("text/html; level=1", Req13)),
-
+				 mochiweb_headers:make([{"Accept",
+							 "text/html; level=1; q=0.0, text/html"}])),
+    ?assertEqual(false,
+		 (mochiweb_request:accepts_content_type("text/html; level=1",
+							Req13))),
     Req14 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html;level=1;q=0.1, text/html"}])),
-    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html; level=1", Req14)).
+				 mochiweb_headers:make([{"Accept",
+							 "text/html;level=1;q=0.1, text/html"}])),
+    ?assertEqual(true,
+		 (mochiweb_request:accepts_content_type("text/html; level=1",
+							Req14))).
 
 accepted_encodings_test() ->
     Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-                                mochiweb_headers:make([])),
+				mochiweb_headers:make([])),
     ?assertEqual(["identity"],
-                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req1)),
-
+		 (mochiweb_request:accepted_encodings(["gzip",
+						       "identity"],
+						      Req1))),
     Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"gzip, deflate"}])),
     ?assertEqual(["gzip", "identity"],
-                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req2)),
-
+		 (mochiweb_request:accepted_encodings(["gzip",
+						       "identity"],
+						      Req2))),
     Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=0.5, deflate"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"gzip;q=0.5, deflate"}])),
     ?assertEqual(["deflate", "gzip", "identity"],
-                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req3)),
-
+		 (mochiweb_request:accepted_encodings(["gzip", "deflate",
+						       "identity"],
+						      Req3))),
     Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "identity, *;q=0"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"identity, *;q=0"}])),
     ?assertEqual(["identity"],
-                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req4)),
-
+		 (mochiweb_request:accepted_encodings(["gzip", "deflate",
+						       "identity"],
+						      Req4))),
     Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=0.1, *;q=0"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"gzip; q=0.1, *;q=0"}])),
     ?assertEqual(["gzip"],
-                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req5)),
-
+		 (mochiweb_request:accepted_encodings(["gzip", "deflate",
+						       "identity"],
+						      Req5))),
     Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip; q=, *;q=0"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"gzip; q=, *;q=0"}])),
     ?assertEqual(bad_accept_encoding_value,
-                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req6)),
-
+		 (mochiweb_request:accepted_encodings(["gzip", "deflate",
+						       "identity"],
+						      Req6))),
     Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "gzip;q=2.0, *;q=0"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"gzip;q=2.0, *;q=0"}])),
     ?assertEqual(bad_accept_encoding_value,
-                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req7)),
-
+		 (mochiweb_request:accepted_encodings(["gzip",
+						       "identity"],
+						      Req7))),
     Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])),
+				mochiweb_headers:make([{"Accept-Encoding",
+							"deflate, *;q=0.0"}])),
     ?assertEqual([],
-                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req8)).
+		 (mochiweb_request:accepted_encodings(["gzip",
+						       "identity"],
+						      Req8))).
 
 accepted_content_types_test() ->
     Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/html"}])),
     ?assertEqual(["text/html"],
-        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req1)),
-
+		 (mochiweb_request:accepted_content_types(["text/html",
+							   "application/json"],
+							  Req1))),
     Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html, */*;q=0"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/html, */*;q=0"}])),
     ?assertEqual(["text/html"],
-        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req2)),
-
+		 (mochiweb_request:accepted_content_types(["text/html",
+							   "application/json"],
+							  Req2))),
     Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/*, */*;q=0"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/*, */*;q=0"}])),
     ?assertEqual(["text/html"],
-        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req3)),
-
+		 (mochiweb_request:accepted_content_types(["text/html",
+							   "application/json"],
+							  Req3))),
     Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/*;q=0.8, */*;q=0.5"}])),
     ?assertEqual(["text/html", "application/json"],
-        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req4)),
-
+		 (mochiweb_request:accepted_content_types(["application/json",
+							   "text/html"],
+							  Req4))),
     Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/*;q=0.8, */*;q=0.5"}])),
     ?assertEqual(["text/html", "application/json"],
-        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req5)),
-
+		 (mochiweb_request:accepted_content_types(["text/html",
+							   "application/json"],
+							  Req5))),
     Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/*;q=0.5, */*;q=0.5"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/*;q=0.5, */*;q=0.5"}])),
     ?assertEqual(["application/json", "text/html"],
-        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req6)),
-
+		 (mochiweb_request:accepted_content_types(["application/json",
+							   "text/html"],
+							  Req6))),
     Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make(
-            [{"Accept", "text/html;q=0.5, application/json;q=0.5"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/html;q=0.5, application/json;q=0.5"}])),
     ?assertEqual(["application/json", "text/html"],
-        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req7)),
-
+		 (mochiweb_request:accepted_content_types(["application/json",
+							   "text/html"],
+							  Req7))),
     Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
-        mochiweb_headers:make([{"Accept", "text/html"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/html"}])),
     ?assertEqual([],
-        mochiweb_request:accepted_content_types(["application/json"], Req8)),
-
+		 (mochiweb_request:accepted_content_types(["application/json"],
+							  Req8))),
     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"}])),
+				mochiweb_headers:make([{"Accept",
+							"text/*;q=0.9, text/html;q=0.5, */*;q=0.7"}])),
     ?assertEqual(["application/json", "text/html"],
-        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req9)).
+		 (mochiweb_request:accepted_content_types(["text/html",
+							   "application/json"],
+							  Req9))).
 
 should_close_test() ->
     F = fun (V, H) ->
-                mochiweb_request:should_close(mochiweb_request:new(
-                   nil, 'GET', "/", V,
-                   mochiweb_headers:make(H)
-                  ))
-        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"}])),
+		mochiweb_request:should_close(mochiweb_request:new(nil,
+								   'GET', "/",
+								   V,
+								   mochiweb_headers:make(H)))
+	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.
diff --git a/test/mochiweb_tests.erl b/test/mochiweb_tests.erl
index ae88bda..ef688f1 100644
--- a/test/mochiweb_tests.erl
+++ b/test/mochiweb_tests.erl
@@ -1,130 +1,149 @@
 -module(mochiweb_tests).
+
 -include_lib("eunit/include/eunit.hrl").
+
 -include("mochiweb_test_util.hrl").
 
 with_server(Transport, ServerFun, ClientFun) ->
-    mochiweb_test_util:with_server(Transport, ServerFun, ClientFun).
+    mochiweb_test_util:with_server(Transport, ServerFun,
+				   ClientFun).
 
 request_test() ->
-    R = mochiweb_request:new(z, z, "//foo///bar/baz%20wibble+quux?qs=2", z, []),
-    "/foo/bar/baz wibble quux" = mochiweb_request:get(path, R),
+    R = mochiweb_request:new(z, z,
+			     "//foo///bar/baz%20wibble+quux?qs=2", z, []),
+    "/foo/bar/baz wibble quux" = mochiweb_request:get(path,
+						      R),
     ok.
 
 -define(LARGE_TIMEOUT, 60).
 
-single_http_GET_test() ->
-    do_GET(plain, 1).
+single_http_GET_test() -> do_GET(plain, 1).
 
-single_https_GET_test() ->
-    do_GET(ssl, 1).
+single_https_GET_test() -> do_GET(ssl, 1).
 
-multiple_http_GET_test() ->
-    do_GET(plain, 3).
+multiple_http_GET_test() -> do_GET(plain, 3).
 
-multiple_https_GET_test() ->
-    do_GET(ssl, 3).
+multiple_https_GET_test() -> do_GET(ssl, 3).
 
-hundred_http_GET_test_() -> % note the underscore
+hundred_http_GET_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_GET(plain,100)) end}.
+     fun () -> ?assertEqual(ok, (do_GET(plain, 100))) end}.
 
-hundred_https_GET_test_() -> % note the underscore
+hundred_https_GET_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_GET(ssl,100)) end}.
+     fun () -> ?assertEqual(ok, (do_GET(ssl, 100))) end}.
 
-single_128_http_POST_test() ->
-    do_POST(plain, 128, 1).
+single_128_http_POST_test() -> do_POST(plain, 128, 1).
 
-single_128_https_POST_test() ->
-    do_POST(ssl, 128, 1).
+single_128_https_POST_test() -> do_POST(ssl, 128, 1).
 
-single_2k_http_POST_test() ->
-    do_POST(plain, 2048, 1).
+single_2k_http_POST_test() -> do_POST(plain, 2048, 1).
 
-single_2k_https_POST_test() ->
-    do_POST(ssl, 2048, 1).
+single_2k_https_POST_test() -> do_POST(ssl, 2048, 1).
 
-single_100k_http_POST_test_() -> % note the underscore
+single_100k_http_POST_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(plain, 102400, 1)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(plain, 102400, 1)))
+     end}.
 
-single_100k_https_POST_test_() -> % note the underscore
+single_100k_https_POST_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(ssl, 102400, 1)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(ssl, 102400, 1)))
+     end}.
 
 multiple_100k_http_POST_test() ->
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(plain, 102400, 3)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(plain, 102400, 3)))
+     end}.
 
 multiple_100K_https_POST_test() ->
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(ssl, 102400, 3)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(ssl, 102400, 3)))
+     end}.
 
-hundred_128_http_POST_test_() -> % note the underscore
+hundred_128_http_POST_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(plain, 128, 100)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(plain, 128, 100)))
+     end}.
 
-hundred_128_https_POST_test_() -> % note the underscore
+hundred_128_https_POST_test_() ->
+    % note the underscore
     {timeout, ?LARGE_TIMEOUT,
-     fun() -> ?assertEqual(ok, do_POST(ssl, 128, 100)) end}.
+     fun () -> ?assertEqual(ok, (do_POST(ssl, 128, 100)))
+     end}.
 
 single_GET_scheme_test_() ->
-    [{"ssl", ?_assertEqual(ok, do_GET("derp", ssl, 1))},
-     {"plain", ?_assertEqual(ok, do_GET("derp", plain, 1))}].
+    [{"ssl", ?_assertEqual(ok, (do_GET("derp", ssl, 1)))},
+     {"plain",
+      ?_assertEqual(ok, (do_GET("derp", plain, 1)))}].
 
 single_GET_absoluteURI_test_() ->
     Uri = "https://example.com:123/x/",
     ServerFun = fun (Req) ->
-                        mochiweb_request:ok({"text/plain", mochiweb_request:get(path, Req)}, Req)
-                end,
+			mochiweb_request:ok({"text/plain",
+					     mochiweb_request:get(path, Req)},
+					    Req)
+		end,
     %% Note that all the scheme/host/port information is discarded from path
-    ClientFun = new_client_fun('GET', [#treq{path = Uri, xreply = <<"/x/">>}]),
+    ClientFun = new_client_fun('GET',
+			       [#treq{path = Uri, xreply = <<"/x/">>}]),
     [{atom_to_list(Transport),
-      ?_assertEqual(ok, with_server(Transport, ServerFun, ClientFun))}
+      ?_assertEqual(ok,
+		    (with_server(Transport, ServerFun, ClientFun)))}
      || Transport <- [ssl, plain]].
 
 single_CONNECT_test_() ->
-    [{"ssl", ?_assertEqual(ok, do_CONNECT(ssl, 1))},
-     {"plain", ?_assertEqual(ok, do_CONNECT(plain, 1))}].
+    [{"ssl", ?_assertEqual(ok, (do_CONNECT(ssl, 1)))},
+     {"plain", ?_assertEqual(ok, (do_CONNECT(plain, 1)))}].
 
 single_GET_any_test_() ->
     ServerFun = fun (Req) ->
-                        mochiweb_request:ok({"text/plain", mochiweb_request:get(path, Req)}, Req)
-                end,
-    ClientFun = new_client_fun('GET', [#treq{path = "*", xreply = <<"*">>}]),
+			mochiweb_request:ok({"text/plain",
+					     mochiweb_request:get(path, Req)},
+					    Req)
+		end,
+    ClientFun = new_client_fun('GET',
+			       [#treq{path = "*", xreply = <<"*">>}]),
     [{atom_to_list(Transport),
-      ?_assertEqual(ok, with_server(Transport, ServerFun, ClientFun))}
+      ?_assertEqual(ok,
+		    (with_server(Transport, ServerFun, ClientFun)))}
      || Transport <- [ssl, plain]].
 
-
 cookie_header_test() ->
     ReplyPrefix = "You requested: ",
     ExHeaders = [{"Set-Cookie", "foo=bar"},
-                 {"Set-Cookie", "foo=baz"}],
+		 {"Set-Cookie", "foo=baz"}],
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
-                        mochiweb_request:ok({"text/plain", ExHeaders, Reply}, Req)
-                end,
+			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+			mochiweb_request:ok({"text/plain", ExHeaders, Reply},
+					    Req)
+		end,
     Path = "cookie_header",
     ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
-    TestReqs = [#treq{path=Path, xreply=ExpectedReply, xheaders=ExHeaders}],
+    TestReqs = [#treq{path = Path, xreply = ExpectedReply,
+		      xheaders = ExHeaders}],
     ClientFun = new_client_fun('GET', TestReqs),
     ok = with_server(plain, ServerFun, ClientFun),
     ok.
 
-
 do_CONNECT(Transport, Times) ->
     PathPrefix = "example.com:",
     ReplyPrefix = "You requested: ",
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
-                        mochiweb_request:ok({"text/plain", Reply}, Req)
-                end,
+			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+			mochiweb_request:ok({"text/plain", Reply}, Req)
+		end,
     TestReqs = [begin
-                    Path = PathPrefix ++ integer_to_list(N),
-                    ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
-                    #treq{path=Path, xreply=ExpectedReply}
-                end || N <- lists:seq(1, Times)],
+		  Path = PathPrefix ++ integer_to_list(N),
+		  ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
+		  #treq{path = Path, xreply = ExpectedReply}
+		end
+		|| N <- lists:seq(1, Times)],
     ClientFun = new_client_fun('CONNECT', TestReqs),
     ok = with_server(Transport, ServerFun, ClientFun),
     ok.
@@ -135,86 +154,85 @@ do_GET(Transport, Times) ->
 do_GET(PathPrefix, Transport, Times) ->
     ReplyPrefix = "You requested: ",
     ServerFun = fun (Req) ->
-                        Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
-                        mochiweb_request:ok({"text/plain", Reply}, Req)
-                end,
+			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
+			mochiweb_request:ok({"text/plain", Reply}, Req)
+		end,
     TestReqs = [begin
-                    Path = PathPrefix ++ integer_to_list(N),
-                    ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
-                    #treq{path=Path, xreply=ExpectedReply}
-                end || N <- lists:seq(1, Times)],
+		  Path = PathPrefix ++ integer_to_list(N),
+		  ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
+		  #treq{path = Path, xreply = ExpectedReply}
+		end
+		|| N <- lists:seq(1, Times)],
     ClientFun = new_client_fun('GET', TestReqs),
     ok = with_server(Transport, ServerFun, ClientFun),
     ok.
 
 do_POST(Transport, Size, Times) ->
     ServerFun = fun (Req) ->
-                        Body = mochiweb_request:recv_body(Req),
-                        Headers = [{"Content-Type", "application/octet-stream"}],
-                        mochiweb_request:respond({201, Headers, Body}, Req)
-                end,
+			Body = mochiweb_request:recv_body(Req),
+			Headers = [{"Content-Type",
+				    "application/octet-stream"}],
+			mochiweb_request:respond({201, Headers, Body}, Req)
+		end,
     TestReqs = [begin
-                    Path = "/stuff/" ++ integer_to_list(N),
-                    Body = crypto:strong_rand_bytes(Size),
-                    #treq{path=Path, body=Body, xreply=Body}
-                end || N <- lists:seq(1, Times)],
+		  Path = "/stuff/" ++ integer_to_list(N),
+		  Body = crypto:strong_rand_bytes(Size),
+		  #treq{path = Path, body = Body, xreply = Body}
+		end
+		|| N <- lists:seq(1, Times)],
     ClientFun = new_client_fun('POST', TestReqs),
     ok = with_server(Transport, ServerFun, ClientFun),
     ok.
 
 new_client_fun(Method, TestReqs) ->
     fun (Transport, Port) ->
-            mochiweb_test_util:client_request(Transport, Port, Method, TestReqs)
+	    mochiweb_test_util:client_request(Transport, Port,
+					      Method, TestReqs)
     end.
 
 close_on_unread_data_test() ->
-    ok = with_server(
-           plain,
-           fun mochiweb_request:not_found/1,
-           fun close_on_unread_data_client/2).
+    ok = with_server(plain,
+		     fun mochiweb_request:not_found/1,
+		     fun close_on_unread_data_client/2).
 
 close_on_unread_data_client(Transport, Port) ->
     SockFun = mochiweb_test_util:sock_fun(Transport, Port),
     %% A normal GET request should not trigger this behavior
-    Request0 = string:join(
-                 ["GET / HTTP/1.1",
-                  "Host: localhost",
-                  "",
-                  ""],
-                 "\r\n"),
+    Request0 = string:join(["GET / HTTP/1.1",
+			    "Host: localhost", "", ""],
+			   "\r\n"),
     ok = SockFun({setopts, [{packet, http}]}),
     ok = SockFun({send, Request0}),
-    ?assertMatch(
-       {ok, {http_response, {1, 1}, 404, _}},
-       SockFun(recv)),
-    Headers0 = mochiweb_test_util:read_server_headers(SockFun),
-    ?assertEqual(
-       undefined,
-       mochiweb_headers:get_value("Connection", Headers0)),
-    Len0 = list_to_integer(
-             mochiweb_headers:get_value("Content-Length", Headers0)),
-    _Body0 = mochiweb_test_util:drain_reply(SockFun, Len0, <<>>),
+    ?assertMatch({ok, {http_response, {1, 1}, 404, _}},
+		 (SockFun(recv))),
+    Headers0 =
+	mochiweb_test_util:read_server_headers(SockFun),
+    ?assertEqual(undefined,
+		 (mochiweb_headers:get_value("Connection", Headers0))),
+    Len0 =
+	list_to_integer(mochiweb_headers:get_value("Content-Length",
+						   Headers0)),
+    _Body0 = mochiweb_test_util:drain_reply(SockFun, Len0,
+					    <<>>),
     %% Re-use same socket
-    Request = string:join(
-                ["POST / HTTP/1.1",
-                 "Host: localhost",
-                 "Content-Type: application/json",
-                 "Content-Length: 2",
-                 "",
-                 "{}"],
-                "\r\n"),
+    Request = string:join(["POST / HTTP/1.1",
+			   "Host: localhost", "Content-Type: application/json",
+			   "Content-Length: 2", "", "{}"],
+			  "\r\n"),
     ok = SockFun({setopts, [{packet, http}]}),
     ok = SockFun({send, Request}),
-    ?assertMatch(
-       {ok, {http_response, {1, 1}, 404, _}},
-       SockFun(recv)),
-    Headers = mochiweb_test_util:read_server_headers(SockFun),
+    ?assertMatch({ok, {http_response, {1, 1}, 404, _}},
+		 (SockFun(recv))),
+    Headers =
+	mochiweb_test_util:read_server_headers(SockFun),
     %% Expect to see a Connection: close header when we know the
     %% server will close the connection re #146
-    ?assertEqual(
-       "close",
-       mochiweb_headers:get_value("Connection", Headers)),
-    Len = list_to_integer(mochiweb_headers:get_value("Content-Length", Headers)),
-    _Body = mochiweb_test_util:drain_reply(SockFun, Len, <<>>),
-    ?assertEqual({error, closed}, SockFun(recv)),
+    ?assertEqual("close",
+		 (mochiweb_headers:get_value("Connection", Headers))),
+    Len =
+	list_to_integer(mochiweb_headers:get_value("Content-Length",
+						   Headers)),
+    _Body = mochiweb_test_util:drain_reply(SockFun, Len,
+					   <<>>),
+    ?assertEqual({error, closed}, (SockFun(recv))),
     ok.
diff --git a/test/mochiweb_websocket_tests.erl b/test/mochiweb_websocket_tests.erl
index 0af29b7..5fd6273 100644
--- a/test/mochiweb_websocket_tests.erl
+++ b/test/mochiweb_websocket_tests.erl
@@ -1,4 +1,5 @@
 -module(mochiweb_websocket_tests).
+
 -author('lukasz.lalik@zadane.pl').
 
 %% The MIT License (MIT)
@@ -27,76 +28,81 @@
 
 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),
+    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("Upgrade",
+		 (proplists:get_value("Connection", Headers1))),
     ?assertEqual(<<"BIFTHkJk4r5t8kuud82tZJaQsCE=">>,
-                 proplists:get_value("Sec-Websocket-Accept", Headers1)),
-
+		 (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"),
+	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("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).
+		 (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() ->
-    ?assertEqual(
-       [{1, <<"foo">>}],
-       mochiweb_websocket:parse_hybi_frames(
-         nil, <<129,131,118,21,153,58,16,122,246>>, [])),
-    ?assertEqual(
-       [{1, <<"foo">>}, {1, <<"bar">>}],
-       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">>}],
+		 (mochiweb_websocket:parse_hybi_frames(nil,
+						       <<129, 131, 118, 21, 153,
+							 58, 16, 122, 246>>,
+						       []))),
+    ?assertEqual([{1, <<"foo">>}, {1, <<"bar">>}],
+		 (mochiweb_websocket:parse_hybi_frames(nil,
+						       <<129, 131, 1, 225, 201,
+							 42, 103, 142, 166, 129,
+							 131, 93, 222, 214, 66,
+							 63, 191, 164>>,
+						       []))).
 
 hixie_frames_decode_test() ->
-    ?assertEqual(
-       [],
-       mochiweb_websocket:parse_hixie_frames(<<>>, [])),
-    ?assertEqual(
-       [<<"foo">>],
-       mochiweb_websocket:parse_hixie_frames(<<0,102,111,111,255>>, [])),
-    ?assertEqual(
-       [<<"foo">>, <<"bar">>],
-       mochiweb_websocket:parse_hixie_frames(
-         <<0,102,111,111,255,0,98,97,114,255>>,
-         [])).
+    ?assertEqual([],
+		 (mochiweb_websocket:parse_hixie_frames(<<>>, []))),
+    ?assertEqual([<<"foo">>],
+		 (mochiweb_websocket:parse_hixie_frames(<<0, 102, 111,
+							  111, 255>>,
+							[]))),
+    ?assertEqual([<<"foo">>, <<"bar">>],
+		 (mochiweb_websocket:parse_hixie_frames(<<0, 102, 111,
+							  111, 255, 0, 98, 97,
+							  114, 255>>,
+							[]))).
 
 end_to_end_test_factory(ServerTransport) ->
-    mochiweb_test_util:with_server(
-      ServerTransport,
-      fun end_to_end_server/1,
-      fun (Transport, Port) ->
-              end_to_end_client(mochiweb_test_util:sock_fun(Transport, Port))
-      end).
+    mochiweb_test_util:with_server(ServerTransport,
+				   fun end_to_end_server/1,
+				   fun (Transport, Port) ->
+					   end_to_end_client(mochiweb_test_util:sock_fun(Transport,
+											 Port))
+				   end).
 
 end_to_end_server(Req) ->
-    ?assertEqual("Upgrade", mochiweb_request:get_header_value("connection", Req)),
-    ?assertEqual("websocket", mochiweb_request:get_header_value("upgrade", Req)),
-    {ReentryWs, _ReplyChannel} = mochiweb_websocket:upgrade_connection(
-                                   Req,
-                                   fun end_to_end_ws_loop/3),
+    ?assertEqual("Upgrade",
+		 (mochiweb_request:get_header_value("connection", Req))),
+    ?assertEqual("websocket",
+		 (mochiweb_request:get_header_value("upgrade", Req))),
+    {ReentryWs, _ReplyChannel} =
+	mochiweb_websocket:upgrade_connection(Req,
+					      fun end_to_end_ws_loop/3),
     ReentryWs(ok).
 
 end_to_end_ws_loop(Payload, State, ReplyChannel) ->
@@ -106,55 +112,52 @@ end_to_end_ws_loop(Payload, State, ReplyChannel) ->
 
 end_to_end_client(S) ->
     %% Key and Accept per https://tools.ietf.org/html/rfc6455
-    UpgradeReq = string:join(
-                   ["GET / HTTP/1.1",
-                    "Host: localhost",
-                    "Upgrade: websocket",
-                    "Connection: Upgrade",
-                    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
-                    "",
-                    ""], "\r\n"),
+    UpgradeReq = string:join(["GET / HTTP/1.1",
+			      "Host: localhost", "Upgrade: websocket",
+			      "Connection: Upgrade",
+			      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==", "",
+			      ""],
+			     "\r\n"),
     ok = S({send, UpgradeReq}),
-    {ok, {http_response, {1,1}, 101, _}} = S(recv),
-    read_expected_headers(
-      S,
-      [{'Upgrade', "websocket"},
-       {'Connection', "Upgrade"},
-       {'Content-Length', "0"},
-       {"Sec-Websocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}]),
+    {ok, {http_response, {1, 1}, 101, _}} = S(recv),
+    read_expected_headers(S,
+			  [{'Upgrade', "websocket"}, {'Connection', "Upgrade"},
+			   {'Content-Length', "0"},
+			   {"Sec-Websocket-Accept",
+			    "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}]),
     %% The first message sent over telegraph :)
     SmallMessage = <<"What hath God wrought?">>,
     ok = S({send,
-       << 1:1, %% Fin
-          0:1, %% Rsv1
-          0:1, %% Rsv2
-          0:1, %% Rsv3
-          2:4, %% Opcode, 1 = text frame
-          1:1, %% Mask on
-          (byte_size(SmallMessage)):7, %% Length, <125 case
-          0:32, %% Mask (trivial)
-          SmallMessage/binary >>}),
+	    <<1:1, %% Fin
+	      0:1, %% Rsv1
+	      0:1, %% Rsv2
+	      0:1, %% Rsv3
+	      2:4, %% Opcode, 1 = text frame
+	      1:1, %% Mask on
+	      (byte_size(SmallMessage)):7, %% Length, <125 case
+	      0:32, %% Mask (trivial)
+	      SmallMessage/binary>>}),
     {ok, WsFrames} = S(recv),
-    << 1:1, %% Fin
-       0:1, %% Rsv1
-       0:1, %% Rsv2
-       0:1, %% Rsv3
-       1:4, %% Opcode, text frame (all mochiweb suports for now)
-       MsgSize:8, %% Expecting small size
-       SmallMessage/binary >> = WsFrames,
-    ?assertEqual(MsgSize, byte_size(SmallMessage)),
+    <<1:1, %% Fin
+      0:1, %% Rsv1
+      0:1, %% Rsv2
+      0:1, %% Rsv3
+      1:4, %% Opcode, text frame (all mochiweb suports for now)
+      MsgSize:8, %% Expecting small size
+      SmallMessage/binary>> =
+	WsFrames,
+    ?assertEqual(MsgSize, (byte_size(SmallMessage))),
     ok.
 
 read_expected_headers(S, D) ->
     Headers = mochiweb_test_util:read_server_headers(S),
-    lists:foreach(
-      fun ({K, V}) ->
-              ?assertEqual(V, mochiweb_headers:get_value(K, Headers))
-      end,
-      D).
+    lists:foreach(fun ({K, V}) ->
+			  ?assertEqual(V,
+				       (mochiweb_headers:get_value(K, Headers)))
+		  end,
+		  D).
 
 end_to_end_http_test() ->
     end_to_end_test_factory(plain).
 
-end_to_end_https_test() ->
-    end_to_end_test_factory(ssl).
+end_to_end_https_test() -> end_to_end_test_factory(ssl).


[couchdb-mochiweb] 10/37: Note this PR. Still have to wait a day for Travis-CI to have this build available

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 790f1359dc06d5a8c69b1977f9dcd970490a3a6b
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Wed Jan 16 09:50:30 2019 -0800

    Note this PR. Still have to wait a day for Travis-CI to have this build available
---
 CHANGES.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGES.md b/CHANGES.md
index b5d77be..91891ac 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,8 @@
-Version 2.19.0 released 2019-XX-XX
+Version 2.19.0 released 2019-01-XX
 
+* Fix warning in 21.2.3 and crash on incompatible releases
+  (21.2, 21.2.1, 21.2.2 have a SSL bug)
+  https://github.com/mochi/mochiweb/pull/210
 * Erlang/OTP 21 compatibility
   https://github.com/mochi/mochiweb/pull/198
   https://github.com/mochi/mochiweb/pull/204


[couchdb-mochiweb] 15/37: Remove compile(tuple_calls) from mochifmt

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 9f82853b1eb8d8cfc30098f00559063382c1ff79
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:28:47 2019 +0000

    Remove compile(tuple_calls) from mochifmt
---
 src/mochifmt.erl | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/mochifmt.erl b/src/mochifmt.erl
index 5a5ed45..1aa01c3 100644
--- a/src/mochifmt.erl
+++ b/src/mochifmt.erl
@@ -25,8 +25,6 @@
 -module(mochifmt).
 -author('bob@mochimedia.com').
 
--compile(tuple_calls).
-
 -export([format/2, format_field/2, convert_field/2, get_value/2, get_field/2]).
 -export([tokenize/1, format/3, get_field/3, format_field/3]).
 -export([bformat/2, bformat/3]).
@@ -76,8 +74,7 @@ get_field(Key, Args) ->
 %%      is used to implement formats such as {0.0}.
 get_field(Key, Args, Module) ->
     {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end, Key),
-    Res = try Module:get_value(Name, Args)
-          catch error:undef -> get_value(Name, Args) end,
+    Res = mod_get_value(Name, Args, Module),
     case Next of
         "" ->
             Res;
@@ -85,6 +82,16 @@ get_field(Key, Args, Module) ->
             get_field(S1, Res, Module)
     end.
 
+mod_get_value(Name, Args, Module) ->
+    try tuple_apply(Module, get_value, [Name, Args])
+    catch error:undef -> get_value(Name, Args)
+    end.
+
+tuple_apply(Module, F, Args) when is_atom(Module) ->
+    erlang:apply(Module, F, Args);
+tuple_apply(Module, F, Args) when is_tuple(Module), is_atom(element(1, Module)) ->
+    erlang:apply(element(1, Module), F, Args ++ [Module]).
+
 %% @spec format(Format::string(), Args) -> iolist()
 %% @doc Format Args with Format.
 format(Format, Args) ->
@@ -204,11 +211,11 @@ format2([{format, {Key, Convert, Format0}} | Rest], Args, Module, Acc) ->
                 V1 = convert_field(V0, Convert),
                 format_field(V1, Format);
             _ ->
-                V0 = try Module:get_field(Key, Args)
+                V0 = try tuple_apply(Module, get_field, [Key, Args])
                      catch error:undef -> get_field(Key, Args, Module) end,
-                V1 = try Module:convert_field(V0, Convert)
+                V1 = try tuple_apply(Module, convert_field, [V0, Convert])
                      catch error:undef -> convert_field(V0, Convert) end,
-                try Module:format_field(V1, Format)
+                try tuple_apply(Module, format_field, [V1, Format])
                 catch error:undef -> format_field(V1, Format, Module) end
         end,
     format2(Rest, Args, Module, [V | Acc]).
@@ -436,9 +443,9 @@ std_test() ->
 records_test() ->
     M = mochifmt_records:new([{conversion, record_info(fields, conversion)}]),
     R = #conversion{length=long, precision=hard, sign=peace},
-    long = M:get_value("length", R),
-    hard = M:get_value("precision", R),
-    peace = M:get_value("sign", R),
+    long = mochifmt_records:get_value("length", R, M),
+    hard = mochifmt_records:get_value("precision", R, M),
+    peace = mochifmt_records:get_value("sign", R, M),
     <<"long hard">> = bformat("{length} {precision}", R, M),
     <<"long hard">> = bformat("{0.length} {0.precision}", [R], M),
     ok.


[couchdb-mochiweb] 34/37: Use a matrix to get an older dist for old releases

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 1006be705fbd2520b5f68d230a8ca80b17dd0b63
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue May 21 20:31:18 2019 -0700

    Use a matrix to get an older dist for old releases
---
 .travis.yml | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index eb26c04..ecc72df 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,9 +8,13 @@ otp_release:
   - 21.0
   - 20.0
   - 19.0
-  - 18.3
-  - 17.5
-  - R16B03-1
-  - R15B03
-before_script:
-  - kerl list installations
+matrix:
+  include:
+  - otp_release: 18.3
+    dist: trusty
+  - otp_release: 17.5
+    dist: trusty
+  - otp_release: R16B03-1
+    dist: trusty
+  - otp_release: R15B03
+    dist: trusty


[couchdb-mochiweb] 11/37: Update CHANGES.md with release date

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 5d4686c2bdb2d206b0a3beaac2eb356cc3b75615
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Thu Jan 17 17:56:51 2019 +0000

    Update CHANGES.md with release date
---
 CHANGES.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGES.md b/CHANGES.md
index 91891ac..e3ac5c3 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,4 +1,4 @@
-Version 2.19.0 released 2019-01-XX
+Version 2.19.0 released 2019-01-17
 
 * Fix warning in 21.2.3 and crash on incompatible releases
   (21.2, 21.2.1, 21.2.2 have a SSL bug)


[couchdb-mochiweb] 13/37: fix cookie value parsing

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 4bee8b66624c7c97590175debd632bc33dad49e7
Author: Oleg Nemanov <le...@yandex.ru>
AuthorDate: Mon Mar 4 15:24:50 2019 +0300

    fix cookie value parsing
    
    Cookie value(according to RFC6265) can contain US-ASCII characters
    excluding CTLs, whitespace, DQUOTE, comma, semicolon and backslash:
    
    cookie-header = "Cookie:" OWS cookie-string OWS
    cookie-string = cookie-pair *( ";" SP cookie-pair )
    cookie-pair       = cookie-name "=" cookie-value
    cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
    cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
    
    But mochiweb_cookie:parse_cookie() use smaller allowed characters list.
    For example, if cookie value is base64 string like MQ==,
    then parse_cookie() makes it MQ.
    
    Fix this by using a separate function for value parsing instead of
    read_token().
---
 src/mochiweb_cookies.erl | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/mochiweb_cookies.erl b/src/mochiweb_cookies.erl
index 013dbe0..b6afb65 100644
--- a/src/mochiweb_cookies.erl
+++ b/src/mochiweb_cookies.erl
@@ -39,6 +39,14 @@
          C =:= $[ orelse C =:= $] orelse C =:= $? orelse C =:= $= orelse
          C =:= ${ orelse C =:= $})).
 
+%% RFC 6265 cookie value allowed characters
+-define(IS_COOKIE_VAL_ALLOWED(C),
+        (C =:= 33
+         orelse (C >= 35 andalso C =< 43)
+         orelse (C >= 45 andalso C =< 58)
+         orelse (C >= 60 andalso C =< 91)
+         orelse (C >= 93 andalso C =< 126))).
+
 %% @type proplist() = [{Key::string(), Value::string()}].
 %% @type header() = {Name::string(), Value::string()}.
 %% @type int_seconds() = integer().
@@ -208,11 +216,15 @@ read_value([$= | Value]) ->
         [?QUOTE | _] ->
             read_quoted(Value1);
         _ ->
-            read_token(Value1)
+            read_value_(Value1)
     end;
 read_value(String) ->
     {"", String}.
 
+read_value_(String) ->
+    F = fun (C) -> ?IS_COOKIE_VAL_ALLOWED(C) end,
+    lists:splitwith(F, String).
+
 read_quoted([?QUOTE | String]) ->
     read_quoted(String, []).
 
@@ -302,6 +314,12 @@ parse_cookie_test() ->
     ?assertEqual(
        [{"foo", "bar"}, {"baz", "wibble"}],
        parse_cookie("foo=bar , baz=wibble ")),
+    ?assertEqual(
+       [{"foo", "base64=="}, {"bar", "base64="}],
+       parse_cookie("foo=\"base64==\";bar=\"base64=\"")),
+    ?assertEqual(
+       [{"foo", "base64=="}, {"bar", "base64="}],
+       parse_cookie("foo=base64==;bar=base64=")),
     ok.
 
 domain_test() ->


[couchdb-mochiweb] 21/37: Remove compile(tuple_calls) from mochiweb_websocket

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 0e0d1de25050939101823a6fd2e2805a1c6910a0
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 21:00:29 2019 +0000

    Remove compile(tuple_calls) from mochiweb_websocket
---
 src/mochiweb_websocket.erl | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/src/mochiweb_websocket.erl b/src/mochiweb_websocket.erl
index 690c91f..c162980 100644
--- a/src/mochiweb_websocket.erl
+++ b/src/mochiweb_websocket.erl
@@ -25,8 +25,6 @@
 
 %% @doc Websockets module for Mochiweb. Based on Misultin websockets module.
 
--compile(tuple_calls).
-
 -export([loop/5, upgrade_connection/2, request/5]).
 -export([send/3]).
 -ifdef(TEST).
@@ -79,11 +77,11 @@ send(Socket, Payload, hybi) ->
 send(Socket, Payload, hixie) ->
     mochiweb_socket:send(Socket, [0, Payload, 255]).
 
-upgrade_connection(Req, Body) ->
+upgrade_connection({ReqM, _} = Req, Body) ->
     case make_handshake(Req) of
         {Version, Response} ->
-            Req:respond(Response),
-            Socket = Req:get(socket),
+            ReqM:respond(Response, Req),
+            Socket = ReqM:get(socket, Req),
             ReplyChannel = fun (Payload) ->
                 ?MODULE:send(Socket, Payload, Version)
             end,
@@ -92,21 +90,21 @@ upgrade_connection(Req, Body) ->
             end,
             {Reentry, ReplyChannel};
         _ ->
-            mochiweb_socket:close(Req:get(socket)),
+            mochiweb_socket:close(ReqM:get(socket, Req)),
             exit(normal)
     end.
 
-make_handshake(Req) ->
-    SecKey  = Req:get_header_value("sec-websocket-key"),
-    Sec1Key = Req:get_header_value("Sec-WebSocket-Key1"),
-    Sec2Key = Req:get_header_value("Sec-WebSocket-Key2"),
-    Origin = Req:get_header_value(origin),
+make_handshake({ReqM, _} = Req) ->
+    SecKey  = ReqM:get_header_value("sec-websocket-key", Req),
+    Sec1Key = ReqM:get_header_value("Sec-WebSocket-Key1", Req),
+    Sec2Key = ReqM:get_header_value("Sec-WebSocket-Key2", Req),
+    Origin = ReqM:get_header_value(origin, Req),
     if SecKey =/= undefined ->
             hybi_handshake(SecKey);
        Sec1Key =/= undefined andalso Sec2Key =/= undefined ->
-            Host = Req:get_header_value("Host"),
-            Path = Req:get(path),
-            Body = Req:recv(8),
+            Host = ReqM:get_header_value("Host", Req),
+            Path = ReqM:get(path, Req),
+            Body = ReqM:recv(8, Req),
             Scheme = scheme(Req),
             hixie_handshake(Scheme, Host, Path, Sec1Key, Sec2Key, Body, Origin);
        true ->


[couchdb-mochiweb] 29/37: Remove compile(tuple_calls) from test/mochiweb_request_tests

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 63d44f044cb11c2c620590ae120fbd403e15a00d
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Mar 12 01:41:45 2019 +0000

    Remove compile(tuple_calls) from test/mochiweb_request_tests
---
 test/mochiweb_request_tests.erl | 70 ++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 36 deletions(-)

diff --git a/test/mochiweb_request_tests.erl b/test/mochiweb_request_tests.erl
index b8f93e2..47fe7ee 100644
--- a/test/mochiweb_request_tests.erl
+++ b/test/mochiweb_request_tests.erl
@@ -1,162 +1,160 @@
 -module(mochiweb_request_tests).
 
--compile(tuple_calls).
-
 -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">>)),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req1)),
+    ?assertEqual(true, mochiweb_request:accepts_content_type(<<"multipart/related">>, Req1)),
 
     Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
         mochiweb_headers:make([{"Accept", "text/html"}])),
-    ?assertEqual(false, Req2:accepts_content_type("multipart/related")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req2)),
 
     Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
         mochiweb_headers:make([{"Accept", "text/html, multipart/*"}])),
-    ?assertEqual(true, Req3:accepts_content_type("multipart/related")),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req3)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req4)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req5)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req6)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("multipart/related", Req7)),
 
     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")),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req8)),
 
     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")),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("multipart/related", Req9)),
 
     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")),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html;level=1", Req10)),
 
     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")),
+    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html", Req11)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("text/html;level=1", Req12)),
 
     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")),
+    ?assertEqual(false, mochiweb_request:accepts_content_type("text/html; level=1", Req13)),
 
     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")).
+    ?assertEqual(true, mochiweb_request:accepts_content_type("text/html; level=1", Req14)).
 
 accepted_encodings_test() ->
     Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
                                 mochiweb_headers:make([])),
     ?assertEqual(["identity"],
-                 Req1:accepted_encodings(["gzip", "identity"])),
+                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req1)),
 
     Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
         mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])),
     ?assertEqual(["gzip", "identity"],
-                 Req2:accepted_encodings(["gzip", "identity"])),
+                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req2)),
 
     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"])),
+                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req3)),
 
     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"])),
+                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req4)),
 
     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"])),
+                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req5)),
 
     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"])),
+                 mochiweb_request:accepted_encodings(["gzip", "deflate", "identity"], Req6)),
 
     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"])),
+                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req7)),
 
     Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
         mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])),
     ?assertEqual([],
-                 Req8:accepted_encodings(["gzip", "identity"])).
+                 mochiweb_request:accepted_encodings(["gzip", "identity"], Req8)).
 
 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"])),
+        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req1)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req2)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req3)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req4)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req5)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req6)),
 
     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"])),
+        mochiweb_request:accepted_content_types(["application/json", "text/html"], Req7)),
 
     Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1},
         mochiweb_headers:make([{"Accept", "text/html"}])),
     ?assertEqual([],
-        Req8:accepted_content_types(["application/json"])),
+        mochiweb_request:accepted_content_types(["application/json"], Req8)),
 
     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"])).
+        mochiweb_request:accepted_content_types(["text/html", "application/json"], Req9)).
 
 should_close_test() ->
     F = fun (V, H) ->
-                (mochiweb_request:new(
+                mochiweb_request:should_close(mochiweb_request:new(
                    nil, 'GET', "/", V,
                    mochiweb_headers:make(H)
-                  )):should_close()
+                  ))
         end,
     ?assertEqual(
        true,


[couchdb-mochiweb] 16/37: Remove compile(tuple_calls) from mochiweb_acceptor

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 9465b8a553322c5e494bd59ec5385bb88f5704cf
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Sat Mar 9 20:38:37 2019 +0000

    Remove compile(tuple_calls) from mochiweb_acceptor
---
 src/mochiweb_acceptor.erl | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/mochiweb_acceptor.erl b/src/mochiweb_acceptor.erl
index 3fd6925..1b53552 100644
--- a/src/mochiweb_acceptor.erl
+++ b/src/mochiweb_acceptor.erl
@@ -24,8 +24,6 @@
 -module(mochiweb_acceptor).
 -author('bob@mochimedia.com').
 
--compile(tuple_calls).
-
 -include("internal.hrl").
 
 -export([start_link/3, start_link/4, init/4]).
@@ -75,11 +73,11 @@ init(Server, Listen, Loop, Opts) ->
             exit({error, accept_failed})
     end.
 
-call_loop({M, F}, Socket, Opts) ->
+call_loop({M, F}, Socket, Opts) when is_atom(M) ->
     M:F(Socket, Opts);
-call_loop({M, F, [A1]}, Socket, Opts) ->
+call_loop({M, F, [A1]}, Socket, Opts) when is_atom(M) ->
     M:F(Socket, Opts, A1);
-call_loop({M, F, A}, Socket, Opts) ->
+call_loop({M, F, A}, Socket, Opts) when is_atom(M) ->
     erlang:apply(M, F, [Socket, Opts | A]);
 call_loop(Loop, Socket, Opts) ->
     Loop(Socket, Opts).


[couchdb-mochiweb] 08/37: Update vsn and CHANGES in prep for a release (waiting for an OTP maint release that fixes SSL)

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 1991194df4a2aa95b53627877d448fe9fc70d8ff
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Jan 15 15:18:11 2019 -0800

    Update vsn and CHANGES in prep for a release (waiting for an OTP maint release that fixes SSL)
---
 CHANGES.md           | 13 +++++++++++++
 src/mochiweb.app.src |  2 +-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/CHANGES.md b/CHANGES.md
index 7fd273e..b5d77be 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,16 @@
+Version 2.19.0 released 2019-XX-XX
+
+* Erlang/OTP 21 compatibility
+  https://github.com/mochi/mochiweb/pull/198
+  https://github.com/mochi/mochiweb/pull/204
+* New `{buffer, Buffer}` socket server option
+  https://github.com/mochi/mochiweb/pull/208
+* New `{format, map}` option for mochijson2:decode/2
+  https://github.com/mochi/mochiweb/pull/206
+* No longer crash when a socket is closed server-side
+  https://github.com/mochi/mochiweb/pull/205
+* Support for SameSite cookie setting
+
 Version 2.18.0 released 2018-05-12
 
 * Add the 100.64.0.0/10 private IP shared address range
diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src
index 60f15f5..70c7165 100644
--- a/src/mochiweb.app.src
+++ b/src/mochiweb.app.src
@@ -1,7 +1,7 @@
 %% This is generated from src/mochiweb.app.src
 {application, mochiweb,
  [{description, "MochiMedia Web Server"},
-  {vsn, "2.18.0"},
+  {vsn, "2.19.0"},
   {modules, []},
   {registered, []},
   {env, []},


[couchdb-mochiweb] 26/37: Remove compile(tuple_calls) from test/mochiweb_http_tests

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 344dd9305dfa8e1e2c19f85d462b919c9088abb2
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Tue Mar 12 01:26:08 2019 +0000

    Remove compile(tuple_calls) from test/mochiweb_http_tests
---
 examples/hmac_api/README     |  2 +-
 test/mochiweb_http_tests.erl | 12 +++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/examples/hmac_api/README b/examples/hmac_api/README
index 3771323..d69821a 100644
--- a/examples/hmac_api/README
+++ b/examples/hmac_api/README
@@ -159,7 +159,7 @@ authorize/request/1 should be called in the loop of project_name_web.erl as per:
     loop(Req, DocRoot) ->
         Auth = hmac_api_lib:authorize_request(Req),
         io:format("Auth is ~p~n", [Auth]),
-        "/" ++ Path = Req:get(path),
+        "/" ++ Path = mochiweb_request:get(path, Req),
         ...
 
 When this is done you are ready to test the api:
diff --git a/test/mochiweb_http_tests.erl b/test/mochiweb_http_tests.erl
index 1057755..8fbf0f3 100644
--- a/test/mochiweb_http_tests.erl
+++ b/test/mochiweb_http_tests.erl
@@ -7,8 +7,6 @@
 -define(SHOULD_HAVE_BUG, false).
 -endif.
 
--compile(tuple_calls).
-
 has_acceptor_bug_test_() ->
     {setup,
      fun start_server/0,
@@ -29,9 +27,13 @@ has_acceptor_bug_tests(Server) ->
       ?_assertEqual(?SHOULD_HAVE_BUG, has_bug(Port, 10000))}].
 
 responder(Req) ->
-    Req:respond({200,
-                 [{"Content-Type", "text/html"}],
-                 ["<html><body>Hello</body></html>"]}).
+    mochiweb_request:respond(
+        {
+            200,
+            [{"Content-Type", "text/html"}],
+            ["<html><body>Hello</body></html>"]
+        },
+        Req).
 
 has_bug(Port, Len) ->
   case


[couchdb-mochiweb] 22/37: Remove compile(tuple_calls) from the template

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit 896999aed431abfe624e86ee88d0d86f01006e2f
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Mon Mar 11 22:45:20 2019 +0000

    Remove compile(tuple_calls) from the template
---
 .../mochiwebapp_skel/src/mochiapp_web.erl          | 47 +++++++++++++++-------
 1 file changed, 33 insertions(+), 14 deletions(-)

diff --git a/support/templates/mochiwebapp_skel/src/mochiapp_web.erl b/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
index 7ffb44d..ecd99c5 100644
--- a/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
+++ b/support/templates/mochiwebapp_skel/src/mochiapp_web.erl
@@ -6,8 +6,6 @@
 -module({{appid}}_web).
 -author("{{author}}").
 
--compile(tuple_calls).
-
 -export([start/1, stop/0, loop/2]).
 
 %% External API
@@ -22,35 +20,56 @@ start(Options) ->
 stop() ->
     mochiweb_http:stop(?MODULE).
 
+
+%% OTP 21 is the first to define OTP_RELEASE and the first to support
+%% EEP-0047 direct stack trace capture.
+-ifdef(OTP_RELEASE).
+-if(?OTP_RELEASE >= 21).
+-define(HAS_DIRECT_STACKTRACE, true).
+-endif.
+-endif.
+
+-ifdef(HAS_DIRECT_STACKTRACE).
+-define(CAPTURE_EXC_PRE(Type, What, Trace), Type:What:Trace).
+-define(CAPTURE_EXC_GET(Trace), Trace).
+-else.
+-define(CAPTURE_EXC_PRE(Type, What, Trace), Type:What).
+-define(CAPTURE_EXC_GET(Trace), erlang:get_stacktrace()).
+-endif.
+
 loop(Req, DocRoot) ->
-    "/" ++ Path = Req:get(path),
+    "/" ++ Path = mochiweb_request:get(path, Req),
     try
-        case Req:get(method) of
+        case mochiweb_request:get(method, Req) of
             Method when Method =:= 'GET'; Method =:= 'HEAD' ->
                 case Path of
-                  "hello_world" ->
-                    Req:respond({200, [{"Content-Type", "text/plain"}],
-                    "Hello world!\n"});
+                    "hello_world" ->
+                        mochiweb_request:respond(
+                            {200, [{"Content-Type", "text/plain"}], "Hello world!\n"},
+                            Req
+                        );
                     _ ->
-                        Req:serve_file(Path, DocRoot)
+                        mochiweb_request:serve_file(Path, DocRoot, Req)
                 end;
             'POST' ->
                 case Path of
                     _ ->
-                        Req:not_found()
+                        mochiweb_request:not_found(Req)
                 end;
             _ ->
-                Req:respond({501, [], []})
+                mochiweb_request:respond({501, [], []}, Req)
         end
     catch
-        Type:What ->
+        ?CAPTURE_EXC_PRE(Type, What, Trace) ->
             Report = ["web request failed",
                       {path, Path},
                       {type, Type}, {what, What},
-                      {trace, erlang:get_stacktrace()}],
+                      {trace, ?CAPTURE_EXC_GET(Trace)}],
             error_logger:error_report(Report),
-            Req:respond({500, [{"Content-Type", "text/plain"}],
-                         "request failed, sorry\n"})
+            mochiweb_request:respond(
+                {500, [{"Content-Type", "text/plain"}], "request failed, sorry\n"},
+                Req
+            )
     end.
 
 %% Internal API


[couchdb-mochiweb] 25/37: Remove compile(tuple_calls) from examples/keepalive

Posted by wi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

willholley pushed a commit to branch upstream
in repository https://gitbox.apache.org/repos/asf/couchdb-mochiweb.git

commit f3a5b37e956dc22bd48112fa4b6761275e46d1fa
Author: Bob Ippolito <bo...@redivi.com>
AuthorDate: Mon Mar 11 22:57:58 2019 +0000

    Remove compile(tuple_calls) from examples/keepalive
---
 examples/keepalive/keepalive.erl | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/examples/keepalive/keepalive.erl b/examples/keepalive/keepalive.erl
index a371e91..51a7c3a 100644
--- a/examples/keepalive/keepalive.erl
+++ b/examples/keepalive/keepalive.erl
@@ -1,7 +1,5 @@
 -module(keepalive).
 
--compile(tuple_calls).
-
 %% your web app can push data to clients using a technique called comet long
 %% polling.  browsers make a request and your server waits to send a
 %% response until data is available.  see wikipedia for a better explanation:
@@ -33,7 +31,7 @@ start(Options = [{port, _Port}]) ->
     mochiweb_http:start([{name, ?MODULE}, {loop, ?LOOP} | Options]).
 
 loop(Req) ->
-    Path = Req:get(path),
+    Path = mochiweb_request:get(path, Req),
     case string:tokens(Path, "/") of
         ["longpoll" | RestOfPath] ->
             %% the "reentry" is a continuation -- what @mochiweb_http@
@@ -74,10 +72,10 @@ resume(Req, RestOfPath, Reentry) ->
     %% if we didn't call @Reentry@ here then the function would finish and the
     %% process would exit.  calling @Reentry@ takes care of returning control
     %% to @mochiweb_http@
-    io:format("reentering loop via continuation in ~p~n", [Req:get(path)]),
+    io:format("reentering loop via continuation in ~p~n", [mochiweb_request:get(path, Req)]),
     Reentry(Req).
 
 ok(Req, Response) ->
-    Req:ok({_ContentType = "text/plain",
-            _Headers = [],
-            Response}).
+    mochiweb_request:ok(
+        {_ContentType = "text/plain", _Headers = [], Response},
+        Req).