You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2016/08/22 11:19:27 UTC

[01/50] ibrowse commit: updated refs/heads/upstream to b28542d

Repository: couchdb-ibrowse
Updated Branches:
  refs/heads/upstream [created] b28542d1e


Changed pipeline algo to smallest pipeline first

Big commit. Switched algorithm to one which will favor
the connection with the smallest pipeline first
(deciding ties by timestamp of last finished request,
and then by pid as ultimate tie breaker).

Note: this also drastically changes the internal
representation of the connection in ets and is dependent
on specific order of operations when changing key values
to limit risk of race conditions between loadbalancer
and a given connection.

Also removed connection reporting of start of request
as this was no longer necessary since the load balancer
tees up the entry into ets with a 1.


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

Branch: refs/heads/upstream
Commit: 9d0b7e3eea12a72ae619e6f34aab349b25893eef
Parents: 3061aa2
Author: benjaminplee <ya...@gmail.com>
Authored: Wed Nov 19 21:50:54 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 16:15:51 2014 +0000

----------------------------------------------------------------------
 src/ibrowse_http_client.erl       | 44 ++++++++-------------
 src/ibrowse_lb.erl                | 71 ++++++++++++++++++++++------------
 test/ibrowse_functional_tests.erl | 11 ++----
 3 files changed, 66 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/9d0b7e3e/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index 1bb95d2..c9161b0 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -762,11 +762,10 @@ send_req_1(From,
                 {ok, _Sent_body} ->
                     trace_request_body(Body_1),
                     _ = active_once(State_1),
-                    State_1_1 = inc_pipeline_counter(State_1),
-                    State_2 = State_1_1#state{status     = get_header,
-                                              cur_req    = NewReq,
-                                              proxy_tunnel_setup = in_progress,
-                                              tunnel_setup_queue = [{From, Url, Headers, Method, Body, Options, Timeout}]},
+                    State_2 = State_1#state{status     = get_header,
+                                            cur_req    = NewReq,
+                                            proxy_tunnel_setup = in_progress,
+                                            tunnel_setup_queue = [{From, Url, Headers, Method, Body, Options, Timeout}]},
                     State_3 = set_inac_timer(State_2),
                     {noreply, State_3};
                 Err ->
@@ -853,15 +852,14 @@ send_req_1(From,
                     Raw_req = list_to_binary([Req, Sent_body]),
                     NewReq_1 = NewReq#request{raw_req = Raw_req},
                     State_1 = State#state{reqs=queue:in(NewReq_1, State#state.reqs)},
-                    State_2 = inc_pipeline_counter(State_1),
-                    _ = active_once(State_2),
-                    State_3 = case Status of
+                    _ = active_once(State_1),
+                    State_2 = case Status of
                                   idle ->
-                                      State_2#state{
+                                      State_1#state{
                                         status     = get_header,
                                         cur_req    = NewReq_1};
                                   _ ->
-                                      State_2
+                                      State_1
                               end,
                     case StreamTo of
                         undefined ->
@@ -875,8 +873,8 @@ send_req_1(From,
                                     catch StreamTo ! {ibrowse_async_raw_req, Raw_req}
                             end
                     end,
-                    State_4 = set_inac_timer(State_3),
-                    {noreply, State_4};
+                    State_3 = set_inac_timer(State_2),
+                    {noreply, State_3};
                 Err ->
                     shutting_down(State),
                     do_trace("Send failed... Reason: ~p~n", [Err]),
@@ -1815,13 +1813,13 @@ format_response_data(Resp_format, Body) ->
 do_reply(State, From, undefined, _, Resp_format, {ok, St_code, Headers, Body}) ->
     Msg_1 = {ok, St_code, Headers, format_response_data(Resp_format, Body)},
     gen_server:reply(From, Msg_1),
-    dec_pipeline_counter(State);
+    report_request_complete(State);
 do_reply(State, From, undefined, _, _, Msg) ->
     gen_server:reply(From, Msg),
-    dec_pipeline_counter(State);
+    report_request_complete(State);
 do_reply(#state{prev_req_id = Prev_req_id} = State,
          _From, StreamTo, ReqId, Resp_format, {ok, _, _, Body}) ->
-    State_1 = dec_pipeline_counter(State),
+    State_1 = report_request_complete(State),
     case Body of
         [] ->
             ok;
@@ -1843,7 +1841,7 @@ do_reply(#state{prev_req_id = Prev_req_id} = State,
     ets:delete(?STREAM_TABLE, {req_id_pid, Prev_req_id}),
     State_1#state{prev_req_id = ReqId};
 do_reply(State, _From, StreamTo, ReqId, Resp_format, Msg) ->
-    State_1 = dec_pipeline_counter(State),
+    State_1 = report_request_complete(State),
     Msg_1 = format_response_data(Resp_format, Msg),
     catch StreamTo ! {ibrowse_async_response, ReqId, Msg_1},
     State_1.
@@ -1946,19 +1944,11 @@ shutting_down(#state{lb_ets_tid = undefined}) ->
 shutting_down(#state{lb_ets_tid = Tid}) ->
     ibrowse_lb:report_connection_down(Tid).
 
-inc_pipeline_counter(#state{is_closing = true} = State) ->
-    State;
-inc_pipeline_counter(#state{lb_ets_tid = undefined} = State) ->
-    State;
-inc_pipeline_counter(#state{lb_ets_tid = Tid} = State) ->
-    ibrowse_lb:report_request_underway(Tid),
-    State.
-
-dec_pipeline_counter(#state{is_closing = true} = State) ->
+report_request_complete(#state{is_closing = true} = State) ->
     State;
-dec_pipeline_counter(#state{lb_ets_tid = undefined} = State) ->
+report_request_complete(#state{lb_ets_tid = undefined} = State) ->
     State;
-dec_pipeline_counter(#state{lb_ets_tid = Tid} = State) ->
+report_request_complete(#state{lb_ets_tid = Tid} = State) ->
     ibrowse_lb:report_request_complete(Tid),
     State.
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/9d0b7e3e/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lb.erl b/src/ibrowse_lb.erl
index cc067fc..3d487d4 100644
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@ -16,7 +16,6 @@
 	 spawn_connection/6,
      stop/1,
      report_connection_down/1,
-     report_request_underway/1,
      report_request_complete/1
 	]).
 
@@ -39,6 +38,9 @@
                 proc_state}).
 
 -define(PIPELINE_MAX, 99999).
+-define(KEY_MATCHSPEC_BY_PID(Pid), [{{{'_', '_', Pid}, '_'}, [], ['$_']}]).
+-define(KEY_MATCHSPEC(Key), [{{Key, '_'}, [], ['$_']}]).
+-define(KEY_MATCHSPEC_FOR_DELETE(Key), [{{Key, '_'}, [], [true]}]).
 
 -include("ibrowse.hrl").
 
@@ -74,13 +76,23 @@ stop(Lb_pid) ->
     end.
 
 report_connection_down(Tid) ->
-    catch ets:delete(Tid, self()).
-
-report_request_underway(Tid) ->
-    catch ets:update_counter(Tid, self(), {2, 1, ?PIPELINE_MAX, ?PIPELINE_MAX}).
+    %% Don't cascade errors since Tid is really managed by other process
+    catch ets:select_delete(Tid, ?KEY_MATCHSPEC_BY_PID(self())).
 
 report_request_complete(Tid) ->
-    catch ets:update_counter(Tid, self(), {2, -1, 0, 0}).
+    %% Don't cascade errors since Tid is really managed by other process
+    catch case ets:select(Tid, ?KEY_MATCHSPEC_BY_PID(self())) of
+        [MatchKey] ->
+            case ets:select_delete(Tid, ?KEY_MATCHSPEC_FOR_DELETE(MatchKey)) of
+                1 ->
+                    ets:insert(Tid, {decremented(MatchKey), undefined}),
+                    true;
+                _ ->
+                    false
+            end;
+        _ ->
+            false
+    end.
 
 %%====================================================================
 %% Server functions
@@ -210,23 +222,17 @@ code_change(_OldVsn, State, _Extra) ->
 %%--------------------------------------------------------------------
 %%% Internal functions
 %%--------------------------------------------------------------------
-find_best_connection(Tid, Max_pipe) ->
-    find_best_connection(ets:first(Tid), Tid, Max_pipe).
-
-find_best_connection('$end_of_table', _, _) ->
-    {error, retry_later};
-find_best_connection(Pid, Tid, Max_pipe) ->
-    case ets:lookup(Tid, Pid) of
-        [{Pid, Cur_sz}] when Cur_sz < Max_pipe ->
-            case record_request_for_connection(Tid, Pid) of
-                {'EXIT', _} ->
-                    %% The selected process has shutdown
-                    find_best_connection(ets:next(Tid, Pid), Tid, Max_pipe);
-                _ ->
-                    {ok, Pid}
+find_best_connection(Tid, Max_pipeline_size) ->
+    case ets:first(Tid) of
+        {Size, _Timestamp, Pid} = Key when Size < Max_pipeline_size ->
+            case record_request_for_connection(Tid, Key) of
+                true ->
+                    {ok, Pid};
+                false ->
+                    find_best_connection(Tid, Max_pipeline_size)
             end;
-         _ ->
-            find_best_connection(ets:next(Tid, Pid), Tid, Max_pipe)
+        _ -> 
+            {error, retry_later}
     end.
 
 maybe_create_ets(#state{ets_tid = undefined} = State) ->
@@ -240,10 +246,25 @@ num_current_connections(Tid) ->
     catch ets:info(Tid, size).
 
 record_new_connection(Tid, Pid) ->
-    catch ets:insert(Tid, {Pid, 0}).
+    catch ets:insert(Tid, {new_key(Pid), undefined}).
+
+record_request_for_connection(Tid, Key) ->
+    case ets:select_delete(Tid, ?KEY_MATCHSPEC_FOR_DELETE(Key)) of
+        1 ->
+            ets:insert(Tid, {incremented(Key), undefined}),
+            true;
+        _ ->
+            false
+    end.
+
+new_key(Pid) ->
+    {1, os:timestamp(), Pid}.
+
+incremented({Size, Timestamp, Pid}) ->
+    {Size + 1, Timestamp, Pid}.
 
-record_request_for_connection(Tid, Pid) ->
-    catch ets:update_counter(Tid, Pid, {2, 1, ?PIPELINE_MAX, ?PIPELINE_MAX}).
+decremented({Size, _Timestamp, Pid}) ->
+    {Size - 1, os:timestamp(), Pid}.
 
 for_each_connection_pid(Tid, Fun) ->
     catch ets:foldl(fun({Pid, _}, _) -> Fun(Pid) end, undefined, Tid),

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/9d0b7e3e/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
index 0a68e14..fc7afec 100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@ -56,15 +56,10 @@ balanced_connections() ->
 
     timer:sleep(1000),
 
-    Diffs = [Count - BalancedNumberOfRequestsPerConnection || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
-    ?assertEqual(MaxSessions, length(Diffs)),
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
 
-    lists:foreach(fun(X) -> ?assertEqual(yep, close_to_zero(X)) end, Diffs).
-
-close_to_zero(0) -> yep;
-close_to_zero(-1) -> yep;
-close_to_zero(1) -> yep;
-close_to_zero(X) -> {nope, X}.
+    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts).
 
 times(0, _) ->
     ok;


[03/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Changed travis-ci build status link


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

Branch: refs/heads/upstream
Commit: f1244abe2c0e9e5646473af6db30b3b99031f882
Parents: 78d1814
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Wed Aug 13 11:22:55 2014 +0100
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 16:52:35 2014 +0000

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/f1244abe/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index b68f197..5820447 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ibrowse [![Build Status](https://secure.travis-ci.org/johannesh/ibrowse.png)](http://travis-ci.org/johannesh/ibrowse)
+# ibrowse [![Build Status](https://secure.travis-ci.org/cmullaparthi/ibrowse.png)](http://travis-ci.org/cmullaparthi/ibrowse)
 
 ibrowse is a HTTP client written in erlang.
 


[40/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed links


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

Branch: refs/heads/upstream
Commit: 96ea3cbb6b077a744a0aa535c34757234de1c0fe
Parents: ecff14a
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Wed Nov 25 08:28:27 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Wed Nov 25 08:28:27 2015 +0000

----------------------------------------------------------------------
 CHANGELOG           | 1 +
 src/ibrowse.app.src | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/96ea3cbb/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index e3c415b..ad15c1f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
+
 25-11-2015 - v4.2.1
              * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/132
              * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/137

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/96ea3cbb/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 2f4ced6..b3a0e8f 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -7,6 +7,6 @@
 	 {mod, {ibrowse_app, []}},
          {maintainers, ["Chandrashekhar Mullaparthi"]},
          {licenses, ["GPLv2", "BSD"]},
-         {links, ["https://github.com/cmullaparthi/ibrowse"]}
+         {links, [{"Github", "https://github.com/cmullaparthi/ibrowse"}]}
         ]
 }.


[08/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Updated contributes/authors


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

Branch: refs/heads/upstream
Commit: 86ccc45f9667c1f310ef1ab4ba902b50b96ac999
Parents: 5b8993e
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 18:27:32 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 18:27:32 2014 +0000

----------------------------------------------------------------------
 CONTRIBUTORS                      | 3 +++
 src/ibrowse_http_client.erl       | 3 +++
 src/ibrowse_lb.erl                | 3 +++
 test/ibrowse_functional_tests.erl | 5 +++--
 test/ibrowse_test_server.erl      | 5 +++--
 5 files changed, 15 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/86ccc45f/CONTRIBUTORS
----------------------------------------------------------------------
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 21e8d06..665e64b 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -9,9 +9,12 @@ In alphabetical order:
 Adam Kocoloski
 Andrew Tunnell-Jones
 Anthony Molinaro
+Benjamin P Lee (https://github.com/benjaminplee)
 Benoit Chesneau (https://github.com/benoitc)
+Brian Richards (http://github.com/richbria)
 Chris Newcombe
 Dan Kelley
+Dan Schwabe (https://github.com/dfschwabe)
 Derek Upham
 Eric Merritt
 Erik Reitsma

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/86ccc45f/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index c9161b0..d92db42 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -1,6 +1,9 @@
 %%%-------------------------------------------------------------------
 %%% File    : ibrowse_http_client.erl
 %%% Author  : Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>
+%%%           Benjamin Lee <http://github.com/benjaminplee>
+%%%           Dan Schwabe <http://github.com/dfschwabe>
+%%%           Brian Richards <http://github.com/richbria>
 %%% Description : The name says it all
 %%%
 %%% Created : 11 Oct 2003 by Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/86ccc45f/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lb.erl b/src/ibrowse_lb.erl
index eabba3a..656adda 100644
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@ -1,6 +1,9 @@
 %%%-------------------------------------------------------------------
 %%% File    : ibrowse_lb.erl
 %%% Author  : chandru <ch...@t-mobile.co.uk>
+%%%           Benjamin Lee <http://github.com/benjaminplee>
+%%%           Dan Schwabe <http://github.com/dfschwabe>
+%%%           Brian Richards <http://github.com/richbria>
 %%% Description : 
 %%%
 %%% Created :  6 Mar 2008 by chandru <ch...@t-mobile.co.uk>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/86ccc45f/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
index 8df662b..8b75e3d 100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@ -1,6 +1,7 @@
 %%% File    : ibrowse_functional_tests.erl
-%%% Authors : Benjamin Lee <ya...@gmail.com>
-%%%           Brian Richards <bm...@gmail.com>
+%%% Authors : Benjamin Lee <http://github.com/benjaminplee>
+%%%           Dan Schwabe <http://github.com/dfschwabe>
+%%%           Brian Richards <http://github.com/richbria>
 %%% Description : Functional tests of the ibrowse library using a live test HTTP server
 %%% Created : 18 November 2014 by Benjamin Lee <ya...@gmail.com>
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/86ccc45f/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index d12d1c4..1f5202f 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -1,7 +1,8 @@
 %%% File    : ibrowse_test_server.erl
 %%% Author  : Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>
-%%%           Benjamin Lee <ya...@gmail.com>
-%%%           Brian Richards <bm...@gmail.com>
+%%%           Benjamin Lee <http://github.com/benjaminplee>
+%%%           Dan Schwabe <http://github.com/dfschwabe>
+%%%           Brian Richards <http://github.com/richbria>
 %%% Description : A server to simulate various test scenarios
 %%% Created : 17 Oct 2010 by Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>
 


[27/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge branch 'master' of https://github.com/shankardevy/ibrowse into shankardevy-master


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

Branch: refs/heads/upstream
Commit: 7c4d098b7976af7dfaa7a3f34818ebfe25be85ae
Parents: ae6a918 e478d01
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 20:56:46 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 20:56:46 2015 +0100

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/7c4d098b/src/ibrowse_http_client.erl
----------------------------------------------------------------------


[45/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Bug fixes


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

Branch: refs/heads/upstream
Commit: 6d5bcef5ffd9724491c9a950717114533526b958
Parents: b5c705c
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Apr 19 18:05:13 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Apr 19 18:05:13 2016 +0100

----------------------------------------------------------------------
 .gitignore                    |   1 +
 CHANGELOG                     |   6 +
 CONTRIBUTORS                  |   2 +-
 Makefile                      |   4 +-
 README.md                     |   7 +-
 src/ibrowse.app.src           |   2 +-
 src/ibrowse.erl               |  17 ++-
 src/ibrowse_http_client.erl   |   1 +
 src/ibrowse_socks5.erl        |  55 ++++++----
 test/Makefile                 |  14 ++-
 test/ibrowse_socks_server.erl | 218 +++++++++++++++++++++++++++++++++++++
 test/ibrowse_test.erl         | 152 +++++++++++++++++---------
 test/ibrowse_test_server.erl  |  16 ++-
 13 files changed, 407 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 3f362b6..a48c26e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ mime.types
 .rebar
 *.plt
 .rebar
+*~

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 17fa072..242d82f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,12 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
 
+19-04-2016 - v4.2.3
+             * Fix for https://github.com/cmullaparthi/ibrowse/issues/143
+             * Fix for https://github.com/cmullaparthi/ibrowse/issues/142
+             * Fix for https://github.com/cmullaparthi/ibrowse/issues/139
+             * Fixed behaviour of option preserve_status_line
+
 25-11-2015 - v4.2.2
              * Fix to ibrowse.app.src to enable publishing using Hex
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/CONTRIBUTORS
----------------------------------------------------------------------
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 40310ae..0b0f803 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -62,4 +62,4 @@ https://github.com/puzza007
 https://github.com/rflynn
 https://github.com/Vagabond
 https://github.com/divolgin
-
+https://github.com/vans163

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index 396140e..f67da07 100644
--- a/Makefile
+++ b/Makefile
@@ -11,9 +11,9 @@ compile:
 	$(REBAR) compile
 
 clean:
-	$(REBAR) clean
+	@$(REBAR) clean && cd test && make clean && cd ..
 
-test: unit_tests old_tests eunit
+test: compile unit_tests eunit
 	@echo "====================================================="
 
 unit_tests:

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 396a25f..3fe7794 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.2.2
+**Current Version:** 4.2.3
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 
@@ -27,7 +27,8 @@ ibrowse is a HTTP client written in erlang.
 *  Asynchronous requests. Responses are streamed to a process
 *  Basic authentication
 *  Supports proxy authentication
-*  Supports socks5
+*  Supports SOCKS5
+    * Authentication methods 0 (No authentication) and 2(Username/password) supported
 *  Can talk to secure webservers using SSL
 *  *Any other features in the code not listed here :)*
 
@@ -292,5 +293,5 @@ ibrowse:send_req("http://google.com", [], get, [],
   [{socks5_host, "127.0.0.1"},
   {socks5_port, 5335},
   {socks5_user, "user4321"},
-  {socks5_pass, "pass7654"}]).
+  {socks5_password, "pass7654"}]).
 ```

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 84781fc..efc8094 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.2.2"},
+         {vsn, "4.2.3"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/src/ibrowse.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse.erl b/src/ibrowse.erl
index 46a3708..c412f25 100644
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@ -300,8 +300,23 @@ send_req(Url, Headers, Method, Body) ->
 %%          {workaround, head_response_with_body}     |
 %%          {worker_process_options, list()} |
 %%          {return_raw_request, true}         |
-%%          {max_attempts, integer()}
+%%          {max_attempts, integer()}          |
+%%          {socks5_host, host()}              |
+%%          {socks5_port, integer()}           |
+%%          {socks5_user, binary()}            |
+%%          {socks5_password, binary()}
 %%
+%% ip4_address() = {0..255, 0..255, 0..255, 0..255}
+%% ip6_address() = 
+%%     {0..65535,
+%%      0..65535,
+%%      0..65535,
+%%      0..65535,
+%%      0..65535,
+%%      0..65535,
+%%      0..65535,
+%%      0..65535}
+%% host() = string() | ip4_address() | ip6_address()
 %% stream_to() = process() | {process(), once}
 %% process() = pid() | atom()
 %% username() = string()

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index c668141..92ac431 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -1174,6 +1174,7 @@ parse_response(Data, #state{reply_buffer = Acc, reqs = Reqs,
                                             http_status_code=StatCode};
                           false ->
                               State_0#state{recvd_headers=Headers_1, status=get_body,
+                                            status_line = Status_line,
                                             reply_buffer = <<>>,
                                             http_status_code=StatCode}
                       end,

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/src/ibrowse_socks5.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_socks5.erl b/src/ibrowse_socks5.erl
index 417f595..2f0d1fc 100644
--- a/src/ibrowse_socks5.erl
+++ b/src/ibrowse_socks5.erl
@@ -53,18 +53,29 @@ connect(Host, Port, Options, SockOptions, Timeout) ->
     end.
 
 handshake(Socket, Options) when is_port(Socket) ->
-    {Handshake, Success} = case get_value(socks5_user, Options, <<>>) of
-        <<>> ->
-            {<<?VERSION, 1, ?NO_AUTH>>, ?NO_AUTH};
-        User ->
-            Password = get_value(socks5_password, Options, <<>>),
-            {<<?VERSION, 1, ?USERPASS, (byte_size(User)), User,
-               (byte_size(Password)), Password>>, ?USERPASS}
-    end,
-    ok = gen_tcp:send(Socket, Handshake),
-    case gen_tcp:recv(Socket, 0) of
-        {ok, <<?VERSION, Success>>} ->
+    User = get_value(socks5_user, Options, <<>>),
+    Handshake_msg = case User of
+                        <<>> ->
+                            <<?VERSION, 1, ?NO_AUTH>>;
+                        User ->
+                            <<?VERSION, 1, ?USERPASS>>
+                    end,
+    ok = gen_tcp:send(Socket, Handshake_msg),
+    case gen_tcp:recv(Socket, 2) of
+        {ok, <<?VERSION, ?NO_AUTH>>} ->
             ok;
+        {ok, <<?VERSION, ?USERPASS>>} ->
+            Password = get_value(socks5_password, Options, <<>>),
+            Auth_msg = list_to_binary([1, 
+                                       iolist_size(User), User,
+                                       iolist_size(Password), Password]),
+            ok = gen_tcp:send(Socket, Auth_msg),
+            case gen_tcp:recv(Socket, 2) of
+                {ok, <<1, ?SUCCEEDED>>} ->
+                    ok;
+                _ ->
+                    {error, unacceptable}
+            end;
         {ok, <<?VERSION, ?UNACCEPTABLE>>} ->
             {error, unacceptable};
         {error, Reason} ->
@@ -76,18 +87,18 @@ connect(Host, Port, Via) when is_list(Host) ->
 connect(Host, Port, Via) when is_binary(Host), is_integer(Port),
                               is_port(Via) ->
     {AddressType, Address} = case inet:parse_address(binary_to_list(Host)) of
-        {ok, {IP1, IP2, IP3, IP4}} ->
-            {?ATYP_IPV4, <<IP1,IP2,IP3,IP4>>};
-        {ok, {IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8}} ->
-            {?ATYP_IPV6, <<IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8>>};
-        _ ->
-            HostLength = byte_size(Host),
-            {?ATYP_DOMAINNAME, <<HostLength,Host/binary>>}
-    end,
+                                 {ok, {IP1, IP2, IP3, IP4}} ->
+                                     {?ATYP_IPV4, <<IP1,IP2,IP3,IP4>>};
+                                 {ok, {IP1, IP2, IP3, IP4, IP5, IP6, IP7, IP8}} ->
+                                     {?ATYP_IPV6, <<IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8>>};
+                                 _ ->
+                                     HostLength = byte_size(Host),
+                                     {?ATYP_DOMAINNAME, <<HostLength,Host/binary>>}
+                             end,
     ok = gen_tcp:send(Via,
-        <<?VERSION, ?CONNECT, ?RESERVED,
-          AddressType, Address/binary,
-          (Port):16>>),
+                      <<?VERSION, ?CONNECT, ?RESERVED,
+                        AddressType, Address/binary,
+                        (Port):16>>),
     case gen_tcp:recv(Via, 0) of
         {ok, <<?VERSION, ?SUCCEEDED, ?RESERVED, _/binary>>} ->
             ok;

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/test/Makefile
----------------------------------------------------------------------
diff --git a/test/Makefile b/test/Makefile
index 8211bb7..7277499 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,13 +1,17 @@
 REBAR ?= $(shell which rebar3)
+IBROWSE_EBIN_PATH=../_build/default/lib/ibrowse/ebin
+
+compile:
+	@erl -pa $(IBROWSE_EBIN_PATH) -make
 
 test: compile
-	@erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test local_unit_tests -s erlang halt
+	@erl -noshell -boot start_clean -pa $(IBROWSE_EBIN_PATH) -s ibrowse_test local_unit_tests -s erlang halt
 
 old_tests: compile
-	@erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test unit_tests -s erlang halt
+	@erl -noshell -boot start_clean -pa $(IBROWSE_EBIN_PATH) -s ibrowse_test unit_tests -s erlang halt
 
-compile:
-	@erl -pa ../../ibrowse/ebin -make
+test_shell: compile
+	erl -boot start_clean -pa $(IBROWSE_EBIN_PATH) -s ibrowse_test_server start_server
 
 clean:
-	$(REBAR) clean
+	@rm -f *.beam

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/test/ibrowse_socks_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_socks_server.erl b/test/ibrowse_socks_server.erl
new file mode 100644
index 0000000..8a17ad4
--- /dev/null
+++ b/test/ibrowse_socks_server.erl
@@ -0,0 +1,218 @@
+%%%-------------------------------------------------------------------
+%%% @author Chandru Mullaparthi <>
+%%% @copyright (C) 2016, Chandru Mullaparthi
+%%% @doc
+%%%
+%%% @end
+%%% Created : 19 Apr 2016 by Chandru Mullaparthi <>
+%%%-------------------------------------------------------------------
+-module(ibrowse_socks_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start/2, stop/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+         terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {listen_port, listen_socket, auth_method}).
+
+-define(NO_AUTH, 0).
+-define(AUTH_USER_PW, 2).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+start(Port, Auth_method) ->
+    Name = make_proc_name(Port),
+    gen_server:start({local, Name}, ?MODULE, [Port, Auth_method], []).
+
+stop(Port) ->
+    make_proc_name(Port) ! stop.
+
+make_proc_name(Port) ->
+    list_to_atom("ibrowse_socks_server_" ++ integer_to_list(Port)).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([Port, Auth_method]) ->
+    State = #state{listen_port = Port, auth_method = Auth_method},
+    {ok, Sock} = gen_tcp:listen(State#state.listen_port, [{active, false}, binary, {reuseaddr, true}]),
+    self() ! accept_connection,
+    process_flag(trap_exit, true),
+    {ok, State#state{listen_socket = Sock}}.
+
+handle_call(_Request, _From, State) ->
+    Reply = ok,
+    {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+handle_info(accept_connection, State) ->
+    case gen_tcp:accept(State#state.listen_socket, 1000) of
+        {error, timeout} ->
+            self() ! accept_connection,
+            {noreply, State};
+        {ok, Socket} ->
+            Pid = proc_lib:spawn_link(fun() ->
+                                              socks_server_loop(Socket, State#state.auth_method)
+                                      end),
+            gen_tcp:controlling_process(Socket, Pid),
+            Pid ! ready,
+            self() ! accept_connection,
+            {noreply, State};
+        _Err ->
+            {stop, normal, State}
+    end;
+
+handle_info(stop, State) ->
+    {stop, normal, State};
+
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+socks_server_loop(In_socket, Auth_method) ->
+    receive
+        ready ->
+            socks_server_loop(In_socket, Auth_method, <<>>, unauth)
+    end.
+
+socks_server_loop(In_socket, Auth_method, Acc, unauth) ->
+    inet:setopts(In_socket, [{active, once}]),
+    receive
+        {tcp, In_socket, Data} ->
+            Acc_1 = list_to_binary([Acc, Data]),
+            case Acc_1 of
+                <<5, ?NO_AUTH>> when Auth_method == ?NO_AUTH ->
+                    ok = gen_tcp:send(In_socket, <<5, ?NO_AUTH>>),
+                    socks_server_loop(In_socket, Auth_method, <<>>, auth_done);
+                <<5, Num_auth_methods, Auth_methods:Num_auth_methods/binary>> ->
+                    case lists:member(Auth_method, binary_to_list(Auth_methods)) of
+                        true ->
+                            ok = gen_tcp:send(In_socket, <<5, Auth_method>>),
+                            Conn_state = case Auth_method of
+                                             ?NO_AUTH -> auth_done;
+                                             _ -> auth_pending
+                                         end,
+                            socks_server_loop(In_socket, Auth_method, <<>>, Conn_state);
+                        false ->
+                            ok = gen_tcp:send(In_socket, <<5, 16#ff>>),
+                            gen_tcp:close(In_socket)
+                    end;
+                _ ->
+                    ok = gen_tcp:send(In_socket, <<5, 0>>),
+                    gen_tcp:close(In_socket)
+            end;
+        {tcp_closed, In_socket} ->
+            ok;
+        {tcp_error, In_socket, _Rsn} ->
+            ok
+    end;
+socks_server_loop(In_socket, Auth_method, Acc, auth_pending) ->
+    inet:setopts(In_socket, [{active, once}]),
+    receive
+        {tcp, In_socket, Data} ->
+            Acc_1 = list_to_binary([Acc, Data]),
+            case Acc_1 of
+                <<1, U_len, Username:U_len/binary, P_len, Password:P_len/binary>> ->
+                    case check_user_pw(Username, Password) of
+                        ok ->
+                            ok = gen_tcp:send(In_socket, <<1, 0>>),
+                            socks_server_loop(In_socket, Auth_method, <<>>, auth_done);
+                        notok ->
+                            ok = gen_tcp:send(In_socket, <<1, 1>>),
+                            gen_tcp:close(In_socket)
+                    end;
+                _ ->
+                    socks_server_loop(In_socket, Auth_method, Acc_1, auth_pending)
+            end;
+        {tcp_closed, In_socket} ->
+            ok;
+        {tcp_error, In_socket, _Rsn} ->
+            ok
+    end;
+socks_server_loop(In_socket, Auth_method, Acc, auth_done) ->
+    inet:setopts(In_socket, [{active, once}]),
+    receive
+        {tcp, In_socket, Data} ->
+            Acc_1 = list_to_binary([Acc, Data]),
+            case Acc_1 of
+                <<5, 1, 0, Addr_type, Dest_ip:4/binary, Dest_port:16>> when Addr_type == 1->
+                    handle_connect(In_socket, Addr_type, Dest_ip, Dest_port);
+                <<5, 1, 0, Addr_type, Dest_len, Dest_hostname:Dest_len/binary, Dest_port:16>> when Addr_type == 3 ->
+                    handle_connect(In_socket, Addr_type, Dest_hostname, Dest_port);
+                <<5, 1, 0, Addr_type, Dest_ip:16/binary, Dest_port:16>> when Addr_type == 4->
+                    handle_connect(In_socket, Addr_type, Dest_ip, Dest_port);
+                _ ->
+                    socks_server_loop(In_socket, Auth_method, Acc_1, auth_done)
+            end;
+        {tcp_closed, In_socket} ->
+            ok;
+        {tcp_error, In_socket, _Rsn} ->
+            ok
+    end.
+
+handle_connect(In_socket, Addr_type, Dest_host, Dest_port) ->
+    Dest_host_1 = case Addr_type of
+                      1 ->
+                          list_to_tuple(binary_to_list(Dest_host));
+                      3 ->
+                          binary_to_list(Dest_host);
+                      4 ->
+                          list_to_tuple(binary_to_list(Dest_host))
+                  end,
+    case gen_tcp:connect(Dest_host_1, Dest_port, [binary, {active, once}]) of
+        {ok, Out_socket} ->
+            Addr = case Addr_type of
+                       1 ->
+                           <<Dest_host/binary, Dest_port:16>>;
+                       3 ->
+                           Len = size(Dest_host),
+                           <<Len, Dest_host/binary, Dest_port:16>>;
+                       4 ->
+                           <<Dest_host/binary, Dest_port:16>>
+                   end,
+            ok = gen_tcp:send(In_socket, <<5, 0, 0, Addr_type, Addr/binary>>),
+            inet:setopts(In_socket, [{active, once}]),
+            inet:setopts(Out_socket, [{active, once}]),
+            connected_loop(In_socket, Out_socket);
+        _Err ->
+            ok = gen_tcp:send(<<5, 1>>),
+            gen_tcp:close(In_socket)
+    end.
+
+check_user_pw(<<"user">>, <<"password">>) ->
+    ok;
+check_user_pw(_, _) ->
+    notok.
+
+connected_loop(In_socket, Out_socket) ->
+    receive
+        {tcp, In_socket, Data} ->
+            inet:setopts(In_socket, [{active, once}]),
+            ok = gen_tcp:send(Out_socket, Data),
+            connected_loop(In_socket, Out_socket);
+        {tcp, Out_socket, Data} ->
+            inet:setopts(Out_socket, [{active, once}]),
+            ok = gen_tcp:send(In_socket, Data),
+            connected_loop(In_socket, Out_socket);
+        _ ->
+            ok
+    end.

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 89d5d06..e5842fb 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -33,16 +33,103 @@
          test_303_response_with_no_body/1,
          test_303_response_with_a_body/0,
          test_303_response_with_a_body/1,
+         test_preserve_status_line/0,
          test_binary_headers/0,
          test_binary_headers/1,
          test_generate_body_0/0,
          test_retry_of_requests/0,
          test_retry_of_requests/1,
-	 test_save_to_file_no_content_length/0
+	 test_save_to_file_no_content_length/0,
+         socks5_noauth_test/0,
+         socks5_auth_succ_test/0,
+         socks5_auth_fail_test/0
 	]).
 
 -include_lib("ibrowse/include/ibrowse.hrl").
 
+%%------------------------------------------------------------------------------
+%% Unit Tests
+%%------------------------------------------------------------------------------
+-define(LOCAL_TESTS, [
+                      {local_test_fun, socks5_noauth_test, []},
+                      {local_test_fun, socks5_auth_succ_test, []},
+                      {local_test_fun, socks5_auth_fail_test, []},
+                      {local_test_fun, test_preserve_status_line, []},
+		      {local_test_fun, test_save_to_file_no_content_length, []},
+                      {local_test_fun, test_20122010, []},
+                      {local_test_fun, test_pipeline_head_timeout, []},
+                      {local_test_fun, test_head_transfer_encoding, []},
+                      {local_test_fun, test_head_response_with_body, []},
+                      {local_test_fun, test_303_response_with_a_body, []},
+		      {local_test_fun, test_303_response_with_no_body, []},
+                      {local_test_fun, test_binary_headers, []},
+                      {local_test_fun, test_retry_of_requests, []},
+		      {local_test_fun, verify_chunked_streaming, []},
+		      {local_test_fun, test_chunked_streaming_once, []},
+		      {local_test_fun, test_generate_body_0, []}
+                     ]).
+
+-define(TEST_LIST, [{"http://intranet/messenger", get},
+		    {"http://www.google.co.uk", get},
+		    {"http://www.google.com", get},
+		    {"http://www.google.com", options},
+                    {"https://mail.google.com", get},
+		    {"http://www.sun.com", get},
+		    {"http://www.oracle.com", get},
+		    {"http://www.bbc.co.uk", get},
+		    {"http://www.bbc.co.uk", trace},
+		    {"http://www.bbc.co.uk", options},
+		    {"http://yaws.hyber.org", get},
+		    {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
+		    {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
+		    {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
+		    {"http://jigsaw.w3.org/HTTP/connection.html", get},
+		    {"http://jigsaw.w3.org/HTTP/cc.html", get},
+		    {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
+		    {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
+		    {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
+		    {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
+		    {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
+		    {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
+		    {"http://jigsaw.w3.org/HTTP/neg", get},
+		    {"http://jigsaw.w3.org/HTTP/negbad", get},
+		    {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
+		    {"http://jigsaw.w3.org/HTTP/300/", get},
+		    {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
+		    {"http://jigsaw.w3.org/HTTP/CL/", get},
+		    {"http://www.httpwatch.com/httpgallery/chunked/", get},
+                    {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}
+		   ]).
+
+socks5_noauth_test() ->
+    case ibrowse:send_req("http://localhost:8181/success", [], get, [],
+                          [{socks5_host, "localhost"}, {socks5_port, 8282}], 2000) of
+	{ok, "200", _, _} ->
+            success;
+	Err ->
+	    Err
+    end.
+
+socks5_auth_succ_test() ->
+    case ibrowse:send_req("http://localhost:8181/success", [], get, [],
+                          [{socks5_host, "localhost"}, {socks5_port, 8383},
+                           {socks5_user, <<"user">>}, {socks5_password, <<"password">>}], 2000) of
+	{ok, "200", _, _} ->
+            success;
+	Err ->
+	    Err
+    end.
+
+socks5_auth_fail_test() ->
+    case ibrowse:send_req("http://localhost:8181/success", [], get, [],
+                          [{socks5_host, "localhost"}, {socks5_port, 8282},
+                           {socks5_user, <<"user">>}, {socks5_password, <<"wrong_password">>}], 2000) of
+        {error,{conn_failed,{error,unacceptable}}} ->
+            success;
+	Err ->
+	    Err
+    end.
+
 test_stream_once(Url, Method, Options) ->
     test_stream_once(Url, Method, Options, 5000).
 
@@ -212,56 +299,6 @@ dump_errors(Key, Iod) ->
     file:write(Iod, io_lib:format("~p~n", [Term])),
     dump_errors(ets:next(ibrowse_errors, Key), Iod).
 
-%%------------------------------------------------------------------------------
-%% Unit Tests
-%%------------------------------------------------------------------------------
--define(LOCAL_TESTS, [
-                      {local_test_fun, test_20122010, []},
-                      {local_test_fun, test_pipeline_head_timeout, []},
-                      {local_test_fun, test_head_transfer_encoding, []},
-                      {local_test_fun, test_head_response_with_body, []},
-                      {local_test_fun, test_303_response_with_a_body, []},
-		      {local_test_fun, test_303_response_with_no_body, []},
-                      {local_test_fun, test_binary_headers, []},
-                      {local_test_fun, test_retry_of_requests, []},
-		      {local_test_fun, test_save_to_file_no_content_length, []},
-		      {local_test_fun, verify_chunked_streaming, []},
-		      {local_test_fun, test_chunked_streaming_once, []},
-		      {local_test_fun, test_generate_body_0, []}
-                     ]).
-
--define(TEST_LIST, [{"http://intranet/messenger", get},
-		    {"http://www.google.co.uk", get},
-		    {"http://www.google.com", get},
-		    {"http://www.google.com", options},
-                    {"https://mail.google.com", get},
-		    {"http://www.sun.com", get},
-		    {"http://www.oracle.com", get},
-		    {"http://www.bbc.co.uk", get},
-		    {"http://www.bbc.co.uk", trace},
-		    {"http://www.bbc.co.uk", options},
-		    {"http://yaws.hyber.org", get},
-		    {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
-		    {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
-		    {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
-		    {"http://jigsaw.w3.org/HTTP/connection.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
-		    {"http://jigsaw.w3.org/HTTP/neg", get},
-		    {"http://jigsaw.w3.org/HTTP/negbad", get},
-		    {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
-		    {"http://jigsaw.w3.org/HTTP/300/", get},
-		    {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
-		    {"http://jigsaw.w3.org/HTTP/CL/", get},
-		    {"http://www.httpwatch.com/httpgallery/chunked/", get},
-                    {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}
-		   ]).
-
 local_unit_tests() ->
     unit_tests([], ?LOCAL_TESTS).
 
@@ -565,6 +602,16 @@ test_303_response_with_a_body(Url) ->
             {test_failed, Res}
     end.
 
+%% Test that the 'preserve_status_line' option works as expected
+test_preserve_status_line() ->
+    case ibrowse:send_req("http://localhost:8181/ibrowse_preserve_status_line", [], get, [],
+                          [{preserve_status_line, true}]) of
+        {ok, "200", [{ibrowse_status_line,<<"HTTP/1.1 200 OKBlah">>} | _], _} ->
+            success;
+        Res ->
+            {test_failed, Res}
+    end.
+
 %%------------------------------------------------------------------------------
 %% Test that when the save_response_to_file option is used with a server which
 %% does not send the Content-Length header, the response is saved correctly to
@@ -578,7 +625,8 @@ test_save_to_file_no_content_length() ->
 		    lists:flatten(
 		      io_lib:format("test_save_to_file_no_content_length_~p~p~p_~p~p~p.txt", [Y, M, D, H, Mi, S]))]),
     try
-	case ibrowse:send_req("http://localhost:8181/ibrowse_send_file_conn_close", [], get, [], [{save_response_to_file, Test_file}]) of
+	case ibrowse:send_req("http://localhost:8181/ibrowse_send_file_conn_close", [], get, [],
+                              [{save_response_to_file, Test_file}]) of
 	    {ok, "200", _, {file, Test_file}} ->
 		success;
 	    Res ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/6d5bcef5/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index 067e627..f30e895 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -5,6 +5,7 @@
 
 -module(ibrowse_test_server).
 -export([
+         start_server/0,
          start_server/2,
          stop_server/1,
          get_conn_pipeline_depth/0
@@ -16,6 +17,9 @@
 -define(ACCEPT_TIMEOUT_MS, 10000).
 -define(CONN_PIPELINE_DEPTH, conn_pipeline_depth).
 
+start_server() ->
+    start_server(8181, tcp).
+
 start_server(Port, Sock_type) ->
     Fun = fun() ->
 		  Proc_name = server_proc_name(Port),
@@ -42,10 +46,14 @@ start_server(Port, Sock_type) ->
 			  ok
 		  end
 	  end,
-    spawn_link(Fun).
+    spawn_link(Fun),
+    ibrowse_socks_server:start(8282, 0), %% No auth
+    ibrowse_socks_server:start(8383, 2). %% Username/Password auth
 
 stop_server(Port) ->
     catch server_proc_name(Port) ! stop,
+    ibrowse_socks_server:stop(8282),
+    ibrowse_socks_server:stop(8383),
     timer:sleep(2000),  % wait for server to receive msg and unregister
     ok.
 
@@ -247,6 +255,12 @@ process_request(Sock, Sock_type,
     Resp = <<"HTTP/1.1 303 See Other\r\nLocation: http://example.org\r\nContent-Length: 5\r\n\r\nabcde">>,
     do_send(Sock, Sock_type, Resp);
 process_request(Sock, Sock_type,
+                #request{method='GET',
+                         headers = _Headers,
+                         uri = {abs_path, "/ibrowse_preserve_status_line"}}) ->
+    Resp = <<"HTTP/1.1 200 OKBlah\r\nContent-Length: 5\r\n\r\nabcde">>,
+    do_send(Sock, Sock_type, Resp);
+process_request(Sock, Sock_type,
     #request{method='GET',
         headers = _Headers,
         uri = {abs_path, "/ibrowse_handle_one_request_only_with_delay"}}) ->


[39/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Version incremented


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

Branch: refs/heads/upstream
Commit: ecff14ab236f8ca4bfba12e10ae75e241dce4447
Parents: 79e26ae
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Wed Nov 25 07:46:13 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Wed Nov 25 07:46:13 2015 +0000

----------------------------------------------------------------------
 CHANGELOG | 4 ++++
 README.md | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ecff14ab/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index e7301cf..e3c415b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
+25-11-2015 - v4.2.1
+             * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/132
+             * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/137
+
 28-09-2015 - v4.2
              * Merged long pending improvements to pipelining
                https://github.com/cmullaparthi/ibrowse/pull/123

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ecff14ab/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index fa0305f..ae060ae 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.2
+**Current Version:** 4.2.1
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 


[30/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
add hex metadata

for packaging in hex


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

Branch: refs/heads/upstream
Commit: 94fab9a4d9986706253473683ac751328502d8ea
Parents: fd81d44
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:29:35 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:29:35 2015 +0100

----------------------------------------------------------------------
 src/ibrowse.app.src | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/94fab9a4/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 3baa8d0..cc20637 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,7 +1,13 @@
-{application, ibrowse,
-        [{description, "Erlang HTTP client application"},
-         {vsn, "4.2"},
-         {registered, [ibrowse_sup, ibrowse]},
-         {applications, [kernel,stdlib]},
-	 {env, []},
-	 {mod, {ibrowse_app, []}}]}.
+{application, ibrowse, [
+	{description, "Erlang HTTP client application"},
+	{vsn, "4.2"},
+	{registered, [ibrowse_sup, ibrowse]},
+	{applications, [kernel,stdlib]},
+	{env, []},
+	{mod, {ibrowse_app, []}},
+
+	{maintainers, ["Chandrashekhar Mullaparthi"]},
+	{license, ["BSD"]},
+	{links, [{"Github", "https://github.com/cmullaparthi/ibrowse"}]}
+
+]}.


[06/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Removed duplicate documentation


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

Branch: refs/heads/upstream
Commit: 4b0fb6b8a0e80c5afe16601a82245776ea2cf498
Parents: 642c082
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 18:01:25 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 18:01:25 2014 +0000

----------------------------------------------------------------------
 src/ibrowse.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/4b0fb6b8/src/ibrowse.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse.erl b/src/ibrowse.erl
index 0ade277..951cfe1 100644
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@ -158,7 +158,7 @@ stop() ->
 %% respHeader() = {headerName(), headerValue()}
 %% headerName() = string()
 %% headerValue() = string()
-%% response() = {ok, Status, ResponseHeaders, ResponseBody} | {ok, Status, ResponseHeaders, ResponseBody} | {ibrowse_req_id, req_id() } | {error, Reason}
+%% response() = {ok, Status, ResponseHeaders, ResponseBody} | {ibrowse_req_id, req_id() } | {error, Reason}
 %% req_id() = term()
 %% ResponseBody = string() | {file, Filename}
 %% Reason = term()


[33/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
fix tests


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

Branch: refs/heads/upstream
Commit: 8734ed3d0db57079a220060a19c082cb2b56a6dd
Parents: 1439ab0
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:42:42 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:42:42 2015 +0100

----------------------------------------------------------------------
 test/ibrowse_load_test.erl | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8734ed3d/test/ibrowse_load_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_load_test.erl b/test/ibrowse_load_test.erl
index 5ff308e..eef0aaf 100644
--- a/test/ibrowse_load_test.erl
+++ b/test/ibrowse_load_test.erl
@@ -36,11 +36,11 @@ start_1(Num_workers, Num_requests, Max_sess) ->
                                                  {one_request_only, 0}
                                                 ]),
         ibrowse:set_max_sessions("localhost", 8081, Max_sess),
-        Start_time    = now(),
+        Start_time    = os:timestamp(),
         Workers       = spawn_workers(Num_workers, Num_requests),
         erlang:send_after(1000, self(), print_diagnostics),
         ok            = wait_for_workers(Workers),
-        End_time      = now(),
+        End_time      = os:timestamp(),
         Time_in_secs  = trunc(round(timer:now_diff(End_time, Start_time) / 1000000)),
         Req_count     = Num_workers * Num_requests,
         [{_, Success_count}] = ets:lookup(?ibrowse_load_test_counters, success),
@@ -95,7 +95,7 @@ spawn_workers(0, _Num_requests, _Parent, Acc) ->
     lists:reverse(Acc);
 spawn_workers(Num_workers, Num_requests, Parent, Acc) ->
     Pid_ref = spawn_monitor(fun() ->
-                                    random:seed(now()),
+                                    random:seed(os:timestamp()),
                                     case catch worker_loop(Parent, Num_requests) of
                                         {'EXIT', Rsn} ->
                                             io:format("Worker crashed with reason: ~p~n", [Rsn]);
@@ -150,11 +150,11 @@ worker_loop(Parent, N) ->
               _ ->
                   "http://localhost:8081/blah"
           end,
-    Start_time = now(),
+    Start_time = os:timestamp(),
     Res = ibrowse:send_req(Url, [], get),
-    End_time = now(),
+    End_time = os:timestamp(),
     Time_taken = trunc(round(timer:now_diff(End_time, Start_time) / 1000)),
-    ets:insert(ibrowse_load_timings, {now(), Time_taken}),
+    ets:insert(ibrowse_load_timings, {os:timestamp(), Time_taken}),
     case Res of
         {ok, "200", _, _} ->
             ets:update_counter(?ibrowse_load_test_counters, success, 1);


[37/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge branch 'barrel-db-master'


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

Branch: refs/heads/upstream
Commit: ad31b0375ba71189899ed417d216d1f0a2af33e6
Parents: 1ae07ed 14bb6b8
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Tue Nov 24 08:55:39 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Tue Nov 24 08:55:39 2015 +0000

----------------------------------------------------------------------
 .gitignore                   |  22 ++---
 .travis.yml                  |  12 ++-
 Makefile                     |  48 ++++-----
 bootstrap_travis.sh          |   5 +
 doc/edoc-info                |   4 +
 doc/erlang.png               | Bin 0 -> 2109 bytes
 doc/ibrowse.html             | 201 +++++++++++---------------------------
 doc/ibrowse_app.html         |  38 +++++++
 doc/ibrowse_http_client.html |  98 +++++++++++++++++++
 doc/ibrowse_lb.html          |  80 +++++++++++++++
 doc/ibrowse_lib.html         | 121 ++++++++++++++++-------
 doc/ibrowse_socks5.html      |  31 ++++++
 doc/ibrowse_sup.html         |  38 +++++++
 doc/index.html               |  17 ++++
 doc/modules-frame.html       |  18 ++++
 doc/overview-summary.html    |  16 +++
 doc/stylesheet.css           |  55 +++++++++++
 rebar                        | Bin 188026 -> 0 bytes
 rebar.lock                   |   1 +
 test/ibrowse_load_test.erl   |  12 +--
 20 files changed, 589 insertions(+), 228 deletions(-)
----------------------------------------------------------------------



[12/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
adding max_attempts option


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

Branch: refs/heads/upstream
Commit: 418f6ce9321074f4462951916b36d3fa683fa827
Parents: e18ea91
Author: Marcelo Gornstein <ma...@gmail.com>
Authored: Thu May 7 11:58:01 2015 -0300
Committer: Marcelo Gornstein <ma...@gmail.com>
Committed: Thu May 7 12:54:55 2015 -0300

----------------------------------------------------------------------
 src/ibrowse.erl | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/418f6ce9/src/ibrowse.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse.erl b/src/ibrowse.erl
index 85bb75c..1ffa11b 100644
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@ -90,6 +90,7 @@
          stream_close/1,
          set_max_sessions/3,
          set_max_pipeline_size/3,
+         set_max_attempts/3,
          set_dest/3,
          trace_on/0,
          trace_off/0,
@@ -120,6 +121,7 @@
 
 -define(DEF_MAX_SESSIONS,10).
 -define(DEF_MAX_PIPELINE_SIZE,10).
+-define(DEF_MAX_ATTEMPTS,3).
 
 %%====================================================================
 %% External functions
@@ -292,7 +294,8 @@ send_req(Url, Headers, Method, Body) ->
 %%          {preserve_chunked_encoding,boolean()}     |
 %%          {workaround, head_response_with_body}     |
 %%          {worker_process_options, list()} |
-%%          {return_raw_request, true}
+%%          {return_raw_request, true}         |
+%%          {max_attempts, integer()}
 %%
 %% stream_to() = process() | {process(), once}
 %% process() = pid() | atom()
@@ -325,6 +328,7 @@ send_req(Url, Headers, Method, Body, Options, Timeout) ->
                      end,
             Max_sessions = get_max_sessions(Host, Port, Options),
             Max_pipeline_size = get_max_pipeline_size(Host, Port, Options),
+            Max_attempts = get_max_attempts(Host, Port, Options),
             Options_1 = merge_options(Host, Port, Options),
             {SSLOptions, IsSSL} =
                 case (Protocol == https) orelse
@@ -336,7 +340,7 @@ send_req(Url, Headers, Method, Body, Options, Timeout) ->
                                 Max_sessions, 
                                 Max_pipeline_size,
                                 {SSLOptions, IsSSL}, 
-                                Headers, Method, Body, Options_1, Timeout, 0);
+                                Headers, Method, Body, Options_1, Timeout, Max_attempts, 0);
         Err ->
             {error, {url_parsing_failed, Err}}
     end.
@@ -345,7 +349,7 @@ try_routing_request(Lb_pid, Parsed_url,
                     Max_sessions, 
                     Max_pipeline_size,
                     {SSLOptions, IsSSL}, 
-                    Headers, Method, Body, Options_1, Timeout, Try_count) when Try_count < 3 ->
+                    Headers, Method, Body, Options_1, Timeout, Max_attempts, Try_count) when Try_count < Max_attempts ->
     ProcessOptions = get_value(worker_process_options, Options_1, []),
     case ibrowse_lb:spawn_connection(Lb_pid, Parsed_url,
                                              Max_sessions, 
@@ -360,14 +364,14 @@ try_routing_request(Lb_pid, Parsed_url,
                                         Max_sessions, 
                                         Max_pipeline_size,
                                         {SSLOptions, IsSSL}, 
-                                        Headers, Method, Body, Options_1, Timeout, Try_count + 1);
+                                        Headers, Method, Body, Options_1, Timeout, Max_attempts, Try_count + 1);
                 Res ->
                     Res
             end;
         Err ->
             Err
     end;
-try_routing_request(_, _, _, _, _, _, _, _, _, _, _) ->
+try_routing_request(_, _, _, _, _, _, _, _, _, _, _, _) ->
     {error, retry_later}.
 
 merge_options(Host, Port, Options) ->
@@ -396,12 +400,20 @@ get_max_pipeline_size(Host, Port, Options) ->
               get_config_value({max_pipeline_size, Host, Port},
                                default_max_pipeline_size())).
 
+get_max_attempts(Host, Port, Options) ->
+    get_value(max_attempts, Options,
+              get_config_value({max_attempts, Host, Port},
+                               default_max_attempts())).
+
 default_max_sessions() ->
     safe_get_env(ibrowse, default_max_sessions, ?DEF_MAX_SESSIONS).
 
 default_max_pipeline_size() ->
     safe_get_env(ibrowse, default_max_pipeline_size, ?DEF_MAX_PIPELINE_SIZE).
 
+default_max_attempts() ->
+    safe_get_env(ibrowse, default_max_attempts, ?DEF_MAX_ATTEMPTS).
+
 safe_get_env(App, Key, Def_val) ->
     case application:get_env(App, Key) of
         undefined ->
@@ -436,6 +448,11 @@ set_max_sessions(Host, Port, Max) when is_integer(Max), Max > 0 ->
 set_max_pipeline_size(Host, Port, Max) when is_integer(Max), Max > 0 ->
     gen_server:call(?MODULE, {set_config_value, {max_pipeline_size, Host, Port}, Max}).
 
+%% @doc Set the maximum attempts for each connection to a specific Host:Port.
+%% @spec set_max_attempts(Host::string(), Port::integer(), Max::integer()) -> ok
+set_max_attempts(Host, Port, Max) when is_integer(Max), Max > 0 ->
+    gen_server:call(?MODULE, {set_config_value, {max_attempts, Host, Port}, Max}).
+
 do_send_req(Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout) ->
     case catch ibrowse_http_client:send_req(Conn_Pid, Parsed_url,
                                             Headers, Method, ensure_bin(Body),


[20/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge pull request #132 from surik/patch-1

Fix ibrowse_http_client.erl

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

Branch: refs/heads/upstream
Commit: 5ee4a806611fcf25cc74155871571e9983a0d0fc
Parents: 58007c7 0970fa0
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Jun 29 07:39:11 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Jun 29 07:39:11 2015 +0100

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[26/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge branch 'merge_pull_req_123'


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

Branch: refs/heads/upstream
Commit: ae6a91855bd573015e25878e94c7c6cccdb41471
Parents: ea3305d 3c96a91
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 20:55:25 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 20:55:25 2015 +0100

----------------------------------------------------------------------
 .gitignore                        |   1 +
 CONTRIBUTORS                      |   3 +
 Makefile                          |   7 +-
 README.md                         |   2 +-
 include/ibrowse.hrl               |   7 +-
 rebar                             | Bin 90778 -> 188026 bytes
 src/ibrowse.erl                   | 155 +++++++++++---------
 src/ibrowse_http_client.erl       | 251 +++++++++++++++++++++------------
 src/ibrowse_lb.erl                | 108 +++++---------
 src/ibrowse_lib.erl               |  10 +-
 test/ibrowse_functional_tests.erl | 174 +++++++++++++++++++++++
 test/ibrowse_load_test.erl        | 181 ++++++++++++++++++++++++
 test/ibrowse_test.erl             | 155 ++++++++++++++++----
 test/ibrowse_test_server.erl      | 124 +++++++++++-----
 14 files changed, 876 insertions(+), 302 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ae6a9185/CONTRIBUTORS
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ae6a9185/README.md
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ae6a9185/src/ibrowse.erl
----------------------------------------------------------------------
diff --cc src/ibrowse.erl
index 1ffa11b,51fcb86..46a3708
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@@ -340,7 -341,7 +345,7 @@@ send_req(Url, Headers, Method, Body, Op
                                  Max_sessions, 
                                  Max_pipeline_size,
                                  {SSLOptions, IsSSL}, 
-                                 Headers, Method, Body, Options_1, Timeout, Max_attempts, 0);
 -                                Headers, Method, Body, Options_1, Timeout, Timeout, os:timestamp(), 0);
++                                Headers, Method, Body, Options_1, Timeout, Timeout, os:timestamp(), Max_attempts, 0);
          Err ->
              {error, {url_parsing_failed, Err}}
      end.
@@@ -349,7 -350,8 +354,8 @@@ try_routing_request(Lb_pid, Parsed_url
                      Max_sessions, 
                      Max_pipeline_size,
                      {SSLOptions, IsSSL}, 
-                     Headers, Method, Body, Options_1, Timeout, Max_attempts, Try_count) when Try_count < Max_attempts ->
+                     Headers, Method, Body, Options_1, Timeout,
 -                    Ori_timeout, Req_start_time, Try_count) when Try_count =< 3 ->
++                    Ori_timeout, Req_start_time, Max_attempts, Try_count) when Try_count < Max_attempts ->
      ProcessOptions = get_value(worker_process_options, Options_1, []),
      case ibrowse_lb:spawn_connection(Lb_pid, Parsed_url,
                                               Max_sessions, 
@@@ -360,18 -362,29 +366,29 @@@
              case do_send_req(Conn_Pid, Parsed_url, Headers,
                               Method, Body, Options_1, Timeout) of
                  {error, sel_conn_closed} ->
-                     try_routing_request(Lb_pid, Parsed_url,
-                                         Max_sessions, 
-                                         Max_pipeline_size,
-                                         {SSLOptions, IsSSL}, 
-                                         Headers, Method, Body, Options_1, Timeout, Max_attempts, Try_count + 1);
+                     Time_now = os:timestamp(),
+                     Time_taken_so_far = trunc(round(timer:now_diff(Time_now, Req_start_time)/1000)),
+                     Time_remaining = Ori_timeout - Time_taken_so_far,
+                     Time_remaining_percent = trunc(round((Time_remaining/Ori_timeout)*100)),
+                     %% io:format("~p -- Time_remaining: ~p (~p%)~n", [self(), Time_remaining, Time_remaining_percent]),
+                     case (Time_remaining > 0) andalso (Time_remaining_percent >= 5) of
+                         true ->
+                             try_routing_request(Lb_pid, Parsed_url,
+                                                 Max_sessions, 
+                                                 Max_pipeline_size,
+                                                 {SSLOptions, IsSSL}, 
+                                                 Headers, Method, Body, Options_1,
 -                                                Time_remaining, Ori_timeout, Req_start_time, Try_count + 1);
++                                                Time_remaining, Ori_timeout, Req_start_time, Max_attempts, Try_count + 1);
+                         false ->
+                             {error, retry_later}
+                     end;
                  Res ->
                      Res
              end;
          Err ->
              Err
      end;
- try_routing_request(_, _, _, _, _, _, _, _, _, _, _, _) ->
 -try_routing_request(_, _, _, _, _, _, _, _, _, _, _, _, _) ->
++try_routing_request(_, _, _, _, _, _, _, _, _, _, _, _, _, _) ->
      {error, retry_later}.
  
  merge_options(Host, Port, Options) ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ae6a9185/src/ibrowse_http_client.erl
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ae6a9185/test/ibrowse_test.erl
----------------------------------------------------------------------


[19/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fix ibrowse_http_client.erl

Fix misprint in #130

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

Branch: refs/heads/upstream
Commit: 0970fa0350c104429b1373e2e89d93de7a8c85d6
Parents: 58007c7
Author: Yury Gargay <yu...@gmail.com>
Authored: Fri Jun 26 18:17:11 2015 +0500
Committer: Yury Gargay <yu...@gmail.com>
Committed: Fri Jun 26 18:17:11 2015 +0500

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/0970fa03/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index b9e6c97..abe0aab 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -1923,7 +1923,7 @@ cancel_timer(Ref, {eat_message, Msg}) ->
     end.
 
 make_req_id() ->
-    case catch erlang:unqiue_integer() of
+    case catch erlang:unique_integer() of
         {'EXIT', _} ->
             erlang:apply(erlang, now, []);
         V ->


[36/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge branch 'master' of https://github.com/barrel-db/ibrowse into barrel-db-master


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

Branch: refs/heads/upstream
Commit: 14bb6b8d04bbf0ec13f87d3a791f4a3c84f8fb0c
Parents: 1ae07ed 82f6186
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Tue Nov 24 08:55:19 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Tue Nov 24 08:55:19 2015 +0000

----------------------------------------------------------------------
 .gitignore                   |  22 ++---
 .travis.yml                  |  12 ++-
 Makefile                     |  48 ++++-----
 bootstrap_travis.sh          |   5 +
 doc/edoc-info                |   4 +
 doc/erlang.png               | Bin 0 -> 2109 bytes
 doc/ibrowse.html             | 201 +++++++++++---------------------------
 doc/ibrowse_app.html         |  38 +++++++
 doc/ibrowse_http_client.html |  98 +++++++++++++++++++
 doc/ibrowse_lb.html          |  80 +++++++++++++++
 doc/ibrowse_lib.html         | 121 ++++++++++++++++-------
 doc/ibrowse_socks5.html      |  31 ++++++
 doc/ibrowse_sup.html         |  38 +++++++
 doc/index.html               |  17 ++++
 doc/modules-frame.html       |  18 ++++
 doc/overview-summary.html    |  16 +++
 doc/stylesheet.css           |  55 +++++++++++
 rebar                        | Bin 188026 -> 0 bytes
 rebar.lock                   |   1 +
 test/ibrowse_load_test.erl   |  12 +--
 20 files changed, 589 insertions(+), 228 deletions(-)
----------------------------------------------------------------------



[32/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
move to rebar3


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

Branch: refs/heads/upstream
Commit: 1439ab010bfe8ae29107bb012c01b5f508ce8afe
Parents: 4509902
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:41:21 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:41:21 2015 +0100

----------------------------------------------------------------------
 .gitignore           |  22 ++---
 Makefile             |  40 +++------
 doc/ibrowse.html     | 201 +++++++++++++---------------------------------
 doc/ibrowse_lib.html | 121 +++++++++++++++++++---------
 rebar.lock           |   1 +
 5 files changed, 167 insertions(+), 218 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1439ab01/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 1491146..3f362b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,12 @@
-ebin/
-*~
-.eunit/
-*beam
-doc/*.html
-doc/*.css
-doc/*.png
-doc/edoc-info
-Emakefile
-*.bat
-.dialyzer_plt
+_build
+ebin
+*.beam
+*.sw*
+deps
+.DS_Store
+erl_crash.dump
+.eunit
+mime.types
+.rebar
+*.plt
 .rebar

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1439ab01/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index 4df166b..918f33b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ IBROWSE_VSN = $(shell sed -n 's/.*{vsn,.*"\(.*\)"}.*/\1/p' src/ibrowse.app.src)
 DIALYZER_PLT=$(CURDIR)/.dialyzer_plt
 DIALYZER_APPS=erts kernel stdlib ssl crypto public_key
 
-REBAR ?= $(shell which rebar)
+REBAR ?= $(shell which rebar3)
 
 all: compile
 
@@ -13,35 +13,21 @@ compile:
 clean:
 	$(REBAR) clean
 
-install: compile
-	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
-	cp -r ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
-
-eunit_test: all
+test:
 	$(REBAR) eunit
 
-test: all
-	cd test; erl -pa ../../ibrowse/ebin -make; cd ../; \
-	erl -noshell -pa test -pa ebin -s ibrowse_test unit_tests \
-	-s ibrowse_test verify_chunked_streaming \
-	-s ibrowse_test test_chunked_streaming_once \
-	-s erlang halt
-
 xref: all
 	$(REBAR) xref
 
 docs:
-	erl -noshell \
-		-eval 'edoc:application(ibrowse, ".", []), init:stop().'
-
-$(DIALYZER_PLT):
-	@echo Creating dialyzer plt file: $(DIALYZER_PLT)
-	@echo This may take a minute or two...
-	@echo
-	dialyzer --output_plt $(DIALYZER_PLT) --build_plt \
-	   --apps $(DIALYZER_APPS)
-
-dialyzer: $(DIALYZER_PLT)
-	@echo Running dialyzer...
-	@echo
-	dialyzer --fullpath --plt $(DIALYZER_PLT) -Wrace_conditions -Wunmatched_returns -Werror_handling -r ./ebin
+	$(REBAR) edoc
+
+dialyzer:
+	$(REBAR) dialyzer
+
+
+install: compile
+	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
+	cp -r _build/lib/default/ibrowse/ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
+
+.PHONY: test docs
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1439ab01/doc/ibrowse.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse.html b/doc/ibrowse.html
index 1594d74..e7c5afd 100644
--- a/doc/ibrowse.html
+++ b/doc/ibrowse.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Module ibrowse</title>
 <link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
 </head>
@@ -10,9 +11,8 @@
 
 <h1>Module ibrowse</h1>
 <ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The ibrowse application implements an HTTP 1.1 client in erlang.
-<p>Copyright \ufffd 2005-2010 Chandrashekhar Mullaparthi</p>
+<p>Copyright � 2005-2014 Chandrashekhar Mullaparthi</p>
 
-<p><b>Version:</b> 2.1.2</p>
 <p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
 <p><b>Authors:</b> Chandrashekhar Mullaparthi (<a href="mailto:chandrashekhar dot mullaparthi at gmail dot com"><tt>chandrashekhar dot mullaparthi at gmail dot com</tt></a>).</p>
 
@@ -61,10 +61,13 @@ send_req/4, send_req/5, send_req/6.</p>
   </code>
  
 <h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all_trace_off-0">all_trace_off/0</a></td><td>Turn Off ALL tracing.</td></tr>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_config-1">add_config/1</a></td><td>Add additional configuration elements at runtime.</td></tr>
+<tr><td valign="top"><a href="#all_trace_off-0">all_trace_off/0</a></td><td>Turn Off ALL tracing.</td></tr>
 <tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
 <tr><td valign="top"><a href="#get_config_value-1">get_config_value/1</a></td><td>Internal export.</td></tr>
 <tr><td valign="top"><a href="#get_config_value-2">get_config_value/2</a></td><td>Internal export.</td></tr>
+<tr><td valign="top"><a href="#get_metrics-0">get_metrics/0</a></td><td></td></tr>
+<tr><td valign="top"><a href="#get_metrics-2">get_metrics/2</a></td><td></td></tr>
 <tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
 <tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
 <tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
@@ -85,19 +88,19 @@ send_req/4, send_req/5, send_req/6.</p>
 <tr><td valign="top"><a href="#send_req_direct-7">send_req_direct/7</a></td><td>Same as send_req/6 except that the first argument is the PID
   returned by spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr>
 <tr><td valign="top"><a href="#set_dest-3">set_dest/3</a></td><td>Deprecated.</td></tr>
+<tr><td valign="top"><a href="#set_max_attempts-3">set_max_attempts/3</a></td><td>Set the maximum attempts for each connection to a specific Host:Port.</td></tr>
 <tr><td valign="top"><a href="#set_max_pipeline_size-3">set_max_pipeline_size/3</a></td><td>Set the maximum pipeline size for each connection to a specific Host:Port.</td></tr>
 <tr><td valign="top"><a href="#set_max_sessions-3">set_max_sessions/3</a></td><td>Set the maximum number of connections allowed to a specific Host:Port.</td></tr>
 <tr><td valign="top"><a href="#show_dest_status-0">show_dest_status/0</a></td><td>Shows some internal information about load balancing.</td></tr>
+<tr><td valign="top"><a href="#show_dest_status-1">show_dest_status/1</a></td><td></td></tr>
 <tr><td valign="top"><a href="#show_dest_status-2">show_dest_status/2</a></td><td>Shows some internal information about load balancing to a
   specified Host:Port.</td></tr>
 <tr><td valign="top"><a href="#spawn_link_worker_process-1">spawn_link_worker_process/1</a></td><td>Same as spawn_worker_process/1 except the the calling process
   is linked to the worker process which is spawned.</td></tr>
-<tr><td valign="top"><a href="#spawn_link_worker_process-2">spawn_link_worker_process/2</a></td><td>Same as spawn_worker_process/2 except the the calling process
-  is linked to the worker process which is spawned.</td></tr>
+<tr><td valign="top"><a href="#spawn_link_worker_process-2">spawn_link_worker_process/2</a></td><td>Same as spawn_link_worker_process/1 except with Erlang process options.</td></tr>
 <tr><td valign="top"><a href="#spawn_worker_process-1">spawn_worker_process/1</a></td><td>Creates a HTTP client process to the specified Host:Port which
   is not part of the load balancing pool.</td></tr>
-<tr><td valign="top"><a href="#spawn_worker_process-2">spawn_worker_process/2</a></td><td>Same as spawn_worker_process/1 but takes as input a Host and Port
-  instead of a URL.</td></tr>
+<tr><td valign="top"><a href="#spawn_worker_process-2">spawn_worker_process/2</a></td><td>Same as spawn_worker_process/1 except with Erlang process options.</td></tr>
 <tr><td valign="top"><a href="#start-0">start/0</a></td><td>Starts the ibrowse process without linking.</td></tr>
 <tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the ibrowse process linked to the calling process.</td></tr>
 <tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stop the ibrowse process.</td></tr>
@@ -118,9 +121,14 @@ send_req/4, send_req/5, send_req/6.</p>
 
 <h2><a name="functions">Function Details</a></h2>
 
+<h3 class="function"><a name="add_config-1">add_config/1</a></h3>
+<div class="spec">
+<p><tt>add_config(Terms) -&gt; any()</tt></p>
+</div><p>Add additional configuration elements at runtime.</p>
+
 <h3 class="function"><a name="all_trace_off-0">all_trace_off/0</a></h3>
 <div class="spec">
-<p><tt>all_trace_off() -&gt; ok</tt></p>
+<p><tt>all_trace_off() -&gt; ok</tt><br></p>
 </div><p>Turn Off ALL tracing</p>
 
 <h3 class="function"><a name="code_change-3">code_change/3</a></h3>
@@ -138,6 +146,16 @@ send_req/4, send_req/5, send_req/6.</p>
 <p><tt>get_config_value(Key, DefVal) -&gt; any()</tt></p>
 </div><p>Internal export</p>
 
+<h3 class="function"><a name="get_metrics-0">get_metrics/0</a></h3>
+<div class="spec">
+<p><tt>get_metrics() -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="get_metrics-2">get_metrics/2</a></h3>
+<div class="spec">
+<p><tt>get_metrics(Host, Port) -&gt; any()</tt></p>
+</div>
+
 <h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
 <div class="spec">
 <p><tt>handle_call(Request, From, State) -&gt; any()</tt></p>
@@ -168,35 +186,20 @@ send_req/4, send_req/5, send_req/6.</p>
 
 <h3 class="function"><a name="rescan_config-1">rescan_config/1</a></h3>
 <div class="spec">
-<p><tt>rescan_config(File) -&gt; any()</tt></p>
+<p><tt>rescan_config(Terms) -&gt; any()</tt></p>
 </div>
 
 <h3 class="function"><a name="send_req-3">send_req/3</a></h3>
 <div class="spec">
 <p><tt>send_req(Url::string(), Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>) -&gt; <a href="#type-response">response()</a></tt>
-<ul class="definitions"><li><tt><a name="type-headerList">headerList()</a> = [{<a href="#type-header">header()</a>, <a href="#type-value">value()</a>}]</tt></li>
-<li><tt><a name="type-header">header()</a> = atom() | string()</tt></li>
-<li><tt><a name="type-value">value()</a> = term()</tt></li>
-<li><tt><a name="type-method">method()</a> = get | post | head | options | put | delete | trace | mkcol | propfind | proppatch | lock | unlock | move | copy</tt></li>
-<li><tt>Status = string()</tt></li>
-<li><tt>ResponseHeaders = [<a href="#type-respHeader">respHeader()</a>]</tt></li>
-<li><tt><a name="type-respHeader">respHeader()</a> = {<a href="#type-headerName">headerName()</a>, <a href="#type-headerValue">headerValue()</a>}</tt></li>
-<li><tt><a name="type-headerName">headerName()</a> = string()</tt></li>
-<li><tt><a name="type-headerValue">headerValue()</a> = string()</tt></li>
-<li><tt><a name="type-response">response()</a> = {ok, Status, ResponseHeaders, ResponseBody} | {ibrowse_req_id, <a href="#type-req_id">req_id()</a>} | {error, Reason}</tt></li>
-<li><tt><a name="type-req_id">req_id()</a> = term()</tt></li>
-<li><tt>ResponseBody = string() | {file, Filename}</tt></li>
-<li><tt>Reason = term()</tt></li>
-</ul></p>
+<ul class="definitions"><li><tt><a name="type-headerList">headerList()</a> = [{<a href="#type-header">header()</a>, <a href="#type-value">value()</a>}]</tt></li><li><tt><a name="type-header">header()</a> = atom() | string() | binary()</tt></li><li><tt><a name="type-value">value()</a> = term()</tt></li><li><tt><a name="type-method">method()</a> = get | post | head | options | put | delete | trace | mkcol | propfind | proppatch | lock | unlock | move | copy</tt></li><li><tt>Status = string()</tt></li><li><tt>ResponseHeaders = [<a href="#type-respHeader">respHeader()</a>]</tt></li><li><tt><a name="type-respHeader">respHeader()</a> = {<a href="#type-headerName">headerName()</a>, <a href="#type-headerValue">headerValue()</a>}</tt></li><li><tt><a name="type-headerName">headerName()</a> = string()</tt></li><li><tt><a name="type-headerValue">headerValue()</a> = string()</tt></li><li><tt><a name="type-response">response()</a> = {ok, Status, ResponseHeaders, ResponseBody} | {ibrowse_req_id, <
 a href="#type-req_id">req_id()</a>} | {error, Reason}</tt></li><li><tt><a name="type-req_id">req_id()</a> = term()</tt></li><li><tt>ResponseBody = string() | {file, Filename}</tt></li><li><tt>Reason = term()</tt></li></ul></p>
 </div><p>This is the basic function to send a HTTP request.
   The Status return value indicates the HTTP status code returned by the webserver</p>
 
 <h3 class="function"><a name="send_req-4">send_req/4</a></h3>
 <div class="spec">
 <p><tt>send_req(Url, Headers, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>) -&gt; <a href="#type-response">response()</a></tt>
-<ul class="definitions"><li><tt><a name="type-body">body()</a> = [] | string() | binary() | <a href="#type-fun_arity_0">fun_arity_0()</a> | {<a href="#type-fun_arity_1">fun_arity_1()</a>, <a href="#type-initial_state">initial_state()</a>}</tt></li>
-<li><tt><a name="type-initial_state">initial_state()</a> = term()</tt></li>
-</ul></p>
+<ul class="definitions"><li><tt><a name="type-body">body()</a> = [] | string() | binary() | <a href="#type-fun_arity_0">fun_arity_0()</a> | {<a href="#type-fun_arity_1">fun_arity_1()</a>, <a href="#type-initial_state">initial_state()</a>}</tt></li><li><tt><a name="type-initial_state">initial_state()</a> = term()</tt></li></ul></p>
 </div><p>Same as send_req/3.
   If a list is specified for the body it has to be a flat list. The body can also be a fun/0 or a fun/1. <br>
   If fun/0, the connection handling process will repeatdely call the fun until it returns an error or eof. <pre>Fun() = {ok, Data} | eof</pre><br>
@@ -205,106 +208,13 @@ send_req/4, send_req/5, send_req/6.</p>
 <h3 class="function"><a name="send_req-5">send_req/5</a></h3>
 <div class="spec">
 <p><tt>send_req(Url::string(), Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>, Options::<a href="#type-optionList">optionList()</a>) -&gt; <a href="#type-response">response()</a></tt>
-<ul class="definitions"><li><tt><a name="type-optionList">optionList()</a> = [<a href="#type-option">option()</a>]</tt></li>
-<li><tt><a name="type-option">option()</a> = {max_sessions, integer()} | {response_format, <a href="#type-response_format">response_format()</a>} | {stream_chunk_size, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>} | {is_ssl, <a href="#type-boolean">boolean()</a>} | {ssl_options, [SSLOpt]} | {pool_name, atom()} | {proxy_host, string()} | {proxy_port, integer()} | {proxy_user, string()} | {proxy_password, string()} | {use_absolute_uri, <a href="#type-boolean">boolean()</a>} | {basic_auth, {<a href="#type-username">username()</a>, <a href="#type-password">password()</a>}} | {cookie, string()} | {content_length, integer()} | {content_type, string()} | {save_response_to_file, <a href="#type-srtf">srtf()</a>} | {stream_to, <a href="#type-stream_to">stream_to()</a>} | {http_vsn, {MajorVsn, MinorVsn}} | {host_header, string()} | {inactivity_timeout, integer()} | {connect_timeout, integer()} | {socket_options, Sock_opts} | {transfer_encoding, {c
 hunked, ChunkSize}} | {headers_as_is, <a href="#type-boolean">boolean()</a>} | {give_raw_headers, <a href="#type-boolean">boolean()</a>} | {preserve_chunked_encoding, <a href="#type-boolean">boolean()</a>}</tt></li>
-<li><tt><a name="type-stream_to">stream_to()</a> = <a href="#type-process">process()</a> | {<a href="#type-process">process()</a>, once}</tt></li>
-<li><tt><a name="type-process">process()</a> = pid() | atom()</tt></li>
-<li><tt><a name="type-username">username()</a> = string()</tt></li>
-<li><tt><a name="type-password">password()</a> = string()</tt></li>
-<li><tt>SSLOpt = term()</tt></li>
-<li><tt>Sock_opts = [Sock_opt]</tt></li>
-<li><tt>Sock_opt = term()</tt></li>
-<li><tt>ChunkSize = integer()</tt></li>
-<li><tt><a name="type-srtf">srtf()</a> = <a href="#type-boolean">boolean()</a> | <a href="#type-filename">filename()</a></tt></li>
-<li><tt><a name="type-filename">filename()</a> = string()</tt></li>
-<li><tt><a name="type-response_format">response_format()</a> = list | binary</tt></li>
-</ul></p>
-</div><p>Same as send_req/4.
-  For a description of SSL Options, look in the <a href="http://www.erlang.org/doc/apps/ssl/index.html">ssl</a> manpage. If the
-  HTTP Version to use is not specified, the default is 1.1.
-  <br>
-  <ul>
-  <li>The <code>host_header</code> option is useful in the case where ibrowse is
-  connecting to a component such as <a href="http://www.stunnel.org">stunnel</a> which then sets up a
-  secure connection to a webserver. In this case, the URL supplied to
-  ibrowse must have the stunnel host/port details, but that won't
-  make sense to the destination webserver. This option can then be
-  used to specify what should go in the <code>Host</code> header in
-  the request.</li>
-  <li>The <code>stream_to</code> option can be used to have the HTTP
-  response streamed to a process as messages as data arrives on the
-  socket. If the calling process wishes to control the rate at which
-  data is received from the server, the option <code>{stream_to,
-  {process(), once}}</code> can be specified. The calling process
-  will have to invoke <code>ibrowse:stream_next(Request_id)</code> to
-  receive the next packet.</li>
- 
-  <li>When both the options <code>save_response_to_file</code> and <code>stream_to</code>
-  are specified, the former takes precedence.</li>
- 
-  <li>For the <code>save_response_to_file</code> option, the response body is saved to
-  file only if the status code is in the 200-299 range. If not, the response body is returned
-  as a string.</li>
-  <li>Whenever an error occurs in the processing of a request, ibrowse will return as much
-  information as it has, such as HTTP Status Code and HTTP Headers. When this happens, the response
-  is of the form <code>{error, {Reason, {stat_code, StatusCode}, HTTP_headers}}</code></li>
- 
-  <li><p>The <code>inactivity_timeout</code> option is useful when  
-dealing with large response bodies and/or slow links. In these  
-cases, it might be hard to estimate how long a request will take to  
-complete. In such cases, the client might want to timeout if no  
-data has been received on the link for a certain time interval.</p>
- 
-  This value is also used to close connections which are not in use for
-  the specified timeout value.
-  </li>
- 
-  <li>
-  The <code>connect_timeout</code> option is to specify how long the
-  client process should wait for connection establishment. This is
-  useful in scenarios where connections to servers are usually setup
-  very fast, but responses might take much longer compared to
-  connection setup. In such cases, it is better for the calling
-  process to timeout faster if there is a problem (DNS lookup
-  delays/failures, network routing issues, etc). The total timeout
-  value specified for the request will enforced. To illustrate using
-  an example:
-  <code>
-  ibrowse:send_req("http://www.example.com/cgi-bin/request", [], get, [], [{connect_timeout, 100}], 1000).
-  </code>
-  In the above invocation, if the connection isn't established within
-  100 milliseconds, the request will fail with
-  <code>{error, conn_failed}</code>.<br>
-  If connection setup succeeds, the total time allowed for the
-  request to complete will be 1000 milliseconds minus the time taken
-  for connection setup.
-  </li>
- 
-  <li> The <code>socket_options</code> option can be used to set
-  specific options on the socket. The <code>{active, true | false | once}</code>
-  and <code>{packet_type, Packet_type}</code> will be filtered out by ibrowse.  </li>
- 
-  <li> The <code>headers_as_is</code> option is to enable the caller
-  to send headers exactly as specified in the request without ibrowse
-  adding some of its own. Required for some picky servers apparently.  </li>
- 
-  <li>The <code>give_raw_headers</code> option is to enable the
-  caller to get access to the raw status line and raw unparsed
-  headers. Not quite sure why someone would want this, but one of my
-  users asked for it, so here it is. </li>
- 
-  <li> The <code>preserve_chunked_encoding</code> option enables the caller
-  to receive the raw data stream when the Transfer-Encoding of the server
-  response is Chunked.
-  </li>
-  </ul>
- </p>
+<ul class="definitions"><li><tt><a name="type-optionList">optionList()</a> = [<a href="#type-option">option()</a>]</tt></li><li><tt><a name="type-option">option()</a> = {max_sessions, integer()} | {response_format, <a href="#type-response_format">response_format()</a>} | {stream_chunk_size, integer()} | {max_pipeline_size, integer()} | {trace, boolean()} | {is_ssl, boolean()} | {ssl_options, [SSLOpt]} | {pool_name, atom()} | {proxy_host, string()} | {proxy_port, integer()} | {proxy_user, string()} | {proxy_password, string()} | {use_absolute_uri, boolean()} | {basic_auth, {<a href="#type-username">username()</a>, <a href="#type-password">password()</a>}} | {cookie, string()} | {content_length, integer()} | {content_type, string()} | {save_response_to_file, <a href="#type-srtf">srtf()</a>} | {stream_to, <a href="#type-stream_to">stream_to()</a>} | {http_vsn, {MajorVsn, MinorVsn}} | {host_header, string()} | {inactivity_timeout, integer()} | {connect_timeout, integer()} | {socket_opti
 ons, Sock_opts} | {transfer_encoding, {chunked, ChunkSize}} | {headers_as_is, boolean()} | {give_raw_headers, boolean()} | {preserve_chunked_encoding, boolean()} | {workaround, head_response_with_body} | {worker_process_options, list()} | {return_raw_request, true} | {max_attempts, integer()}</tt></li><li><tt><a name="type-stream_to">stream_to()</a> = <a href="#type-process">process()</a> | {<a href="#type-process">process()</a>, once}</tt></li><li><tt><a name="type-process">process()</a> = pid() | atom()</tt></li><li><tt><a name="type-username">username()</a> = string()</tt></li><li><tt><a name="type-password">password()</a> = string()</tt></li><li><tt>SSLOpt = term()</tt></li><li><tt>Sock_opts = [Sock_opt]</tt></li><li><tt>Sock_opt = term()</tt></li><li><tt>ChunkSize = integer()</tt></li><li><tt><a name="type-srtf">srtf()</a> = boolean() | <a href="#type-filename">filename()</a> | {append, <a href="#type-filename">filename()</a>}</tt></li><li><tt><a name="type-filename">filename()
 </a> = string()</tt></li><li><tt><a name="type-response_format">response_format()</a> = list | binary</tt></li></ul></p>
+</div><p>Same as send_req/4.</p>
 
 <h3 class="function"><a name="send_req-6">send_req/6</a></h3>
 <div class="spec">
 <p><tt>send_req(Url, Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>, Options::<a href="#type-optionList">optionList()</a>, Timeout) -&gt; <a href="#type-response">response()</a></tt>
-<ul class="definitions"><li><tt>Timeout = integer() | infinity</tt></li>
-</ul></p>
+<ul class="definitions"><li><tt>Timeout = integer() | infinity</tt></li></ul></p>
 </div><p>Same as send_req/5.
   All timeout values are in milliseconds.</p>
 
@@ -338,14 +248,19 @@ data has been received on the link for a certain time interval.</p>
 </div><p>Deprecated. Use set_max_sessions/3 and set_max_pipeline_size/3
   for achieving the same effect.</p>
 
+<h3 class="function"><a name="set_max_attempts-3">set_max_attempts/3</a></h3>
+<div class="spec">
+<p><tt>set_max_attempts(Host::string(), Port::integer(), Max::integer()) -&gt; ok</tt><br></p>
+</div><p>Set the maximum attempts for each connection to a specific Host:Port.</p>
+
 <h3 class="function"><a name="set_max_pipeline_size-3">set_max_pipeline_size/3</a></h3>
 <div class="spec">
-<p><tt>set_max_pipeline_size(Host::string(), Port::integer(), Max::integer()) -&gt; ok</tt></p>
+<p><tt>set_max_pipeline_size(Host::string(), Port::integer(), Max::integer()) -&gt; ok</tt><br></p>
 </div><p>Set the maximum pipeline size for each connection to a specific Host:Port.</p>
 
 <h3 class="function"><a name="set_max_sessions-3">set_max_sessions/3</a></h3>
 <div class="spec">
-<p><tt>set_max_sessions(Host::string(), Port::integer(), Max::integer()) -&gt; ok</tt></p>
+<p><tt>set_max_sessions(Host::string(), Port::integer(), Max::integer()) -&gt; ok</tt><br></p>
 </div><p>Set the maximum number of connections allowed to a specific Host:Port.</p>
 
 <h3 class="function"><a name="show_dest_status-0">show_dest_status/0</a></h3>
@@ -355,6 +270,11 @@ data has been received on the link for a certain time interval.</p>
   about workers spawned using spawn_worker_process/2 or
   spawn_link_worker_process/2 is not included.</p>
 
+<h3 class="function"><a name="show_dest_status-1">show_dest_status/1</a></h3>
+<div class="spec">
+<p><tt>show_dest_status(Url) -&gt; any()</tt></p>
+</div>
+
 <h3 class="function"><a name="show_dest_status-2">show_dest_status/2</a></h3>
 <div class="spec">
 <p><tt>show_dest_status(Host, Port) -&gt; any()</tt></p>
@@ -365,19 +285,18 @@ data has been received on the link for a certain time interval.</p>
 
 <h3 class="function"><a name="spawn_link_worker_process-1">spawn_link_worker_process/1</a></h3>
 <div class="spec">
-<p><tt>spawn_link_worker_process(Url::string()) -&gt; {ok, pid()}</tt></p>
+<p><tt>spawn_link_worker_process(Url::string() | {Host::string(), Port::integer()}) -&gt; {ok, pid()}</tt><br></p>
 </div><p>Same as spawn_worker_process/1 except the the calling process
   is linked to the worker process which is spawned.</p>
 
 <h3 class="function"><a name="spawn_link_worker_process-2">spawn_link_worker_process/2</a></h3>
 <div class="spec">
-<p><tt>spawn_link_worker_process(Host::string(), Port::integer()) -&gt; {ok, pid()}</tt></p>
-</div><p>Same as spawn_worker_process/2 except the the calling process
-  is linked to the worker process which is spawned.</p>
+<p><tt>spawn_link_worker_process(Host::string(), Port::integer()) -&gt; {ok, pid()}</tt><br></p>
+</div><p>Same as spawn_link_worker_process/1 except with Erlang process options.</p>
 
 <h3 class="function"><a name="spawn_worker_process-1">spawn_worker_process/1</a></h3>
 <div class="spec">
-<p><tt>spawn_worker_process(Url::string()) -&gt; {ok, pid()}</tt></p>
+<p><tt>spawn_worker_process(Url::string() | {Host::string(), Port::integer()}) -&gt; {ok, pid()}</tt><br></p>
 </div><p>Creates a HTTP client process to the specified Host:Port which
   is not part of the load balancing pool. This is useful in cases
   where some requests to a webserver might take a long time whereas
@@ -388,14 +307,12 @@ data has been received on the link for a certain time interval.</p>
   is setup. The connection attempt is made only when the first
   request is sent via any of the send_req_direct/4,5,6,7 functions.<br>
   <b>Note:</b> It is the responsibility of the calling process to control
-  pipeline size on such connections.
- </p>
+  pipeline size on such connections.</p>
 
 <h3 class="function"><a name="spawn_worker_process-2">spawn_worker_process/2</a></h3>
 <div class="spec">
-<p><tt>spawn_worker_process(Host::string(), Port::integer()) -&gt; {ok, pid()}</tt></p>
-</div><p>Same as spawn_worker_process/1 but takes as input a Host and Port
-  instead of a URL.</p>
+<p><tt>spawn_worker_process(Host::string(), Port::integer()) -&gt; {ok, pid()}</tt><br></p>
+</div><p>Same as spawn_worker_process/1 except with Erlang process options.</p>
 
 <h3 class="function"><a name="start-0">start/0</a></h3>
 <div class="spec">
@@ -404,7 +321,7 @@ data has been received on the link for a certain time interval.</p>
 
 <h3 class="function"><a name="start_link-0">start_link/0</a></h3>
 <div class="spec">
-<p><tt>start_link() -&gt; {ok, pid()}</tt></p>
+<p><tt>start_link() -&gt; {ok, pid()}</tt><br></p>
 </div><p>Starts the ibrowse process linked to the calling process. Usually invoked by the supervisor ibrowse_sup</p>
 
 <h3 class="function"><a name="stop-0">stop/0</a></h3>
@@ -414,14 +331,14 @@ data has been received on the link for a certain time interval.</p>
 
 <h3 class="function"><a name="stop_worker_process-1">stop_worker_process/1</a></h3>
 <div class="spec">
-<p><tt>stop_worker_process(Conn_pid::pid()) -&gt; ok</tt></p>
+<p><tt>stop_worker_process(Conn_pid::pid()) -&gt; ok</tt><br></p>
 </div><p>Terminate a worker process spawned using
   spawn_worker_process/2 or spawn_link_worker_process/2. Requests in
   progress will get the error response <pre>{error, closing_on_request}</pre></p>
 
 <h3 class="function"><a name="stream_close-1">stream_close/1</a></h3>
 <div class="spec">
-<p><tt>stream_close(Req_id::<a href="#type-req_id">req_id()</a>) -&gt; ok | {error, unknown_req_id}</tt></p>
+<p><tt>stream_close(Req_id::<a href="#type-req_id">req_id()</a>) -&gt; ok | {error, unknown_req_id}</tt><br></p>
 </div><p>Tell ibrowse to close the connection associated with the
   specified stream.  Should be used in conjunction with the
   <code>stream_to</code> option. Note that all requests in progress on
@@ -430,7 +347,7 @@ data has been received on the link for a certain time interval.</p>
 
 <h3 class="function"><a name="stream_next-1">stream_next/1</a></h3>
 <div class="spec">
-<p><tt>stream_next(Req_id::<a href="#type-req_id">req_id()</a>) -&gt; ok | {error, unknown_req_id}</tt></p>
+<p><tt>stream_next(Req_id::<a href="#type-req_id">req_id()</a>) -&gt; ok | {error, unknown_req_id}</tt><br></p>
 </div><p>Tell ibrowse to stream the next chunk of data to the
   caller. Should be used in conjunction with the
   <code>stream_to</code> option</p>
@@ -447,7 +364,7 @@ data has been received on the link for a certain time interval.</p>
 
 <h3 class="function"><a name="trace_off-2">trace_off/2</a></h3>
 <div class="spec">
-<p><tt>trace_off(Host, Port) -&gt; ok</tt></p>
+<p><tt>trace_off(Host, Port) -&gt; ok</tt><br></p>
 </div><p>Turn tracing OFF for all connections to the specified HTTP
   server.</p>
 
@@ -459,14 +376,12 @@ data has been received on the link for a certain time interval.</p>
 <h3 class="function"><a name="trace_on-2">trace_on/2</a></h3>
 <div class="spec">
 <p><tt>trace_on(Host, Port) -&gt; ok</tt>
-<ul class="definitions"><li><tt>Host = string()</tt></li>
-<li><tt>Port = integer()</tt></li>
-</ul></p>
+<ul class="definitions"><li><tt>Host = string()</tt></li><li><tt>Port = integer()</tt></li></ul></p>
 </div><p>Turn tracing on for all connections to the specified HTTP
   server. Host is whatever is specified as the domain name in the URL</p>
 <hr>
 
 <div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Nov 10 2010, 06:04:33.</i></p>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1439ab01/doc/ibrowse_lib.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_lib.html b/doc/ibrowse_lib.html
index 7a00d4f..4411692 100644
--- a/doc/ibrowse_lib.html
+++ b/doc/ibrowse_lib.html
@@ -1,67 +1,114 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Module ibrowse_lib</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
 </head>
 <body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
 
 <h1>Module ibrowse_lib</h1>
-Module with a few useful functions.
-<ul><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Module with a few useful functions.
+
 
 <h2><a name="description">Description</a></h2>Module with a few useful functions
 <h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1"><tr><td valign="top"><a href="#dec2hex-2">dec2hex/2</a></td><td>dec2hex taken from gtk.erl in std dist
-  M = integer() -- number of hex digits required
-  N = integer() -- the number to represent as hex.</td></tr>
-<tr><td valign="top"><a href="#decode_base64-1">decode_base64/1</a></td><td>Implements the base64 decoding algorithm.</td></tr>
-<tr><td valign="top"><a href="#decode_rfc822_date-1">decode_rfc822_date/1</a></td><td/></tr>
-<tr><td valign="top"><a href="#drv_ue-1">drv_ue/1</a></td><td/></tr>
-<tr><td valign="top"><a href="#drv_ue-2">drv_ue/2</a></td><td/></tr>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#decode_base64-1">decode_base64/1</a></td><td>Implements the base64 decoding algorithm.</td></tr>
+<tr><td valign="top"><a href="#decode_rfc822_date-1">decode_rfc822_date/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#do_trace-2">do_trace/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#do_trace-3">do_trace/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#do_trace-3">do_trace/3</a></td><td></td></tr>
 <tr><td valign="top"><a href="#encode_base64-1">encode_base64/1</a></td><td>Implements the base64 encoding algorithm.</td></tr>
+<tr><td valign="top"><a href="#get_trace_status-2">get_trace_status/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#get_value-3">get_value/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#parse_url-1">parse_url/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#printable_date-0">printable_date/0</a></td><td></td></tr>
+<tr><td valign="top"><a href="#printable_date-1">printable_date/1</a></td><td></td></tr>
 <tr><td valign="top"><a href="#status_code-1">status_code/1</a></td><td>Given a status code, returns an atom describing the status code.</td></tr>
 <tr><td valign="top"><a href="#url_encode-1">url_encode/1</a></td><td>URL-encodes a string based on RFC 1738.</td></tr>
 </table>
 
 <h2><a name="functions">Function Details</a></h2>
 
-<h3><a name="dec2hex-2">dec2hex/2</a></h3>
-<p><tt>dec2hex(M::integer(), N::integer()) -&gt; string()</tt></p>
-<p>dec2hex taken from gtk.erl in std dist
-  M = integer() -- number of hex digits required
-  N = integer() -- the number to represent as hex</p>
+<h3 class="function"><a name="decode_base64-1">decode_base64/1</a></h3>
+<div class="spec">
+<p><tt>decode_base64(List::In) -&gt; Out | <a href="#type-exit">exit</a>({error, invalid_input})</tt>
+<ul class="definitions"><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
+</div><p>Implements the base64 decoding algorithm. The output data type matches in the input data type.</p>
 
-<h3><a name="decode_base64-1">decode_base64/1</a></h3>
-<p><tt>decode_base64(List::In) -&gt; Out | <a href="#type-exit">exit({error, invalid_input})</a></tt>
-<ul><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
-<p>Implements the base64 decoding algorithm. The output data type matches in the input data type.</p>
+<h3 class="function"><a name="decode_rfc822_date-1">decode_rfc822_date/1</a></h3>
+<div class="spec">
+<p><tt>decode_rfc822_date(String) -&gt; any()</tt></p>
+</div>
 
-<h3><a name="decode_rfc822_date-1">decode_rfc822_date/1</a></h3>
-<tt>decode_rfc822_date(String) -&gt; term()
-</tt>
+<h3 class="function"><a name="do_trace-2">do_trace/2</a></h3>
+<div class="spec">
+<p><tt>do_trace(Fmt, Args) -&gt; any()</tt></p>
+</div>
 
-<h3><a name="drv_ue-1">drv_ue/1</a></h3>
-<tt>drv_ue(Str) -&gt; term()
-</tt>
+<h3 class="function"><a name="do_trace-3">do_trace/3</a></h3>
+<div class="spec">
+<p><tt>do_trace(X1, Fmt, Args) -&gt; any()</tt></p>
+</div>
 
-<h3><a name="drv_ue-2">drv_ue/2</a></h3>
-<tt>drv_ue(Str, Port) -&gt; term()
-</tt>
+<h3 class="function"><a name="do_trace-3">do_trace/3</a></h3>
+<div class="spec">
+<p><tt>do_trace(X1, Fmt, Args) -&gt; any()</tt></p>
+</div>
 
-<h3><a name="encode_base64-1">encode_base64/1</a></h3>
+<h3 class="function"><a name="encode_base64-1">encode_base64/1</a></h3>
+<div class="spec">
 <p><tt>encode_base64(List::In) -&gt; Out</tt>
-<ul><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
-<p>Implements the base64 encoding algorithm. The output data type matches in the input data type.</p>
+<ul class="definitions"><li><tt>In = string() | binary()</tt></li><li><tt>Out = string() | binary()</tt></li></ul></p>
+</div><p>Implements the base64 encoding algorithm. The output data type matches in the input data type.</p>
+
+<h3 class="function"><a name="get_trace_status-2">get_trace_status/2</a></h3>
+<div class="spec">
+<p><tt>get_trace_status(Host, Port) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="get_value-2">get_value/2</a></h3>
+<div class="spec">
+<p><tt>get_value(Tag, TVL) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="get_value-3">get_value/3</a></h3>
+<div class="spec">
+<p><tt>get_value(Tag, TVL, DefVal) -&gt; any()</tt></p>
+</div>
 
-<h3><a name="status_code-1">status_code/1</a></h3>
+<h3 class="function"><a name="parse_url-1">parse_url/1</a></h3>
+<div class="spec">
+<p><tt>parse_url(Url) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="printable_date-0">printable_date/0</a></h3>
+<div class="spec">
+<p><tt>printable_date() -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="printable_date-1">printable_date/1</a></h3>
+<div class="spec">
+<p><tt>printable_date(Now) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="status_code-1">status_code/1</a></h3>
+<div class="spec">
 <p><tt>status_code(StatusCode::<a href="#type-status_code">status_code()</a>) -&gt; StatusDescription</tt>
-<ul><li><tt><a name="type-status_code">status_code()</a> = string() | integer()</tt></li><li><tt>StatusDescription = atom()</tt></li></ul></p>
-<p>Given a status code, returns an atom describing the status code.</p>
+<ul class="definitions"><li><tt><a name="type-status_code">status_code()</a> = string() | integer()</tt></li><li><tt>StatusDescription = atom()</tt></li></ul></p>
+</div><p>Given a status code, returns an atom describing the status code.</p>
 
-<h3><a name="url_encode-1">url_encode/1</a></h3>
+<h3 class="function"><a name="url_encode-1">url_encode/1</a></h3>
+<div class="spec">
 <p><tt>url_encode(Str) -&gt; UrlEncodedStr</tt>
-<ul><li><tt>Str = string()</tt></li><li><tt>UrlEncodedStr = string()</tt></li></ul></p>
-<p>URL-encodes a string based on RFC 1738. Returns a flat list.</p>
+<ul class="definitions"><li><tt>Str = string()</tt></li><li><tt>UrlEncodedStr = string()</tt></li></ul></p>
+</div><p>URL-encodes a string based on RFC 1738. Returns a flat list.</p>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1439ab01/rebar.lock
----------------------------------------------------------------------
diff --git a/rebar.lock b/rebar.lock
new file mode 100644
index 0000000..57afcca
--- /dev/null
+++ b/rebar.lock
@@ -0,0 +1 @@
+[].


[13/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge pull request #125 from marcelog/marcelog_max_attempts_config

Add max_attempts option

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

Branch: refs/heads/upstream
Commit: 200b7eb5f16e54c8680a3df3f4e627f19c9d8eea
Parents: e18ea91 418f6ce
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon May 11 19:45:12 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon May 11 19:45:12 2015 +0100

----------------------------------------------------------------------
 src/ibrowse.erl | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)
----------------------------------------------------------------------



[25/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Removed update to author list. Names are already in the CONTRIBUTORS file. This is a consistent approach to the way contributions from everyone else has been handled over the years. Correct authorship has been acknowledged in the new module ibrowse_functional_tests.erl


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

Branch: refs/heads/upstream
Commit: 3c96a918ca109288c91a4c8277d0ab7b2ff2d5dc
Parents: b4ad6df
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 20:43:31 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 20:43:31 2015 +0100

----------------------------------------------------------------------
 test/ibrowse_test_server.erl | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/3c96a918/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index 7025286..90c46c4 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -1,8 +1,5 @@
 %%% File    : ibrowse_test_server.erl
 %%% Author  : Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>
-%%%           Benjamin Lee <http://github.com/benjaminplee>
-%%%           Dan Schwabe <http://github.com/dfschwabe>
-%%%           Brian Richards <http://github.com/richbria>
 %%% Description : A server to simulate various test scenarios
 %%% Created : 17 Oct 2010 by Chandrashekhar Mullaparthi <ch...@t-mobile.co.uk>
 


[05/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed matchspec miss and added retry logic w/ ets

In prior commit, missed switch of matchspec to work
with deletes, fixed here.

Added retry logic for race conditions around lb and
conn both trying to update same record at the same time.
If more than max is experienced, just let it go, things
will probably be ok.


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

Branch: refs/heads/upstream
Commit: 642c082d54777857cb8d6185ab123666e7a4520e
Parents: e4d41ec
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 17:44:05 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 17:44:05 2014 +0000

----------------------------------------------------------------------
 src/ibrowse_lb.erl | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/642c082d/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lb.erl b/src/ibrowse_lb.erl
index 3d487d4..eabba3a 100644
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@ -38,8 +38,9 @@
                 proc_state}).
 
 -define(PIPELINE_MAX, 99999).
+-define(MAX_RETRIES, 3).
 -define(KEY_MATCHSPEC_BY_PID(Pid), [{{{'_', '_', Pid}, '_'}, [], ['$_']}]).
--define(KEY_MATCHSPEC(Key), [{{Key, '_'}, [], ['$_']}]).
+-define(KEY_MATCHSPEC_BY_PID_FOR_DELETE(Pid), [{{{'_', '_', Pid}, '_'}, [], [true]}]).
 -define(KEY_MATCHSPEC_FOR_DELETE(Key), [{{Key, '_'}, [], [true]}]).
 
 -include("ibrowse.hrl").
@@ -77,22 +78,10 @@ stop(Lb_pid) ->
 
 report_connection_down(Tid) ->
     %% Don't cascade errors since Tid is really managed by other process
-    catch ets:select_delete(Tid, ?KEY_MATCHSPEC_BY_PID(self())).
+    catch ets:select_delete(Tid, ?KEY_MATCHSPEC_BY_PID_FOR_DELETE(self())).
 
 report_request_complete(Tid) ->
-    %% Don't cascade errors since Tid is really managed by other process
-    catch case ets:select(Tid, ?KEY_MATCHSPEC_BY_PID(self())) of
-        [MatchKey] ->
-            case ets:select_delete(Tid, ?KEY_MATCHSPEC_FOR_DELETE(MatchKey)) of
-                1 ->
-                    ets:insert(Tid, {decremented(MatchKey), undefined}),
-                    true;
-                _ ->
-                    false
-            end;
-        _ ->
-            false
-    end.
+    report_request_complete(Tid, ?MAX_RETRIES).
 
 %%====================================================================
 %% Server functions
@@ -223,13 +212,18 @@ code_change(_OldVsn, State, _Extra) ->
 %%% Internal functions
 %%--------------------------------------------------------------------
 find_best_connection(Tid, Max_pipeline_size) ->
+    find_best_connection(Tid, Max_pipeline_size, ?MAX_RETRIES).
+
+find_best_connection(_Tid, _Max_pipeline_size, 0) ->
+    {error, retry_later};
+find_best_connection(Tid, Max_pipeline_size, RemainingRetries) ->
     case ets:first(Tid) of
         {Size, _Timestamp, Pid} = Key when Size < Max_pipeline_size ->
             case record_request_for_connection(Tid, Key) of
                 true ->
                     {ok, Pid};
                 false ->
-                    find_best_connection(Tid, Max_pipeline_size)
+                    find_best_connection(Tid, Max_pipeline_size, RemainingRetries - 1)
             end;
         _ -> 
             {error, retry_later}
@@ -257,6 +251,24 @@ record_request_for_connection(Tid, Key) ->
             false
     end.
 
+report_request_complete(_Tid, 0) ->
+    false;
+report_request_complete(Tid, RemainingRetries) ->
+    %% Don't cascade errors since Tid is really managed by other process
+    catch case ets:select(Tid, ?KEY_MATCHSPEC_BY_PID(self())) of
+        [MatchKey] ->
+            case ets:select_delete(Tid, ?KEY_MATCHSPEC_FOR_DELETE(MatchKey)) of
+                1 ->
+                    ets:insert(Tid, {decremented(MatchKey), undefined}),
+                    true;
+                _ ->
+                    report_request_complete(Tid, RemainingRetries - 1)
+            end;
+        _ ->
+            false
+    end.
+
+
 new_key(Pid) ->
     {1, os:timestamp(), Pid}.
 


[17/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge pull request #130 from surik/otp18

Build under R18 #129

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

Branch: refs/heads/upstream
Commit: 58007c74336a02aa51c4527b32e3a17aca366fa2
Parents: 04566c7 6281603
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Thu Jun 25 22:44:24 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Thu Jun 25 22:44:24 2015 +0100

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 9 +++++++--
 src/ibrowse_lib.erl         | 2 +-
 test/ibrowse_test.erl       | 8 ++++----
 3 files changed, 12 insertions(+), 7 deletions(-)
----------------------------------------------------------------------



[28/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Version 4.2


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

Branch: refs/heads/upstream
Commit: fd81d44182507c23445ed720df8c30e2e8da9d9b
Parents: 7c4d098
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 21:14:04 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 21:14:04 2015 +0100

----------------------------------------------------------------------
 CHANGELOG           | 5 +++++
 README.md           | 2 +-
 src/ibrowse.app.src | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/fd81d441/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 0d9ee11..e7301cf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
+28-09-2015 - v4.2
+             * Merged long pending improvements to pipelining
+               https://github.com/cmullaparthi/ibrowse/pull/123
+             * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/131
+
 03-08-2015 - v4.1.2
              * R18 compatibility fix
                https://github.com/cmullaparthi/ibrowse/issues/129

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/fd81d441/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index c2dffe4..fa0305f 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.1.2
+**Current Version:** 4.2
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/fd81d441/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 65fb5a2..3baa8d0 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.1.2"},
+         {vsn, "4.2"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},


[29/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Added info for hex


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

Branch: refs/heads/upstream
Commit: 1ae07edae8c5532ba543c9a41624a6221adf6214
Parents: fd81d44
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 21:55:23 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 21:55:23 2015 +0100

----------------------------------------------------------------------
 src/ibrowse.app.src | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1ae07eda/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 3baa8d0..7e28895 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -4,4 +4,9 @@
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},
-	 {mod, {ibrowse_app, []}}]}.
+	 {mod, {ibrowse_app, []}},
+         {maintainers, ["Chandrashekhar Mullaparthi"]},
+         {licenses, ["GPLv2", "BSD"]},
+         {links, ["https://github.com/cmullaparthi/ibrowse"]}
+        ]
+}.


[42/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fix for #139 - file not being saved to disk when server does not respond with content-length


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

Branch: refs/heads/upstream
Commit: 411468d7490c4a66afb884cb59a6142c438ee8d0
Parents: a1be536
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Jan 18 22:47:48 2016 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Jan 18 22:47:48 2016 +0000

----------------------------------------------------------------------
 test/Makefile                     |  10 ++
 test/ibrowse_functional_tests.erl | 174 ---------------------------------
 test/ibrowse_tests.erl            | 174 +++++++++++++++++++++++++++++++++
 3 files changed, 184 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/Makefile
----------------------------------------------------------------------
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..c7d6f42
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,10 @@
+REBAR ?= $(shell which rebar3)
+
+all: compile
+	erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test local_unit_tests -s erlang halt
+
+compile:
+	erl -pa ../../ibrowse/ebin -make
+
+clean:
+	$(REBAR) clean

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
deleted file mode 100644
index 3517011..0000000
--- a/test/ibrowse_functional_tests.erl
+++ /dev/null
@@ -1,174 +0,0 @@
-%%% File    : ibrowse_functional_tests.erl
-%%% Authors : Benjamin Lee <http://github.com/benjaminplee>
-%%%           Dan Schwabe <http://github.com/dfschwabe>
-%%%           Brian Richards <http://github.com/richbria>
-%%% Description : Functional tests of the ibrowse library using a live test HTTP server
-%%% Created : 18 November 2014 by Benjamin Lee <ya...@gmail.com>
-
--module(ibrowse_functional_tests).
-
--include_lib("eunit/include/eunit.hrl").
--define(PER_TEST_TIMEOUT_SEC, 60).
--define(TIMEDTEST(Desc, Fun), {Desc, {timeout, ?PER_TEST_TIMEOUT_SEC, fun Fun/0}}).
-
--define(SERVER_PORT, 8181).
--define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)).
--define(SHORT_TIMEOUT_MS, 5000).
--define(LONG_TIMEOUT_MS, 30000).
--define(PAUSE_FOR_CONNECTIONS_MS, 2000).
-
--compile(export_all).
-
-setup() ->
-    application:start(crypto),
-    application:start(public_key),
-    application:start(ssl),
-    ibrowse_test_server:start_server(?SERVER_PORT, tcp),
-    ibrowse:start(),
-    ok.
-
-teardown(_) ->
-    ibrowse:stop(),
-    ibrowse_test_server:stop_server(?SERVER_PORT),
-    ok.
-
-running_server_fixture_test_() ->
-    {foreach,
-     fun setup/0,
-     fun teardown/1,
-     [
-        ?TIMEDTEST("Simple request can be honored", simple_request),
-        ?TIMEDTEST("Slow server causes timeout", slow_server_timeout),
-        ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
-        ?TIMEDTEST("Pipelines refill", pipeline_refill),
-        ?TIMEDTEST("Timeout closes pipe", closing_pipes),
-        ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
-        ?TIMEDTEST("Pipeline too small signals retries", small_pipeline),
-        ?TIMEDTEST("Dest status can be gathered", status)
-     ]
-    }.
-
-simple_request() ->
-    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [])).
-
-slow_server_timeout() ->
-    ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)).
-
-pipeline_depth() ->
-    MaxSessions = 2,
-    MaxPipeline = 2,
-    RequestsSent = 2,
-    EmptyPipelineDepth = 0,
-
-    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
-
-    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
-    times(RequestsSent, fun() -> spawn_link(Fun) end),
-
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
-
-    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
-    ?assertEqual(MaxSessions, length(Counts)),
-    ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts).
-
-pipeline_refill() ->
-    MaxSessions = 2,
-    MaxPipeline = 2,
-    RequestsToFill = MaxSessions * MaxPipeline,
-
-    %% Send off enough requests to fill sessions and pipelines in rappid succession
-    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
-    times(RequestsToFill, fun() -> spawn_link(Fun) end),
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
-
-    % Verify that connections properly reported their completed responses and can still accept more
-    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)),
-
-    % and do it again to make sure we really are clear
-    times(RequestsToFill, fun() -> spawn_link(Fun) end),
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
-
-    % Verify that connections properly reported their completed responses and can still accept more
-    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)).
-
-closing_pipes() ->
-    MaxSessions = 2,
-    MaxPipeline = 2,
-    RequestsSent = 2,
-    BalancedNumberOfRequestsPerConnection = 1,
-
-    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
-
-    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
-    times(RequestsSent, fun() -> spawn_link(Fun) end),
-
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
-
-    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
-    ?assertEqual(MaxSessions, length(Counts)),
-    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts),
-
-    timer:sleep(?SHORT_TIMEOUT_MS),
-
-    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()).
-
-balanced_connections() ->
-    MaxSessions = 4,
-    MaxPipeline = 100,
-    RequestsSent = 80,
-    BalancedNumberOfRequestsPerConnection = 20,
-
-    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
-
-    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end,
-    times(RequestsSent, fun() -> spawn_link(Fun) end),
-
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
-
-    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
-    ?assertEqual(MaxSessions, length(Counts)),
-
-    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts).
-
-small_pipeline() ->
-    MaxSessions = 10,
-    MaxPipeline = 10,
-    RequestsSent = 100,
-    FullRequestsPerConnection = 10,
-
-    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
-
-    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
-    times(RequestsSent, fun() -> spawn(Fun) end),
-
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
-
-    ibrowse:show_dest_status("localhost", 8181),
-    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
-    ?assertEqual(MaxSessions, length(Counts)),
-
-    ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts),
-
-    Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS),
-
-    ?assertEqual({error, retry_later}, Response).
-
-status() ->
-    MaxSessions = 10,
-    MaxPipeline = 10,
-    RequestsSent = 100,
-
-    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
-    times(RequestsSent, fun() -> spawn(Fun) end),
-
-    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
-
-    ibrowse:show_dest_status(),
-    ibrowse:show_dest_status("http://localhost:8181").
-
-
-times(0, _) ->
-    ok;
-times(X, Fun) ->
-    Fun(),
-    times(X - 1, Fun).

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/411468d7/test/ibrowse_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_tests.erl b/test/ibrowse_tests.erl
new file mode 100644
index 0000000..3517011
--- /dev/null
+++ b/test/ibrowse_tests.erl
@@ -0,0 +1,174 @@
+%%% File    : ibrowse_functional_tests.erl
+%%% Authors : Benjamin Lee <http://github.com/benjaminplee>
+%%%           Dan Schwabe <http://github.com/dfschwabe>
+%%%           Brian Richards <http://github.com/richbria>
+%%% Description : Functional tests of the ibrowse library using a live test HTTP server
+%%% Created : 18 November 2014 by Benjamin Lee <ya...@gmail.com>
+
+-module(ibrowse_functional_tests).
+
+-include_lib("eunit/include/eunit.hrl").
+-define(PER_TEST_TIMEOUT_SEC, 60).
+-define(TIMEDTEST(Desc, Fun), {Desc, {timeout, ?PER_TEST_TIMEOUT_SEC, fun Fun/0}}).
+
+-define(SERVER_PORT, 8181).
+-define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)).
+-define(SHORT_TIMEOUT_MS, 5000).
+-define(LONG_TIMEOUT_MS, 30000).
+-define(PAUSE_FOR_CONNECTIONS_MS, 2000).
+
+-compile(export_all).
+
+setup() ->
+    application:start(crypto),
+    application:start(public_key),
+    application:start(ssl),
+    ibrowse_test_server:start_server(?SERVER_PORT, tcp),
+    ibrowse:start(),
+    ok.
+
+teardown(_) ->
+    ibrowse:stop(),
+    ibrowse_test_server:stop_server(?SERVER_PORT),
+    ok.
+
+running_server_fixture_test_() ->
+    {foreach,
+     fun setup/0,
+     fun teardown/1,
+     [
+        ?TIMEDTEST("Simple request can be honored", simple_request),
+        ?TIMEDTEST("Slow server causes timeout", slow_server_timeout),
+        ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
+        ?TIMEDTEST("Pipelines refill", pipeline_refill),
+        ?TIMEDTEST("Timeout closes pipe", closing_pipes),
+        ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
+        ?TIMEDTEST("Pipeline too small signals retries", small_pipeline),
+        ?TIMEDTEST("Dest status can be gathered", status)
+     ]
+    }.
+
+simple_request() ->
+    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [])).
+
+slow_server_timeout() ->
+    ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)).
+
+pipeline_depth() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsSent = 2,
+    EmptyPipelineDepth = 0,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn_link(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+    ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts).
+
+pipeline_refill() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsToFill = MaxSessions * MaxPipeline,
+
+    %% Send off enough requests to fill sessions and pipelines in rappid succession
+    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsToFill, fun() -> spawn_link(Fun) end),
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    % Verify that connections properly reported their completed responses and can still accept more
+    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)),
+
+    % and do it again to make sure we really are clear
+    times(RequestsToFill, fun() -> spawn_link(Fun) end),
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    % Verify that connections properly reported their completed responses and can still accept more
+    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)).
+
+closing_pipes() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsSent = 2,
+    BalancedNumberOfRequestsPerConnection = 1,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn_link(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts),
+
+    timer:sleep(?SHORT_TIMEOUT_MS),
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()).
+
+balanced_connections() ->
+    MaxSessions = 4,
+    MaxPipeline = 100,
+    RequestsSent = 80,
+    BalancedNumberOfRequestsPerConnection = 20,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn_link(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+
+    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts).
+
+small_pipeline() ->
+    MaxSessions = 10,
+    MaxPipeline = 10,
+    RequestsSent = 100,
+    FullRequestsPerConnection = 10,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+
+    ibrowse:show_dest_status("localhost", 8181),
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+
+    ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts),
+
+    Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS),
+
+    ?assertEqual({error, retry_later}, Response).
+
+status() ->
+    MaxSessions = 10,
+    MaxPipeline = 10,
+    RequestsSent = 100,
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+
+    ibrowse:show_dest_status(),
+    ibrowse:show_dest_status("http://localhost:8181").
+
+
+times(0, _) ->
+    ok;
+times(X, Fun) ->
+    Fun(),
+    times(X - 1, Fun).


[49/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
New release after fixing travis-ci builds


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

Branch: refs/heads/upstream
Commit: 07e47c6ba0eeb3046b767eb5a0e88c0082ba5cf7
Parents: b1e9ad4
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Apr 19 19:46:05 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Apr 19 19:46:05 2016 +0100

----------------------------------------------------------------------
 CHANGELOG           | 4 ++++
 README.md           | 2 +-
 src/ibrowse.app.src | 2 +-
 3 files changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/07e47c6b/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 242d82f..c56a57d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
 
+19-04-2016 - v4.2.4
+             * Fixed travis-ci build as it was failing in running tests. 
+               No code changes to ibrowse
+
 19-04-2016 - v4.2.3
              * Fix for https://github.com/cmullaparthi/ibrowse/issues/143
              * Fix for https://github.com/cmullaparthi/ibrowse/issues/142

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/07e47c6b/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 3fe7794..a3985df 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.2.3
+**Current Version:** 4.2.4
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/07e47c6b/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index efc8094..026a6ac 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.2.3"},
+         {vsn, "4.2.4"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},


[44/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed invocation of socks proxy


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

Branch: refs/heads/upstream
Commit: b5c705cb8fc369cc51012eac9fd49e5f7b6a87e9
Parents: 1917a70
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Sun Jan 31 16:57:33 2016 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Sun Jan 31 16:57:33 2016 +0000

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b5c705cb/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index 2d700a7..c668141 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -568,11 +568,12 @@ do_connect(Host, Port, Options, #state{is_ssl      = true,
     ssl:connect(Host, Port, get_sock_options(Host, Options, SSLOptions), Timeout);
 do_connect(Host, Port, Options, _State, Timeout) ->
     Socks5Host = get_value(socks5_host, Options, undefined),
+    Sock_options = get_sock_options(Host, Options, []),
     case Socks5Host of
       undefined ->
-        gen_tcp:connect(Host, Port, get_sock_options(Host, Options, []), Timeout);
+        gen_tcp:connect(Host, Port, Sock_options, Timeout);
       _ ->
-        catch ibrowse_socks5:connect(Host, Port, Options)
+        catch ibrowse_socks5:connect(Host, Port, Options, Sock_options, Timeout)
     end.
 
 get_sock_options(Host, Options, SSLOptions) ->


[16/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Build under R18 #129


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

Branch: refs/heads/upstream
Commit: 62816035bb8fba5bd6ce86c64c64820c43ec096f
Parents: 04566c7
Author: Yury Gargay <yu...@gmail.com>
Authored: Thu Jun 25 16:35:10 2015 +0600
Committer: Yury Gargay <yu...@gmail.com>
Committed: Thu Jun 25 16:46:25 2015 +0600

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 9 +++++++--
 src/ibrowse_lib.erl         | 2 +-
 test/ibrowse_test.erl       | 8 ++++----
 3 files changed, 12 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/62816035/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index ad24351..b9e6c97 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -433,7 +433,7 @@ accumulate_response(Data, #state{reply_buffer      = RepBuf,
 
 make_tmp_filename(true) ->
     DownloadDir = ibrowse:get_config_value(download_dir, filename:absname("./")),
-    {A,B,C} = now(),
+    {A,B,C} = os:timestamp(),
     filename:join([DownloadDir,
                    "ibrowse_tmp_file_"++
                    integer_to_list(A) ++
@@ -1923,7 +1923,12 @@ cancel_timer(Ref, {eat_message, Msg}) ->
     end.
 
 make_req_id() ->
-    now().
+    case catch erlang:unqiue_integer() of
+        {'EXIT', _} ->
+            erlang:apply(erlang, now, []);
+        V ->
+            V
+    end.
 
 to_lower(Str) when is_binary(Str) ->
     to_lower(binary_to_list(Str));

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/62816035/src/ibrowse_lib.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lib.erl b/src/ibrowse_lib.erl
index 3362b39..20c74e8 100644
--- a/src/ibrowse_lib.erl
+++ b/src/ibrowse_lib.erl
@@ -369,7 +369,7 @@ default_port(ftp)   -> 21.
 
 printable_date() ->
     {{Y,Mo,D},{H, M, S}} = calendar:local_time(),
-    {_,_,MicroSecs} = now(),
+    {_,_,MicroSecs} = os:timestamp(),
     [integer_to_list(Y),
      $-,
      integer_to_list(Mo),

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/62816035/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 407ffcb..0819668 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -86,7 +86,7 @@ load_test(Url, NumWorkers, NumReqsPerWorker) when is_list(Url),
     proc_lib:spawn(?MODULE, send_reqs_1, [Url, NumWorkers, NumReqsPerWorker]).
 
 send_reqs_1(Url, NumWorkers, NumReqsPerWorker) ->
-    Start_time = now(),
+    Start_time = os:timestamp(),
     ets:new(pid_table, [named_table, public]),
     ets:new(ibrowse_test_results, [named_table, public]),
     ets:new(ibrowse_errors, [named_table, public, ordered_set]),
@@ -96,7 +96,7 @@ send_reqs_1(Url, NumWorkers, NumReqsPerWorker) ->
     spawn_workers(Url, NumWorkers, NumReqsPerWorker),
     log_msg("Finished spawning workers...~n", []),
     do_wait(Url),
-    End_time = now(),
+    End_time = os:timestamp(),
     log_msg("All workers are done...~n", []),
     log_msg("ibrowse_test_results table: ~n~p~n", [ets:tab2list(ibrowse_test_results)]),
     log_msg("Start time: ~1000.p~n", [calendar:now_to_local_time(Start_time)]),
@@ -174,7 +174,7 @@ do_send_req_1(Url, NumReqs) ->
 	{error, retry_later} ->
 	    ets:update_counter(ibrowse_test_results, retry_later, 1);
 	Err ->
-	    ets:insert(ibrowse_errors, {now(), Err}),
+	    ets:insert(ibrowse_errors, {os:timestamp(), Err}),
 	    ets:update_counter(ibrowse_test_results, other_error, 1),
 	    ok
     end,
@@ -185,7 +185,7 @@ dump_errors() ->
 	0 ->
 	    ok;
 	_ ->
-	    {A, B, C} = now(),
+	    {A, B, C} = os:timestamp(),
 	    Filename = lists:flatten(
 			 io_lib:format("ibrowse_errors_~p_~p_~p.txt" , [A, B, C])),
 	    case file:open(Filename, [write, delayed_write, raw]) of


[47/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Modified build to get travis builds to succeed


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

Branch: refs/heads/upstream
Commit: 7aa39ea5752716ebb05dbf213e0b9e455975aca8
Parents: 017ab58
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Apr 19 19:31:27 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Apr 19 19:31:27 2016 +0100

----------------------------------------------------------------------
 Makefile              |  2 +-
 test/ibrowse_test.erl | 33 +++++++++++++++++----------------
 2 files changed, 18 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/7aa39ea5/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index e0ca0f2..f67da07 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ old_tests:
 eunit:
 	@echo "====================================================="
 	@echo "Running eunit tests..."
-	$(REBAR) eunit --dir="src" 
+	$(REBAR) eunit
 
 xref: all
 	$(REBAR) xref

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/7aa39ea5/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index e5842fb..56c16b8 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -5,15 +5,15 @@
 
 -module(ibrowse_test).
 -export([
-	 load_test/3,
+	 load_test_/3,
 	 send_reqs_1/3,
 	 do_send_req/2,
          local_unit_tests/0,
 	 unit_tests/0,
          unit_tests/2,
          unit_tests_1/3,
-	 ue_test/0,
-	 ue_test/1,
+	 ue_test_/0,
+	 ue_test_/1,
 	 verify_chunked_streaming/0,
 	 verify_chunked_streaming/1,
          test_chunked_streaming_once/0,
@@ -40,9 +40,9 @@
          test_retry_of_requests/0,
          test_retry_of_requests/1,
 	 test_save_to_file_no_content_length/0,
-         socks5_noauth_test/0,
-         socks5_auth_succ_test/0,
-         socks5_auth_fail_test/0
+         socks5_noauth/0,
+         socks5_auth_succ/0,
+         socks5_auth_fail/0
 	]).
 
 -include_lib("ibrowse/include/ibrowse.hrl").
@@ -51,9 +51,9 @@
 %% Unit Tests
 %%------------------------------------------------------------------------------
 -define(LOCAL_TESTS, [
-                      {local_test_fun, socks5_noauth_test, []},
-                      {local_test_fun, socks5_auth_succ_test, []},
-                      {local_test_fun, socks5_auth_fail_test, []},
+                      {local_test_fun, socks5_noauth, []},
+                      {local_test_fun, socks5_auth_succ, []},
+                      {local_test_fun, socks5_auth_fail, []},
                       {local_test_fun, test_preserve_status_line, []},
 		      {local_test_fun, test_save_to_file_no_content_length, []},
                       {local_test_fun, test_20122010, []},
@@ -101,7 +101,7 @@
                     {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}
 		   ]).
 
-socks5_noauth_test() ->
+socks5_noauth() ->
     case ibrowse:send_req("http://localhost:8181/success", [], get, [],
                           [{socks5_host, "localhost"}, {socks5_port, 8282}], 2000) of
 	{ok, "200", _, _} ->
@@ -110,7 +110,7 @@ socks5_noauth_test() ->
 	    Err
     end.
 
-socks5_auth_succ_test() ->
+socks5_auth_succ() ->
     case ibrowse:send_req("http://localhost:8181/success", [], get, [],
                           [{socks5_host, "localhost"}, {socks5_port, 8383},
                            {socks5_user, <<"user">>}, {socks5_password, <<"password">>}], 2000) of
@@ -120,7 +120,7 @@ socks5_auth_succ_test() ->
 	    Err
     end.
 
-socks5_auth_fail_test() ->
+socks5_auth_fail() ->
     case ibrowse:send_req("http://localhost:8181/success", [], get, [],
                           [{socks5_host, "localhost"}, {socks5_port, 8282},
                            {socks5_user, <<"user">>}, {socks5_password, <<"wrong_password">>}], 2000) of
@@ -169,9 +169,10 @@ test_stream_once(Req_id) ->
 	{ibrowse_async_response_end, Req_id} ->
 	    ok
     end.
+
 %% Use ibrowse:set_max_sessions/3 and ibrowse:set_max_pipeline_size/3 to
 %% tweak settings before running the load test. The defaults are 10 and 10.
-load_test(Url, NumWorkers, NumReqsPerWorker) when is_list(Url),
+load_test_(Url, NumWorkers, NumReqsPerWorker) when is_list(Url),
                                                   is_integer(NumWorkers),
                                                   is_integer(NumReqsPerWorker),
                                                   NumWorkers > 0,
@@ -502,9 +503,9 @@ execute_req(Url, Method, Options) ->
 	    io:format("~p~n", [Err])
     end.
 
-ue_test() ->
-    ue_test(lists:duplicate(1024, $?)).
-ue_test(Data) ->
+ue_test_() ->
+    ue_test_(lists:duplicate(1024, $?)).
+ue_test_(Data) ->
     {Time, Res} = timer:tc(ibrowse_lib, url_encode, [Data]),
     io:format("Time -> ~p~n", [Time]),
     io:format("Data Length -> ~p~n", [length(Data)]),


[09/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed bug with connection req completion

Algorithm change had bug where ets:select return
value was incorrectly assumed to be the object key
and not the entire object causing the following
delete attempt based on a matchspec and the key to fail.

This meant that ets was not updated to reflect the completed
requests on each connection and causing exaustion of pipelines
event though connections were idle.  Functional test added which
demonstrated the problem.


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

Branch: refs/heads/upstream
Commit: 247dd563fbf5b11a54bfefe96b6cd9bc2efa5a1b
Parents: 86ccc45
Author: benjaminplee <ya...@gmail.com>
Authored: Fri Nov 21 04:33:08 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Fri Nov 21 04:35:52 2014 +0000

----------------------------------------------------------------------
 src/ibrowse_lb.erl                |  2 +-
 test/ibrowse_functional_tests.erl | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/247dd563/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lb.erl b/src/ibrowse_lb.erl
index 656adda..656c3f9 100644
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@ -259,7 +259,7 @@ report_request_complete(_Tid, 0) ->
 report_request_complete(Tid, RemainingRetries) ->
     %% Don't cascade errors since Tid is really managed by other process
     catch case ets:select(Tid, ?KEY_MATCHSPEC_BY_PID(self())) of
-        [MatchKey] ->
+        [{MatchKey, _}] ->
             case ets:select_delete(Tid, ?KEY_MATCHSPEC_FOR_DELETE(MatchKey)) of
                 1 ->
                     ets:insert(Tid, {decremented(MatchKey), undefined}),

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/247dd563/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
index 8b75e3d..e55c5b2 100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@ -38,6 +38,7 @@ running_server_fixture_test_() ->
         ?TIMEDTEST("Simple request can be honored", simple_request),
         ?TIMEDTEST("Slow server causes timeout", slow_server_timeout),
         ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
+        ?TIMEDTEST("Pipelines refill", pipeline_refill),
         ?TIMEDTEST("Timeout closes pipe", closing_pipes),
         ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
         ?TIMEDTEST("Pipeline too small signals retries", small_pipeline),
@@ -68,6 +69,26 @@ pipeline_depth() ->
     ?assertEqual(MaxSessions, length(Counts)),
     ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts).
 
+pipeline_refill() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsToFill = MaxSessions * MaxPipeline,
+
+    %% Send off enough requests to fill sessions and pipelines in rappid succession
+    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsToFill, fun() -> spawn_link(Fun) end),
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    % Verify that connections properly reported their completed responses and can still accept more
+    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)),
+
+    % and do it again to make sure we really are clear
+    times(RequestsToFill, fun() -> spawn_link(Fun) end),
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    % Verify that connections properly reported their completed responses and can still accept more
+    ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)).
+
 closing_pipes() ->
     MaxSessions = 2,
     MaxPipeline = 2,


[02/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Filled in more functional tests

Added additional functional tests ensuring that
the pipelines empty and added some robustness
around the test server.


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

Branch: refs/heads/upstream
Commit: 78d1814638bcf2b2d7c7441a418e3f52d31f58d5
Parents: 9d0b7e3
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 16:49:28 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 16:49:28 2014 +0000

----------------------------------------------------------------------
 test/ibrowse_functional_tests.erl | 72 ++++++++++++++++++++++++++++++++--
 test/ibrowse_test_server.erl      | 27 ++++++++-----
 2 files changed, 86 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/78d18146/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
index fc7afec..0e43f6a 100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@ -12,6 +12,9 @@
 
 -define(SERVER_PORT, 8181).
 -define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)).
+-define(SHORT_TIMEOUT_MS, 5000).
+-define(LONG_TIMEOUT_MS, 30000).
+-define(PAUSE_FOR_CONNECTIONS_MS, 2000).
 
 setup() ->
     application:start(crypto),
@@ -33,7 +36,10 @@ running_server_fixture_test_() ->
      [
         ?TIMEDTEST("Simple request can be honored", simple_request),
         ?TIMEDTEST("Slow server causes timeout", slow_server_timeout),
-        ?TIMEDTEST("Requests are balanced over connections", balanced_connections)
+        ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
+        ?TIMEDTEST("Timeout closes pipe", closing_pipes),
+        ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
+        ?TIMEDTEST("Pipeline too small signals retries", small_pipeline)
      ]
     }.
 
@@ -43,6 +49,44 @@ simple_request() ->
 slow_server_timeout() ->
     ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)).
 
+pipeline_depth() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsSent = 2,
+    EmptyPipelineDepth = 0,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn_link(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+    ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts).
+
+closing_pipes() ->
+    MaxSessions = 2,
+    MaxPipeline = 2,
+    RequestsSent = 2,
+    BalancedNumberOfRequestsPerConnection = 1,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn_link(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+    ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts),
+
+    timer:sleep(?SHORT_TIMEOUT_MS),
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()).
+
 balanced_connections() ->
     MaxSessions = 4,
     MaxPipeline = 100,
@@ -51,16 +95,38 @@ balanced_connections() ->
 
     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
 
-    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], 30000) end,
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end,
     times(RequestsSent, fun() -> spawn_link(Fun) end),
 
-    timer:sleep(1000),
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
 
     Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
     ?assertEqual(MaxSessions, length(Counts)),
 
     ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts).
 
+small_pipeline() ->
+    MaxSessions = 10,
+    MaxPipeline = 10,
+    RequestsSent = 100,
+    FullRequestsPerConnection = 10,
+
+    ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+
+    Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+    ?assertEqual(MaxSessions, length(Counts)),
+
+    ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts),
+
+    Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS),
+
+    ?assertEqual({error, retry_later}, Response).
+
 times(0, _) ->
     ok;
 times(X, Fun) ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/78d18146/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index 940552a..d12d1c4 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -68,11 +68,7 @@ do_accept(ssl, Listen_sock) ->
 accept_loop(Sock, Sock_type) ->
     case do_accept(Sock_type, Sock) of
         {ok, Conn} ->
-            Pid = spawn_link(
-              fun() ->
-                      server_loop(Conn, Sock_type, #request{})
-              end),
-            ets:insert(?CONN_PIPELINE_DEPTH, {Pid, 0}),
+            Pid = spawn_link(fun() -> connection(Conn, Sock_type) end),
             set_controlling_process(Conn, Sock_type, Pid),
             Pid ! {setopts, [{active, true}]},
             accept_loop(Sock, Sock_type);
@@ -87,6 +83,14 @@ accept_loop(Sock, Sock_type) ->
             Err
     end.
 
+connection(Conn, Sock_type) ->
+    ets:insert(?CONN_PIPELINE_DEPTH, {self(), 0}),
+    try
+        server_loop(Conn, Sock_type, #request{})
+    after
+        ets:delete(?CONN_PIPELINE_DEPTH, self())
+    end.
+
 set_controlling_process(Sock, tcp, Pid) ->
     gen_tcp:controlling_process(Sock, Pid);
 set_controlling_process(Sock, ssl, Pid) ->
@@ -100,14 +104,19 @@ setopts(Sock, ssl, Opts) ->
 server_loop(Sock, Sock_type, #request{headers = Headers} = Req) ->
     receive
         {http, Sock, {http_request, HttpMethod, HttpUri, HttpVersion}} ->
+            ets:update_counter(?CONN_PIPELINE_DEPTH, self(), 1),
             server_loop(Sock, Sock_type, Req#request{method = HttpMethod,
                                                      uri = HttpUri,
                                                      version = HttpVersion});
         {http, Sock, {http_header, _, _, _, _} = H} ->
             server_loop(Sock, Sock_type, Req#request{headers = [H | Headers]});
         {http, Sock, http_eoh} ->
-            ets:update_counter(?CONN_PIPELINE_DEPTH, self(), 1),
-            process_request(Sock, Sock_type, Req),
+            case process_request(Sock, Sock_type, Req) of
+                not_done ->
+                    ok;
+                _ ->
+                    ets:update_counter(?CONN_PIPELINE_DEPTH, self(), -1)
+            end,
             server_loop(Sock, Sock_type, #request{});
         {http, Sock, {http_error, Err}} ->
             do_trace("Error parsing HTTP request:~n"
@@ -172,7 +181,6 @@ process_request(Sock, Sock_type,
                          uri = {abs_path, "/ibrowse_head_transfer_enc"}}) ->
     Resp = <<"HTTP/1.1 400 Bad Request\r\nServer: Apache-Coyote/1.1\r\nContent-Length:5\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\n\r\nabcde">>,
     do_send(Sock, Sock_type, Resp);
-
 process_request(Sock, Sock_type,
                 #request{method='GET',
                          headers = Headers,
@@ -210,7 +218,7 @@ process_request(Sock, Sock_type,
     Resp = <<"HTTP/1.1 303 See Other\r\nLocation: http://example.org\r\nContent-Length: 5\r\n\r\nabcde">>,
     do_send(Sock, Sock_type, Resp);
 process_request(_Sock, _Sock_type, #request{uri = {abs_path, "/never_respond"} } ) ->
-    noop;
+    not_done;
 process_request(Sock, Sock_type, Req) ->
     do_trace("Recvd req: ~p~n", [Req]),
     Resp = <<"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n">>,
@@ -221,7 +229,6 @@ do_send(Sock, tcp, Resp) ->
 do_send(Sock, ssl, Resp) ->
     ssl:send(Sock, Resp).
 
-
 %%------------------------------------------------------------------------------
 %% Utility functions
 %%------------------------------------------------------------------------------


[38/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Removed lines which were failing travis builds


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

Branch: refs/heads/upstream
Commit: 79e26aed6bccecaef66037811a70a20ba4e65963
Parents: ad31b03
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Wed Nov 25 07:38:26 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Wed Nov 25 07:38:26 2015 +0000

----------------------------------------------------------------------
 .travis.yml         | 3 ---
 src/ibrowse.app.src | 2 +-
 2 files changed, 1 insertion(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/79e26aed/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 0861069..4875662 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,8 +7,5 @@ otp_release:
    - 18.0
    - 18.1
 before_script:
-  - curl -X PUT localhost:5984/couchbeam_testdb
-  - curl -X PUT localhost:5984/couchbeam_testdb2
-  - curl -X PUT localhost:5984/couchbeam_testdb3
   - "./bootstrap_travis.sh"
 script: "./rebar3 eunit"

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/79e26aed/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 7e28895..2f4ced6 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.2"},
+         {vsn, "4.2.1"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},


[07/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Added basic test for show_dest_status


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

Branch: refs/heads/upstream
Commit: 5b8993e10ba76bfd76cd7b992dfcf33cec4de938
Parents: 4b0fb6b
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 18:01:51 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 18:01:51 2014 +0000

----------------------------------------------------------------------
 test/ibrowse_functional_tests.erl | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/5b8993e1/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_functional_tests.erl b/test/ibrowse_functional_tests.erl
index 0e43f6a..8df662b 100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@ -39,7 +39,8 @@ running_server_fixture_test_() ->
         ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
         ?TIMEDTEST("Timeout closes pipe", closing_pipes),
         ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
-        ?TIMEDTEST("Pipeline too small signals retries", small_pipeline)
+        ?TIMEDTEST("Pipeline too small signals retries", small_pipeline),
+        ?TIMEDTEST("Dest status can be gathered", status)
      ]
     }.
 
@@ -127,6 +128,20 @@ small_pipeline() ->
 
     ?assertEqual({error, retry_later}, Response).
 
+status() ->
+    MaxSessions = 10,
+    MaxPipeline = 10,
+    RequestsSent = 100,
+
+    Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+    times(RequestsSent, fun() -> spawn(Fun) end),
+
+    timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+
+    ibrowse:show_dest_status(),
+    ibrowse:show_dest_status("http://localhost:8181").
+
+
 times(0, _) ->
     ok;
 times(X, Fun) ->


[11/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed extraction of Pid for iteration with new key

Missed in original work.


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

Branch: refs/heads/upstream
Commit: 37fce828469d3a0ca6aae95b7a8b30deb9187d4d
Parents: 1a680f0
Author: benjamin.lee <be...@asynchrony.com>
Authored: Thu Dec 11 21:35:12 2014 +0000
Committer: benjamin.lee <be...@asynchrony.com>
Committed: Thu Dec 11 21:35:12 2014 +0000

----------------------------------------------------------------------
 src/ibrowse_lb.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/37fce828/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lb.erl b/src/ibrowse_lb.erl
index 656c3f9..794ba45 100644
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@ -282,5 +282,5 @@ decremented({Size, _Timestamp, Pid}) ->
     {Size - 1, os:timestamp(), Pid}.
 
 for_each_connection_pid(Tid, Fun) ->
-    catch ets:foldl(fun({Pid, _}, _) -> Fun(Pid) end, undefined, Tid),
+    ets:foldl(fun({{_, _, Pid}, _}, _) -> Fun(Pid) end, undefined, Tid),
     ok.


[46/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Invoke eunit tests only for files in src directory


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

Branch: refs/heads/upstream
Commit: 017ab585e463150535f16682d916ee47d7735838
Parents: 6d5bcef
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Apr 19 18:28:11 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Apr 19 18:28:11 2016 +0100

----------------------------------------------------------------------
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/017ab585/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index f67da07..e0ca0f2 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ old_tests:
 eunit:
 	@echo "====================================================="
 	@echo "Running eunit tests..."
-	$(REBAR) eunit
+	$(REBAR) eunit --dir="src" 
 
 xref: all
 	$(REBAR) xref


[24/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Workaround travis-ci build failure.


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

Branch: refs/heads/upstream
Commit: b4ad6df3c54a6e2a88a63e3ac97090baf04919cf
Parents: 3a4044d
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 20:23:43 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 20:23:43 2015 +0100

----------------------------------------------------------------------
 test/ibrowse_test.erl | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b4ad6df3/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 0787493..4bf8ffc 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -266,8 +266,9 @@ unit_tests() ->
 
 unit_tests(Options, Test_list) ->
     application:start(crypto),
+    application:start(asn1),
     application:start(public_key),
-    application:ensure_all_started(ssl),
+    application:start(ssl),
     (catch ibrowse_test_server:start_server(8181, tcp)),
     application:start(ibrowse),
     Options_1 = Options ++ [{connect_timeout, 5000}],


[22/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge branch 'improve_pipeline_balance' of https://github.com/benjaminplee/ibrowse into merge_pull_req_123


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

Branch: refs/heads/upstream
Commit: 8494e9433f1e74f9ab43aaa23039ff3ccedadb55
Parents: d61dd9a 37fce82
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 08:19:59 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 08:19:59 2015 +0100

----------------------------------------------------------------------
 .gitignore                        |   1 +
 CONTRIBUTORS                      |   3 +
 Makefile                          |   6 +-
 include/ibrowse.hrl               |   5 +
 rebar                             | Bin 90778 -> 188026 bytes
 src/ibrowse.erl                   |  11 ++-
 src/ibrowse_http_client.erl       |   2 +-
 src/ibrowse_lb.erl                |  27 +++--
 src/ibrowse_lib.erl               |   1 +
 src/ibrowse_socks5.erl            | 131 ++++++++++++++++++-------
 test/ibrowse_functional_tests.erl | 174 +++++++++++++++++++++++++++++++++
 test/ibrowse_test.erl             |  20 ++--
 test/ibrowse_test_server.erl      |  97 +++++++++++-------
 13 files changed, 376 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/Makefile
----------------------------------------------------------------------
diff --cc Makefile
index b596b64,b596b64..28dfda8
--- a/Makefile
+++ b/Makefile
@@@ -15,9 -15,9 +15,11 @@@ install: compil
  	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
  	cp -r ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
  
--test: all
++eunit_test: all
  	./rebar eunit
--	erl -noshell -pa .eunit -pa test -s ibrowse -s ibrowse_test unit_tests \
++
++test: all
++	erl -noshell -pa test -pa ebin -s ibrowse_test unit_tests \
  	-s ibrowse_test verify_chunked_streaming \
  	-s ibrowse_test test_chunked_streaming_once \
  	-s erlang halt

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/include/ibrowse.hrl
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/src/ibrowse.erl
----------------------------------------------------------------------
diff --cc src/ibrowse.erl
index fbb4b83,951cfe1..51fcb86
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@@ -651,7 -619,7 +651,7 @@@ show_dest_status() -
      io:format("~80.80.=s~n", [""]),
      Metrics = get_metrics(),
      lists:foreach(
--      fun({Host, Port, Lb_pid, Tid, Size}) ->
++      fun({Host, Port, {Lb_pid, _, Tid, Size, _}}) ->
                io:format("~40.40s | ~-5.5s | ~-5.5s | ~p~n",
                          [Host ++ ":" ++ integer_to_list(Port),
                           integer_to_list(Tid),
@@@ -686,33 -654,43 +686,38 @@@ show_dest_status(Host, Port) -
      end.
  
  get_metrics() ->
 -    Dests = lists:filter(fun({lb_pid, {Host, Port}, _}) when is_list(Host),
 -                                                             is_integer(Port) ->
 -                                 true;
 -                            (_) ->
 -                                 false
 -                         end, ets:tab2list(?LOAD_BALANCER_NAMED_TABLE)),
 -    All_ets = ets:all(),
 -    lists:map(fun({lb_pid, {Host, Port}, Lb_pid}) ->
 -                  case lists:dropwhile(
 -                         fun(Tid) ->
 -                                 ets:info(Tid, owner) /= Lb_pid
 -                         end, All_ets) of
 -                      [] ->
 -                          {Host, Port, Lb_pid, unknown, 0};
 -                      [Tid | _] ->
 -                          Size = case catch (ets:info(Tid, size)) of
 -                                     N when is_integer(N) -> N;
 -                                     _ -> 0
 -                                 end,
 -                          {Host, Port, Lb_pid, Tid, Size}
 -                  end
 -              end, Dests).
 +    Dests = lists:filter(
 +              fun(#lb_pid{host_port = {Host, Port}}) when is_list(Host),
 +                                                          is_integer(Port) ->
 +                      true;
 +                 (_) ->
 +                      false
 +              end, ets:tab2list(ibrowse_lb)),
 +    lists:foldl(
 +      fun(#lb_pid{host_port = {X_host, X_port}}, X_acc) ->
 +              case get_metrics(X_host, X_port) of
 +                  {_, _, _, _, _} = X_res ->
-                       [X_res | X_acc];
++                      [{X_host, X_port, X_res} | X_acc];
 +                  _X_res ->
 +                      X_acc
 +              end
 +      end, [], Dests).
  
  get_metrics(Host, Port) ->
 -    case ets:lookup(?LOAD_BALANCER_NAMED_TABLE, {Host, Port}) of
 +    case ets:lookup(ibrowse_lb, {Host, Port}) of
          [] ->
              no_active_processes;
 -        [#lb_pid{pid = Lb_pid}] ->
 -            MsgQueueSize = (catch process_info(Lb_pid, message_queue_len)),
 -            %% {Lb_pid, MsgQueueSize,
 -            case lists:dropwhile(
 -                   fun(Tid) ->
 -                           ets:info(Tid, owner) /= Lb_pid
 -                   end, ets:all()) of
 -                [] ->
 -                    {Lb_pid, MsgQueueSize, unknown, 0, unknown};
 -                [Tid | _] ->
 +        [#lb_pid{pid = Lb_pid, ets_tid = Tid}] ->
-             MsgQueueSize = (catch process_info(Lb_pid, message_queue_len)),
++            MsgQueueSize = case (catch process_info(Lb_pid, message_queue_len)) of
++			       {message_queue_len, Msg_q_len} ->
++				   Msg_q_len;
++			       _ ->
++				   -1
++			   end,
 +            case Tid of
 +                undefined ->
 +                    {Lb_pid, MsgQueueSize, undefined, 0, {{0, 0}, {0, 0}}};
 +                _ ->
                      try
                          Size = ets:info(Tid, size),
                          case Size of

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --cc src/ibrowse_http_client.erl
index db9559a,d92db42..92e4964
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@@ -2005,30 -1944,15 +2005,30 @@@ to_lower([], Acc) -
  
  shutting_down(#state{lb_ets_tid = undefined}) ->
      ok;
 -shutting_down(#state{lb_ets_tid = Tid}) ->
 -    ibrowse_lb:report_connection_down(Tid).
 +shutting_down(#state{lb_ets_tid = Tid,
 +                     cur_pipeline_size = _Sz}) ->
 +    (catch ets:select_delete(Tid, [{{{'_', '_', '$1'},'_'},[{'==','$1',{const,self()}}],[true]}])).
  
 -report_request_complete(#state{is_closing = true} = State) ->
 +inc_pipeline_counter(#state{is_closing = true} = State) ->
      State;
 -report_request_complete(#state{lb_ets_tid = undefined} = State) ->
 +inc_pipeline_counter(#state{lb_ets_tid = undefined} = State) ->
      State;
 -report_request_complete(#state{lb_ets_tid = Tid} = State) ->
 -    ibrowse_lb:report_request_complete(Tid),
 +inc_pipeline_counter(#state{cur_pipeline_size = Pipe_sz} = State) ->
 +    State#state{cur_pipeline_size = Pipe_sz + 1}.
 +
 +dec_pipeline_counter(#state{cur_pipeline_size = Pipe_sz,
 +                            lb_ets_tid        = Tid,
 +                            proc_state        = Proc_state} = State) when Tid /= undefined,
 +                                                                          Proc_state /= ?dead_proc_walking ->
 +    Ts = os:timestamp(),
++    catch ets:insert(Tid, {{Pipe_sz - 1, os:timestamp(), self()}, []}),
 +    (catch ets:select_delete(Tid, [{{{'_', '$2', '$1'},'_'},
 +                                    [{'==', '$1', {const,self()}},
 +                                     {'<',  '$2', {const,Ts}}
 +                                    ],
 +                                    [true]}])),
-     catch ets:insert(Tid, {{Pipe_sz - 1, os:timestamp(), self()}, []}),
 +    State#state{cur_pipeline_size = Pipe_sz - 1};
 +dec_pipeline_counter(State) ->
      State.
  
  flatten([H | _] = L) when is_integer(H) ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/src/ibrowse_lb.erl
----------------------------------------------------------------------
diff --cc src/ibrowse_lb.erl
index 88b169b,794ba45..894d8ad
--- a/src/ibrowse_lb.erl
+++ b/src/ibrowse_lb.erl
@@@ -119,23 -133,18 +119,23 @@@ handle_call(stop, _From, #state{ets_ti
  handle_call(_, _From, #state{proc_state = shutting_down} = State) ->
      {reply, {error, shutting_down}, State};
  
 -handle_call({spawn_connection, Url, Max_sess, Max_pipe, SSL_options, Process_options}, _From, State) ->
 -    State_1 = maybe_create_ets(State),
 -    Tid = State_1#state.ets_tid,
 -    Reply = case num_current_connections(Tid) of
 -        X when X >= Max_sess ->
 -            find_best_connection(Tid, Max_pipe);
 -        _ ->
 -            Result = {ok, Pid} = ibrowse_http_client:start_link({Tid, Url, SSL_options}, Process_options),
 -            record_new_connection(Tid, Pid),
 -            Result
 -    end,
 -    {reply, Reply, State_1#state{max_sessions = Max_sess, max_pipeline_size = Max_pipe}};
 +handle_call({spawn_connection, Url, Max_sess, Max_pipe, SSL_options, Process_options}, _From,
 +	    State) ->
 +    State_1   = maybe_create_ets(State),
 +    Tid       = State_1#state.ets_tid,
 +    Tid_size  = ets:info(Tid, size),
-     case Tid_size > Max_sess of
++    case Tid_size >= Max_sess of
 +        true ->
-             Reply = find_best_connection(Tid, Max_pipe, Tid_size),
++            Reply = find_best_connection(Tid, Max_pipe),
 +            {reply, Reply, State_1#state{max_sessions      = Max_sess,
 +                                         max_pipeline_size = Max_pipe}};
 +        false ->
 +            {ok, Pid} = ibrowse_http_client:start({Tid, Url, SSL_options}, Process_options),
 +            Ts = os:timestamp(),
-             ets:insert(Tid, {{0, Ts, Pid}, []}),
-             {reply, {ok, {0, Ts, Pid}}, State_1#state{max_sessions      = Max_sess,
-                                                   max_pipeline_size = Max_pipe}}
++            ets:insert(Tid, {{1, Ts, Pid}, []}),
++            {reply, {ok, {1, Ts, Pid}}, State_1#state{max_sessions      = Max_sess,
++						      max_pipeline_size = Max_pipe}}
 +    end;
  
  handle_call(Request, _From, State) ->
      Reply = {unknown_request, Request},
@@@ -215,18 -214,21 +215,13 @@@ code_change(_OldVsn, State, _Extra) -
  %%--------------------------------------------------------------------
  %%% Internal functions
  %%--------------------------------------------------------------------
- find_best_connection(Tid, Max_pipe, _Num_cur) ->
 -find_best_connection(Tid, Max_pipeline_size) ->
 -    find_best_connection(Tid, Max_pipeline_size, ?MAX_RETRIES).
 -
 -find_best_connection(_Tid, _Max_pipeline_size, 0) ->
 -    {error, retry_later};
 -find_best_connection(Tid, Max_pipeline_size, RemainingRetries) ->
++find_best_connection(Tid, Max_pipe) ->
      case ets:first(Tid) of
-         {Spec_size, Ts, Pid} = First ->
-             case Spec_size >= Max_pipe of
 -        {Size, _Timestamp, Pid} = Key when Size < Max_pipeline_size ->
 -            case record_request_for_connection(Tid, Key) of
--                true ->
-                     {error, retry_later};
 -                    {ok, Pid};
--                false ->
-                     ets:delete(Tid, First),
-                     ets:insert(Tid, {{Spec_size + 1, Ts, Pid}, []}),
-                     {ok, First}
 -                    find_best_connection(Tid, Max_pipeline_size, RemainingRetries - 1)
--            end;
-         '$end_of_table' ->
 -        _ -> 
++        {Spec_size, Ts, Pid} = First when Spec_size < Max_pipe ->
++	    ets:delete(Tid, First),
++	    ets:insert(Tid, {{Spec_size + 1, Ts, Pid}, []}),
++	    {ok, First};
++        _ ->
              {error, retry_later}
      end.
  

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/src/ibrowse_lib.erl
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/test/ibrowse_functional_tests.erl
----------------------------------------------------------------------
diff --cc test/ibrowse_functional_tests.erl
index 0000000,e55c5b2..3517011
mode 000000,100644..100644
--- a/test/ibrowse_functional_tests.erl
+++ b/test/ibrowse_functional_tests.erl
@@@ -1,0 -1,171 +1,174 @@@
+ %%% File    : ibrowse_functional_tests.erl
+ %%% Authors : Benjamin Lee <http://github.com/benjaminplee>
+ %%%           Dan Schwabe <http://github.com/dfschwabe>
+ %%%           Brian Richards <http://github.com/richbria>
+ %%% Description : Functional tests of the ibrowse library using a live test HTTP server
+ %%% Created : 18 November 2014 by Benjamin Lee <ya...@gmail.com>
+ 
+ -module(ibrowse_functional_tests).
+ 
+ -include_lib("eunit/include/eunit.hrl").
+ -define(PER_TEST_TIMEOUT_SEC, 60).
+ -define(TIMEDTEST(Desc, Fun), {Desc, {timeout, ?PER_TEST_TIMEOUT_SEC, fun Fun/0}}).
+ 
+ -define(SERVER_PORT, 8181).
+ -define(BASE_URL, "http://localhost:" ++ integer_to_list(?SERVER_PORT)).
+ -define(SHORT_TIMEOUT_MS, 5000).
+ -define(LONG_TIMEOUT_MS, 30000).
+ -define(PAUSE_FOR_CONNECTIONS_MS, 2000).
+ 
++-compile(export_all).
++
+ setup() ->
+     application:start(crypto),
+     application:start(public_key),
+     application:start(ssl),
+     ibrowse_test_server:start_server(?SERVER_PORT, tcp),
+     ibrowse:start(),
+     ok.
+ 
+ teardown(_) ->
+     ibrowse:stop(),
+     ibrowse_test_server:stop_server(?SERVER_PORT),
+     ok.
+ 
+ running_server_fixture_test_() ->
+     {foreach,
+      fun setup/0,
+      fun teardown/1,
+      [
+         ?TIMEDTEST("Simple request can be honored", simple_request),
+         ?TIMEDTEST("Slow server causes timeout", slow_server_timeout),
+         ?TIMEDTEST("Pipeline depth goes down with responses", pipeline_depth),
+         ?TIMEDTEST("Pipelines refill", pipeline_refill),
+         ?TIMEDTEST("Timeout closes pipe", closing_pipes),
+         ?TIMEDTEST("Requests are balanced over connections", balanced_connections),
+         ?TIMEDTEST("Pipeline too small signals retries", small_pipeline),
+         ?TIMEDTEST("Dest status can be gathered", status)
+      ]
+     }.
+ 
+ simple_request() ->
+     ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [])).
+ 
+ slow_server_timeout() ->
+     ?assertMatch({error, req_timedout}, ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [], 5000)).
+ 
+ pipeline_depth() ->
+     MaxSessions = 2,
+     MaxPipeline = 2,
+     RequestsSent = 2,
+     EmptyPipelineDepth = 0,
+ 
+     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+ 
+     Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+     times(RequestsSent, fun() -> spawn_link(Fun) end),
+ 
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+ 
+     Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+     ?assertEqual(MaxSessions, length(Counts)),
+     ?assertEqual(lists:duplicate(MaxSessions, EmptyPipelineDepth), Counts).
+ 
+ pipeline_refill() ->
+     MaxSessions = 2,
+     MaxPipeline = 2,
+     RequestsToFill = MaxSessions * MaxPipeline,
+ 
+     %% Send off enough requests to fill sessions and pipelines in rappid succession
+     Fun = fun() -> ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+     times(RequestsToFill, fun() -> spawn_link(Fun) end),
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+ 
+     % Verify that connections properly reported their completed responses and can still accept more
+     ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)),
+ 
+     % and do it again to make sure we really are clear
+     times(RequestsToFill, fun() -> spawn_link(Fun) end),
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+ 
+     % Verify that connections properly reported their completed responses and can still accept more
+     ?assertMatch({ok, "200", _, _}, ibrowse:send_req(?BASE_URL, [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS)).
+ 
+ closing_pipes() ->
+     MaxSessions = 2,
+     MaxPipeline = 2,
+     RequestsSent = 2,
+     BalancedNumberOfRequestsPerConnection = 1,
+ 
+     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+ 
+     Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+     times(RequestsSent, fun() -> spawn_link(Fun) end),
+ 
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+ 
+     Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+     ?assertEqual(MaxSessions, length(Counts)),
+     ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts),
+ 
+     timer:sleep(?SHORT_TIMEOUT_MS),
+ 
+     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()).
+ 
+ balanced_connections() ->
+     MaxSessions = 4,
+     MaxPipeline = 100,
+     RequestsSent = 80,
+     BalancedNumberOfRequestsPerConnection = 20,
+ 
+     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+ 
+     Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?LONG_TIMEOUT_MS) end,
+     times(RequestsSent, fun() -> spawn_link(Fun) end),
+ 
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),
+ 
+     Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+     ?assertEqual(MaxSessions, length(Counts)),
+ 
+     ?assertEqual(lists:duplicate(MaxSessions, BalancedNumberOfRequestsPerConnection), Counts).
+ 
+ small_pipeline() ->
+     MaxSessions = 10,
+     MaxPipeline = 10,
+     RequestsSent = 100,
+     FullRequestsPerConnection = 10,
+ 
+     ?assertEqual([], ibrowse_test_server:get_conn_pipeline_depth()),
+ 
+     Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+     times(RequestsSent, fun() -> spawn(Fun) end),
+ 
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+ 
++    ibrowse:show_dest_status("localhost", 8181),
+     Counts = [Count || {_Pid, Count} <- ibrowse_test_server:get_conn_pipeline_depth()],
+     ?assertEqual(MaxSessions, length(Counts)),
+ 
+     ?assertEqual(lists:duplicate(MaxSessions, FullRequestsPerConnection), Counts),
+ 
+     Response = ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS),
+ 
+     ?assertEqual({error, retry_later}, Response).
+ 
+ status() ->
+     MaxSessions = 10,
+     MaxPipeline = 10,
+     RequestsSent = 100,
+ 
+     Fun = fun() -> ibrowse:send_req(?BASE_URL ++ "/never_respond", [], get, [], [{max_sessions, MaxSessions}, {max_pipeline_size, MaxPipeline}], ?SHORT_TIMEOUT_MS) end,
+     times(RequestsSent, fun() -> spawn(Fun) end),
+ 
+     timer:sleep(?PAUSE_FOR_CONNECTIONS_MS),  %% Wait for everyone to get in line
+ 
+     ibrowse:show_dest_status(),
+     ibrowse:show_dest_status("http://localhost:8181").
+ 
+ 
+ times(0, _) ->
+     ok;
+ times(X, Fun) ->
+     Fun(),
+     times(X - 1, Fun).

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --cc test/ibrowse_test.erl
index e216e82,4ddb9c1..0787493
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@@ -35,13 -34,9 +35,13 @@@
           test_303_response_with_a_body/1,
           test_binary_headers/0,
           test_binary_headers/1,
 -         test_generate_body_0/0
 +         test_generate_body_0/0,
 +         test_retry_of_requests/0,
 +         test_retry_of_requests/1
  	]).
  
- -include("ibrowse.hrl").
++-include_lib("ibrowse/include/ibrowse.hrl").
 +
  test_stream_once(Url, Method, Options) ->
      test_stream_once(Url, Method, Options, 5000).
  
@@@ -214,65 -207,56 +214,65 @@@ dump_errors(Key, Iod) -
  %%------------------------------------------------------------------------------
  %% Unit Tests
  %%------------------------------------------------------------------------------
 +-define(LOCAL_TESTS, [
 +                      {local_test_fun, test_20122010, []},
 +                      {local_test_fun, test_pipeline_head_timeout, []},
 +                      {local_test_fun, test_head_transfer_encoding, []},
 +                      {local_test_fun, test_head_response_with_body, []},
 +                      {local_test_fun, test_303_response_with_a_body, []},
 +                      {local_test_fun, test_binary_headers, []},
 +                      {local_test_fun, test_retry_of_requests, []}
 +                     ]).
 +
  -define(TEST_LIST, [{"http://intranet/messenger", get},
 -            {"http://www.google.co.uk", get},
 -            {"http://www.google.com", get},
 -            {"http://www.google.com", options},
 -            {"https://mail.google.com", get},
 -            {"http://www.sun.com", get},
 -            {"http://www.oracle.com", get},
 -            {"http://www.bbc.co.uk", get},
 -            {"http://www.bbc.co.uk", trace},
 -            {"http://www.bbc.co.uk", options},
 -            {"http://yaws.hyber.org", get},
 -            {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
 -            {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
 -            {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
 -            {"http://jigsaw.w3.org/HTTP/connection.html", get},
 -            {"http://jigsaw.w3.org/HTTP/cc.html", get},
 -            {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
 -            {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
 -            {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
 -            {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
 -            {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
 -            {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
 -            {"http://jigsaw.w3.org/HTTP/neg", get},
 -            {"http://jigsaw.w3.org/HTTP/negbad", get},
 -            {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
 -            {"http://jigsaw.w3.org/HTTP/300/", get},
 -            {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
 -            {"http://jigsaw.w3.org/HTTP/CL/", get},
 -            {"http://www.httpwatch.com/httpgallery/chunked/", get},
 -            {"https://github.com", get, [{ssl_options, [{depth, 2}]}]},
 -            {local_test_fun, test_20122010, []},
 -            {local_test_fun, test_pipeline_head_timeout, []},
 -            {local_test_fun, test_head_transfer_encoding, []},
 -            {local_test_fun, test_head_response_with_body, []},
 -            {local_test_fun, test_303_response_with_a_body, []},
 -            {local_test_fun, test_binary_headers, []}
 -           ]).
 +		    {"http://www.google.co.uk", get},
 +		    {"http://www.google.com", get},
 +		    {"http://www.google.com", options},
 +                    {"https://mail.google.com", get},
 +		    {"http://www.sun.com", get},
 +		    {"http://www.oracle.com", get},
 +		    {"http://www.bbc.co.uk", get},
 +		    {"http://www.bbc.co.uk", trace},
 +		    {"http://www.bbc.co.uk", options},
 +		    {"http://yaws.hyber.org", get},
 +		    {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
 +		    {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
 +		    {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
 +		    {"http://jigsaw.w3.org/HTTP/connection.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/cc.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
 +		    {"http://jigsaw.w3.org/HTTP/neg", get},
 +		    {"http://jigsaw.w3.org/HTTP/negbad", get},
 +		    {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
 +		    {"http://jigsaw.w3.org/HTTP/300/", get},
 +		    {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
 +		    {"http://jigsaw.w3.org/HTTP/CL/", get},
 +		    {"http://www.httpwatch.com/httpgallery/chunked/", get},
 +                    {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}
 +		   ] ++ ?LOCAL_TESTS).
 +
 +local_unit_tests() ->
-     error_logger:tty(false),
-     unit_tests([], ?LOCAL_TESTS),
-     error_logger:tty(true).
++    unit_tests([], ?LOCAL_TESTS).
  
  unit_tests() ->
-     unit_tests([], ?TEST_LIST).
 -    unit_tests([]).
++    error_logger:tty(false),
++    unit_tests([], ?TEST_LIST),
++    error_logger:tty(true).
  
 -unit_tests(Options) ->
 +unit_tests(Options, Test_list) ->
      application:start(crypto),
      application:start(public_key),
--    application:start(ssl),
++    application:ensure_all_started(ssl),
      (catch ibrowse_test_server:start_server(8181, tcp)),
 -    ibrowse:start(),
 +    application:start(ibrowse),
      Options_1 = Options ++ [{connect_timeout, 5000}],
      Test_timeout = proplists:get_value(test_timeout, Options, 60000),
 -    {Pid, Ref} = erlang:spawn_monitor(?MODULE, unit_tests_1, [self(), Options_1]),
 +    {Pid, Ref} = erlang:spawn_monitor(?MODULE, unit_tests_1, [self(), Options_1, Test_list]),
      receive 
  	{done, Pid} ->
  	    ok;
@@@ -387,6 -371,6 +387,8 @@@ wait_for_resp(Pid) -
  	    {'EXIT', Reason};
  	{'DOWN', _, _, _, _} ->
  	    wait_for_resp(Pid);
++	{'EXIT', _, normal} ->
++	    wait_for_resp(Pid);
  	Msg ->
  	    io:format("Recvd unknown message: ~p~n", [Msg]),
  	    wait_for_resp(Pid)
@@@ -556,74 -539,6 +558,74 @@@ test_303_response_with_a_body(Url) -
      end.
  
  %%------------------------------------------------------------------------------
 +%% Test that retry of requests happens correctly, and that ibrowse doesn't retry
 +%% if there is not enough time left
 +%%------------------------------------------------------------------------------
 +test_retry_of_requests() ->
 +    clear_msg_q(),
 +    test_retry_of_requests("http://localhost:8181/ibrowse_handle_one_request_only_with_delay").
 +
 +test_retry_of_requests(Url) ->
++    reset_ibrowse(),
 +    Timeout_1 = 2050,
 +    Res_1 = test_retry_of_requests(Url, Timeout_1),
 +    case lists:filter(fun({_Pid, {ok, "200", _, _}}) ->
 +                              true;
 +                         (_) -> false
 +                      end, Res_1) of
 +        [_|_] = X ->
 +            Res_1_1 = Res_1 -- X,
 +            case lists:all(
 +                   fun({_Pid, {error, retry_later}}) ->
 +                           true;
 +                      (_) ->
 +                           false
 +                   end, Res_1_1) of
 +                true ->
 +                    ok;
 +                false ->
 +                    exit({failed, Timeout_1, Res_1})
 +            end;
 +        _ ->
 +            exit({failed, Timeout_1, Res_1})
 +    end,
-     reset_ibrowse(),
 +    Timeout_2 = 2200,
 +    Res_2 = test_retry_of_requests(Url, Timeout_2),
 +    case lists:filter(fun({_Pid, {ok, "200", _, _}}) ->
 +                              true;
 +                         (_) -> false
 +                      end, Res_2) of
 +        [_|_] = Res_2_X ->
 +            Res_2_1 = Res_2 -- Res_2_X,
 +            case lists:all(
 +                   fun({_Pid, {error, X_err_2}}) ->
 +                           (X_err_2 == retry_later) orelse (X_err_2 == req_timedout);
 +                      (_) ->
 +                           false
 +                   end, Res_2_1) of
 +                true ->
 +                    ok;
 +                false ->
-                     exit({failed, Timeout_2, Res_2})
++                    exit({failed, {?MODULE, ?LINE}, Timeout_2, Res_2})
 +            end;
 +        _ ->
-             exit({failed, Timeout_2, Res_2})
++            exit({failed, {?MODULE, ?LINE}, Timeout_2, Res_2})
 +    end,
 +    success.
 +
 +test_retry_of_requests(Url, Timeout) ->
 +    #url{host = Host, port = Port} = ibrowse_lib:parse_url(Url),
 +    ibrowse:set_max_sessions(Host, Port, 1),
 +    Parent = self(),
 +    Pids = lists:map(fun(_) ->
 +                        spawn(fun() ->
 +                                 Res = (catch ibrowse:send_req(Url, [], get, [], [], Timeout)),
 +                                 Parent ! {self(), Res}
 +                              end)
 +                     end, lists:seq(1,10)),
 +    accumulate_worker_resp(Pids).
 +
 +%%------------------------------------------------------------------------------
  %% Test what happens when the request at the head of a pipeline times out
  %%------------------------------------------------------------------------------
  test_pipeline_head_timeout() ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/8494e943/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --cc test/ibrowse_test_server.erl
index 1d72210,dc0d7e2..7025286
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@@ -15,29 -21,26 +21,30 @@@
  
  start_server(Port, Sock_type) ->
      Fun = fun() ->
-         Proc_name = server_proc_name(Port),
-         case whereis(Proc_name) of
-             undefined ->
-                 register(Proc_name, self()),
-                 case do_listen(Sock_type, Port, [{active, false},
-                     {reuseaddr, true},
-                     {nodelay, true},
-                     {packet, http}]) of
-                     {ok, Sock} ->
-                         do_trace("Server listening on port: ~p~n", [Port]),
-                         accept_loop(Sock, Sock_type);
-                     Err ->
-                         erlang:error(
 -                  Name = server_proc_name(Port),
 -                  register(Name, self()),
 -                  ets:new(?CONN_PIPELINE_DEPTH, [named_table, public, set]),
 -                  case do_listen(Sock_type, Port, [{active, false},
 -                                                   {reuseaddr, true},
 -                                                   {nodelay, true},
 -                                                   {packet, http}]) of
 -                      {ok, Sock} ->
 -                          do_trace("Server listening on port: ~p~n", [Port]),
 -                          accept_loop(Sock, Sock_type);
 -                      Err ->
 -                          erlang:error(
--                            lists:flatten(
-                                 io_lib:format(
-                                     "Failed to start server on port ~p. ~p~n",
-                                     [Port, Err]))),
-                         exit({listen_error, Err})
-                 end;
-             _X ->
-                 ok
-         end
-     end,
 -                              io_lib:format(
 -                                "Failed to start server on port ~p. ~p~n",
 -                                [Port, Err]))),
 -                          exit({listen_error, Err})
 -                  end,
 -                  unregister(Name)
 -          end,
++		  Proc_name = server_proc_name(Port),
++		  case whereis(Proc_name) of
++		      undefined ->
++			  register(Proc_name, self()),
++			  ets:new(?CONN_PIPELINE_DEPTH, [named_table, public, set]),
++			  case do_listen(Sock_type, Port, [{active, false},
++							   {reuseaddr, true},
++							   {nodelay, true},
++							   {packet, http}]) of
++			      {ok, Sock} ->
++				  do_trace("Server listening on port: ~p~n", [Port]),
++				  accept_loop(Sock, Sock_type);
++			      Err ->
++				  erlang:error(
++				    lists:flatten(
++				      io_lib:format(
++					"Failed to start server on port ~p. ~p~n",
++					[Port, Err]))),
++				  exit({listen_error, Err})
++			  end;
++		      _X ->
++			  ok
++		  end
++	  end,
      spawn_link(Fun).
  
  stop_server(Port) ->
@@@ -86,6 -105,7 +109,7 @@@ setopts(Sock, ssl, Opts) -
  server_loop(Sock, Sock_type, #request{headers = Headers} = Req) ->
      receive
          {http, Sock, {http_request, HttpMethod, HttpUri, HttpVersion}} ->
 -            ets:update_counter(?CONN_PIPELINE_DEPTH, self(), 1),
++            catch ets:update_counter(?CONN_PIPELINE_DEPTH, self(), 1),
              server_loop(Sock, Sock_type, Req#request{method = HttpMethod,
                                                       uri = HttpUri,
                                                       version = HttpVersion});
@@@ -93,15 -113,16 +117,18 @@@
              server_loop(Sock, Sock_type, Req#request{headers = [H | Headers]});
          {http, Sock, http_eoh} ->
              case process_request(Sock, Sock_type, Req) of
 +                close_connection ->
 +                    gen_tcp:shutdown(Sock, read_write);
+                 not_done ->
+                     ok;
                  _ ->
-                     server_loop(Sock, Sock_type, #request{})
-             end;
 -                    ets:update_counter(?CONN_PIPELINE_DEPTH, self(), -1)
++                    catch ets:update_counter(?CONN_PIPELINE_DEPTH, self(), -1)
+             end,
+             server_loop(Sock, Sock_type, #request{});
          {http, Sock, {http_error, Err}} ->
 -            do_trace("Error parsing HTTP request:~n"
 -                     "Req so far : ~p~n"
 -                     "Err        : ", [Req, Err]),
 +            io:format("Error parsing HTTP request:~n"
 +                      "Req so far : ~p~n"
 +                      "Err        : ~p", [Req, Err]),
              exit({http_error, Err});
          {setopts, Opts} ->
              setopts(Sock, Sock_type, Opts),
@@@ -109,12 -130,10 +136,10 @@@
          {tcp_closed, Sock} ->
              do_trace("Client closed connection~n", []),
              ok;
-         stop ->
-             ok;
          Other ->
 -            do_trace("Recvd unknown msg: ~p~n", [Other]),
 +            io:format("Recvd unknown msg: ~p~n", [Other]),
              exit({unknown_msg, Other})
 -    after 5000 ->
 +    after 120000 ->
              do_trace("Timing out client connection~n", []),
              ok
      end.
@@@ -200,21 -218,8 +224,23 @@@ process_request(Sock, Sock_type
                           uri = {abs_path, "/ibrowse_303_with_body_test"}}) ->
      Resp = <<"HTTP/1.1 303 See Other\r\nLocation: http://example.org\r\nContent-Length: 5\r\n\r\nabcde">>,
      do_send(Sock, Sock_type, Resp);
 +process_request(Sock, Sock_type,
 +    #request{method='GET',
 +        headers = _Headers,
 +        uri = {abs_path, "/ibrowse_handle_one_request_only_with_delay"}}) ->
 +    timer:sleep(2000),
 +    Resp = <<"HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\nConnection: close\r\n\r\n">>,
 +    do_send(Sock, Sock_type, Resp),
 +    close_connection;
 +process_request(Sock, Sock_type,
 +    #request{method='GET',
 +        headers = _Headers,
 +        uri = {abs_path, "/ibrowse_handle_one_request_only"}}) ->
 +    Resp = <<"HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\nConnection: close\r\n\r\n">>,
 +    do_send(Sock, Sock_type, Resp),
 +    close_connection;
+ process_request(_Sock, _Sock_type, #request{uri = {abs_path, "/never_respond"} } ) ->
+     not_done;
  process_request(Sock, Sock_type, Req) ->
      do_trace("Recvd req: ~p~n", [Req]),
      Resp = <<"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n">>,


[18/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Rename 'Digest' to 'Basic'

Digest could mean HTTP Digest Authentication which is completely
different from what we call Digest currently. Renaming this is
essential to implement the actual HTTP Digest Authentication


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

Branch: refs/heads/upstream
Commit: e478d010259fcc2558afec7b50712d0507710ed7
Parents: 58007c7
Author: Shankar Dhanasekaran <sh...@opendrops.com>
Authored: Fri Jun 26 01:31:39 2015 +0530
Committer: Shankar Dhanasekaran <sh...@opendrops.com>
Committed: Fri Jun 26 10:17:10 2015 +0530

----------------------------------------------------------------------
 src/ibrowse_http_client.erl | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/e478d010/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index b9e6c97..5e93539 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -41,7 +41,7 @@
 
 -record(state, {host, port, connect_timeout,
                 inactivity_timer_ref,
-                use_proxy = false, proxy_auth_digest,
+                use_proxy = false, proxy_auth_basic,
                 ssl_options = [], is_ssl = false, socket,
                 proxy_tunnel_setup = false,
                 tunnel_setup_queue = [],
@@ -695,10 +695,10 @@ send_req_1(From,
             PHost ->
                 ProxyUser     = get_value(proxy_user, Options, []),
                 ProxyPassword = get_value(proxy_password, Options, []),
-                Digest        = http_auth_digest(ProxyUser, ProxyPassword),
+                AuthBasic        = http_auth_basic(ProxyUser, ProxyPassword),
                 {PHost, get_value(proxy_port, Options, 80),
                  State#state{use_proxy = true,
-                             proxy_auth_digest = Digest}}
+                             proxy_auth_basic = AuthBasic}}
         end,
     State_2 = check_ssl_options(Options, State_1),
     do_trace("Connecting...~n", []),
@@ -919,23 +919,23 @@ add_auth_headers(#url{username = User,
                             undefined ->
                                 Headers;
                             {U,P} ->
-                                [{"Authorization", ["Basic ", http_auth_digest(U, P)]} | Headers]
+                                [{"Authorization", ["Basic ", http_auth_basic(U, P)]} | Headers]
                         end;
                     _ ->
-                        [{"Authorization", ["Basic ", http_auth_digest(User, UPw)]} | Headers]
+                        [{"Authorization", ["Basic ", http_auth_basic(User, UPw)]} | Headers]
                 end,
     add_proxy_auth_headers(State, Headers_1).
 
 add_proxy_auth_headers(#state{use_proxy = false}, Headers) ->
     Headers;
-add_proxy_auth_headers(#state{proxy_auth_digest = []}, Headers) ->
+add_proxy_auth_headers(#state{proxy_auth_basic = []}, Headers) ->
     Headers;
-add_proxy_auth_headers(#state{proxy_auth_digest = Auth_digest}, Headers) ->
-    [{"Proxy-Authorization", ["Basic ", Auth_digest]} | Headers].
+add_proxy_auth_headers(#state{proxy_auth_basic = Auth_basic}, Headers) ->
+    [{"Proxy-Authorization", ["Basic ", Auth_basic]} | Headers].
 
-http_auth_digest([], []) ->
+http_auth_basic([], []) ->
     [];
-http_auth_digest(Username, Password) ->
+http_auth_basic(Username, Password) ->
     ibrowse_lib:encode_base64(Username ++ [$: | Password]).
 
 make_request(Method, Headers, AbsPath, RelPath, Body, Options,


[15/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Merge pull request #126 from StoneCypher/master

removes doubled repl prompt

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

Branch: refs/heads/upstream
Commit: 04566c70016f5a2a9a8b8ba6e6adf429e399c260
Parents: 200b7eb d713f20
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Tue May 12 21:06:34 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Tue May 12 21:06:34 2015 +0100

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[21/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Release 4.1.2


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

Branch: refs/heads/upstream
Commit: ea3305d21f37eced4fac290f64b068e56df7de80
Parents: 5ee4a80
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Aug 3 07:23:12 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Aug 3 07:23:12 2015 +0100

----------------------------------------------------------------------
 CHANGELOG           | 9 +++++++++
 CONTRIBUTORS        | 3 +++
 README.md           | 2 +-
 src/ibrowse.app.src | 2 +-
 4 files changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ea3305d2/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index aaedf0f..0d9ee11 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,14 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
+03-08-2015 - v4.1.2
+             * R18 compatibility fix
+               https://github.com/cmullaparthi/ibrowse/issues/129
+             * Add max_attempts option
+               https://github.com/cmullaparthi/ibrowse/pull/125
+             * Fix for https://github.com/cmullaparthi/ibrowse/pull/120
+             * Enhanced SOCKS5 support
+               https://github.com/cmullaparthi/ibrowse/pull/117
+
 10-07-2014 - v4.1.1
              * Added support for accepting binaries as header names
              * Fix for https://github.com/cmullaparthi/ibrowse/issues/110

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ea3305d2/CONTRIBUTORS
----------------------------------------------------------------------
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 21e8d06..c25d1fb 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -23,6 +23,7 @@ Joseph Wayne Norton
 Karol Skocik
 Konstantin Nikiforov
 Kostis Sagonas
+Marcelo Gornstein (https://github.com/marcelog)
 Matthew Reilly
 Michael Terry
 Oscar Hellstr?m
@@ -40,6 +41,7 @@ Seth Falcon
 Steve Vinoski
 Thomas Lindgren
 Youn?s Hafri
+Yury Gargay (https://github.com/surik)
 fholzhauser (https://github.com/fholzhauser/)
 hyperthunk (https://github.com/hyperthunk/)
 Mistagrooves (https://github.com/Mistagrooves/)
@@ -56,4 +58,5 @@ https://github.com/pib
 https://github.com/puzza007
 https://github.com/rflynn
 https://github.com/Vagabond
+https://github.com/divolgin
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ea3305d2/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 19773fd..ee0713c 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.1.1
+**Current Version:** 4.1.2
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ea3305d2/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 70ed7b2..65fb5a2 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.1.1"},
+         {vsn, "4.1.2"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},


[10/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Made test server less chatty while shutting down

Connections warned of badargs to ets:delete
when shutting the server down with open connections;
created noise while reviewing test results.


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

Branch: refs/heads/upstream
Commit: 1a680f00e0c053cb81424e200f6657cdd0ad71ca
Parents: 247dd56
Author: benjaminplee <ya...@gmail.com>
Authored: Fri Nov 21 14:38:12 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Fri Nov 21 14:38:12 2014 +0000

----------------------------------------------------------------------
 test/ibrowse_test_server.erl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1a680f00/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index 1f5202f..dc0d7e2 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -85,11 +85,11 @@ accept_loop(Sock, Sock_type) ->
     end.
 
 connection(Conn, Sock_type) ->
-    ets:insert(?CONN_PIPELINE_DEPTH, {self(), 0}),
+    catch ets:insert(?CONN_PIPELINE_DEPTH, {self(), 0}),
     try
         server_loop(Conn, Sock_type, #request{})
     after
-        ets:delete(?CONN_PIPELINE_DEPTH, self())
+        catch ets:delete(?CONN_PIPELINE_DEPTH, self())
     end.
 
 set_controlling_process(Sock, tcp, Pid) ->


[34/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
update doc


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

Branch: refs/heads/upstream
Commit: a2bd3485ec24e67d5a28dbd7cfc94bd852dc4a2b
Parents: 8734ed3
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:43:01 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:43:01 2015 +0100

----------------------------------------------------------------------
 doc/edoc-info                |   4 ++
 doc/erlang.png               | Bin 0 -> 2109 bytes
 doc/ibrowse_app.html         |  38 +++++++++++++++
 doc/ibrowse_http_client.html |  98 ++++++++++++++++++++++++++++++++++++++
 doc/ibrowse_lb.html          |  80 +++++++++++++++++++++++++++++++
 doc/ibrowse_socks5.html      |  31 ++++++++++++
 doc/ibrowse_sup.html         |  38 +++++++++++++++
 doc/index.html               |  17 +++++++
 doc/modules-frame.html       |  18 +++++++
 doc/overview-summary.html    |  16 +++++++
 doc/stylesheet.css           |  55 +++++++++++++++++++++
 11 files changed, 395 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/edoc-info
----------------------------------------------------------------------
diff --git a/doc/edoc-info b/doc/edoc-info
new file mode 100644
index 0000000..8d400b5
--- /dev/null
+++ b/doc/edoc-info
@@ -0,0 +1,4 @@
+%% encoding: UTF-8
+{application,ibrowse}.
+{modules,[ibrowse,ibrowse_app,ibrowse_http_client,ibrowse_lb,ibrowse_lib,
+          ibrowse_socks5,ibrowse_sup]}.

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/erlang.png
----------------------------------------------------------------------
diff --git a/doc/erlang.png b/doc/erlang.png
new file mode 100644
index 0000000..987a618
Binary files /dev/null and b/doc/erlang.png differ

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/ibrowse_app.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_app.html b/doc/ibrowse_app.html
new file mode 100644
index 0000000..368a4b3
--- /dev/null
+++ b/doc/ibrowse_app.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Module ibrowse_app</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module ibrowse_app</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="application.html"><tt>application</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="start-2">start/2</a></h3>
+<div class="spec">
+<p><tt>start(Type, StartArgs) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="stop-1">stop/1</a></h3>
+<div class="spec">
+<p><tt>stop(State) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/ibrowse_http_client.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_http_client.html b/doc/ibrowse_http_client.html
new file mode 100644
index 0000000..66f0f53
--- /dev/null
+++ b/doc/ibrowse_http_client.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Module ibrowse_http_client</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module ibrowse_http_client</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#send_req-7">send_req/7</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start-1">start/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
+<div class="spec">
+<p><tt>code_change(OldVsn, State, Extra) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
+<div class="spec">
+<p><tt>handle_call(Request, From, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
+<div class="spec">
+<p><tt>handle_cast(Msg, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
+<div class="spec">
+<p><tt>handle_info(Info, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="init-1">init/1</a></h3>
+<div class="spec">
+<p><tt>init(Url) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="send_req-7">send_req/7</a></h3>
+<div class="spec">
+<p><tt>send_req(Conn_Pid, Url, Headers, Method, Body, Options, Timeout) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start-1">start/1</a></h3>
+<div class="spec">
+<p><tt>start(Args) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start-2">start/2</a></h3>
+<div class="spec">
+<p><tt>start(Args, Options) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
+<div class="spec">
+<p><tt>start_link(Args) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-2">start_link/2</a></h3>
+<div class="spec">
+<p><tt>start_link(Args, Options) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="stop-1">stop/1</a></h3>
+<div class="spec">
+<p><tt>stop(Conn_pid) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
+<div class="spec">
+<p><tt>terminate(Reason, State) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/ibrowse_lb.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_lb.html b/doc/ibrowse_lb.html
new file mode 100644
index 0000000..b115982
--- /dev/null
+++ b/doc/ibrowse_lb.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Module ibrowse_lb</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module ibrowse_lb</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#spawn_connection-6">spawn_connection/6</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
+<div class="spec">
+<p><tt>code_change(OldVsn, State, Extra) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
+<div class="spec">
+<p><tt>handle_call(Request, From, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
+<div class="spec">
+<p><tt>handle_cast(Msg, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
+<div class="spec">
+<p><tt>handle_info(Info, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="init-1">init/1</a></h3>
+<div class="spec">
+<p><tt>init(X1) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="spawn_connection-6">spawn_connection/6</a></h3>
+<div class="spec">
+<p><tt>spawn_connection(Lb_pid, Url, Max_sessions, Max_pipeline_size, SSL_options, Process_options) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
+<div class="spec">
+<p><tt>start_link(Args) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="stop-1">stop/1</a></h3>
+<div class="spec">
+<p><tt>stop(Lb_pid) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
+<div class="spec">
+<p><tt>terminate(Reason, State) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/ibrowse_socks5.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_socks5.html b/doc/ibrowse_socks5.html
new file mode 100644
index 0000000..bddd420
--- /dev/null
+++ b/doc/ibrowse_socks5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Module ibrowse_socks5</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module ibrowse_socks5</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#connect-5">connect/5</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="connect-5">connect/5</a></h3>
+<div class="spec">
+<p><tt>connect(Host, Port, Options, SockOptions, Timeout) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/ibrowse_sup.html
----------------------------------------------------------------------
diff --git a/doc/ibrowse_sup.html b/doc/ibrowse_sup.html
new file mode 100644
index 0000000..0e5226d
--- /dev/null
+++ b/doc/ibrowse_sup.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Module ibrowse_sup</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module ibrowse_sup</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="init-1">init/1</a></h3>
+<div class="spec">
+<p><tt>init(X1) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-0">start_link/0</a></h3>
+<div class="spec">
+<p><tt>start_link() -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/index.html
----------------------------------------------------------------------
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..657b98c
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The ibrowse application</title>
+</head>
+<frameset cols="20%,80%">
+<frame src="modules-frame.html" name="modulesFrame" title="">
+
+<frame src="overview-summary.html" name="overviewFrame" title="">
+<noframes>
+<h2>This page uses frames</h2>
+<p>Your browser does not accept frames.
+<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead.
+</p>
+</noframes>
+</frameset>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/modules-frame.html
----------------------------------------------------------------------
diff --git a/doc/modules-frame.html b/doc/modules-frame.html
new file mode 100644
index 0000000..3d6f50c
--- /dev/null
+++ b/doc/modules-frame.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The ibrowse application</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<h2 class="indextitle">Modules</h2>
+<table width="100%" border="0" summary="list of modules">
+<tr><td><a href="ibrowse.html" target="overviewFrame" class="module">ibrowse</a></td></tr>
+<tr><td><a href="ibrowse_app.html" target="overviewFrame" class="module">ibrowse_app</a></td></tr>
+<tr><td><a href="ibrowse_http_client.html" target="overviewFrame" class="module">ibrowse_http_client</a></td></tr>
+<tr><td><a href="ibrowse_lb.html" target="overviewFrame" class="module">ibrowse_lb</a></td></tr>
+<tr><td><a href="ibrowse_lib.html" target="overviewFrame" class="module">ibrowse_lib</a></td></tr>
+<tr><td><a href="ibrowse_socks5.html" target="overviewFrame" class="module">ibrowse_socks5</a></td></tr>
+<tr><td><a href="ibrowse_sup.html" target="overviewFrame" class="module">ibrowse_sup</a></td></tr></table>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/overview-summary.html
----------------------------------------------------------------------
diff --git a/doc/overview-summary.html b/doc/overview-summary.html
new file mode 100644
index 0000000..b563096
--- /dev/null
+++ b/doc/overview-summary.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The ibrowse application</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<h1>The ibrowse application</h1>
+
+<hr>
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Nov 6 2015, 11:40:24.</i></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a2bd3485/doc/stylesheet.css
----------------------------------------------------------------------
diff --git a/doc/stylesheet.css b/doc/stylesheet.css
new file mode 100644
index 0000000..ab170c0
--- /dev/null
+++ b/doc/stylesheet.css
@@ -0,0 +1,55 @@
+/* standard EDoc style sheet */
+body {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+      	margin-left: .25in;
+       	margin-right: .2in;
+       	margin-top: 0.2in;
+       	margin-bottom: 0.2in;
+       	color: #000000;
+       	background-color: #ffffff;
+}
+h1,h2 {
+ 	margin-left: -0.2in;
+}
+div.navbar {
+	background-color: #add8e6;
+	padding: 0.2em;
+}
+h2.indextitle {
+	padding: 0.4em;
+	background-color: #add8e6;
+}
+h3.function,h3.typedecl {
+	background-color: #add8e6;
+ 	padding-left: 1em;
+}
+div.spec {
+ 	margin-left: 2em;
+	background-color: #eeeeee;
+}
+a.module {
+	text-decoration:none
+}
+a.module:hover {
+	background-color: #eeeeee;
+}
+ul.definitions {
+	list-style-type: none;
+}
+ul.index {
+	list-style-type: none;
+	background-color: #eeeeee;
+}
+
+/*
+ * Minor style tweaks
+ */
+ul {
+	list-style-type: square;
+}
+table {
+	border-collapse: collapse;
+}
+td {
+	padding: 3
+}


[23/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Compile test modules


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

Branch: refs/heads/upstream
Commit: 3a4044d4c185010f35c000bd94a62b23b77a91f0
Parents: 8494e94
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Mon Sep 28 08:27:35 2015 +0100
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Mon Sep 28 08:27:35 2015 +0100

----------------------------------------------------------------------
 Makefile | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/3a4044d4/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index 28dfda8..d2e61c6 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@ eunit_test: all
 	./rebar eunit
 
 test: all
+	cd test; erl -pa ../../ibrowse/ebin -make; cd ../; \
 	erl -noshell -pa test -pa ebin -s ibrowse_test unit_tests \
 	-s ibrowse_test verify_chunked_streaming \
 	-s ibrowse_test test_chunked_streaming_once \


[04/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Whitespace cleanup


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

Branch: refs/heads/upstream
Commit: e4d41ec4535fc32081d286d143b15b15185e1692
Parents: f1244ab
Author: benjaminplee <ya...@gmail.com>
Authored: Thu Nov 20 17:02:29 2014 +0000
Committer: benjaminplee <ya...@gmail.com>
Committed: Thu Nov 20 17:02:29 2014 +0000

----------------------------------------------------------------------
 test/ibrowse_test.erl | 72 +++++++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/e4d41ec4/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 407ffcb..4ddb9c1 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -208,42 +208,42 @@ dump_errors(Key, Iod) ->
 %% Unit Tests
 %%------------------------------------------------------------------------------
 -define(TEST_LIST, [{"http://intranet/messenger", get},
-		    {"http://www.google.co.uk", get},
-		    {"http://www.google.com", get},
-		    {"http://www.google.com", options},
-                    {"https://mail.google.com", get},
-		    {"http://www.sun.com", get},
-		    {"http://www.oracle.com", get},
-		    {"http://www.bbc.co.uk", get},
-		    {"http://www.bbc.co.uk", trace},
-		    {"http://www.bbc.co.uk", options},
-		    {"http://yaws.hyber.org", get},
-		    {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
-		    {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
-		    {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
-		    {"http://jigsaw.w3.org/HTTP/connection.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
-		    {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
-		    {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
-		    {"http://jigsaw.w3.org/HTTP/neg", get},
-		    {"http://jigsaw.w3.org/HTTP/negbad", get},
-		    {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
-		    {"http://jigsaw.w3.org/HTTP/300/", get},
-		    {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
-		    {"http://jigsaw.w3.org/HTTP/CL/", get},
-		    {"http://www.httpwatch.com/httpgallery/chunked/", get},
-                    {"https://github.com", get, [{ssl_options, [{depth, 2}]}]},
-                    {local_test_fun, test_20122010, []},
-                    {local_test_fun, test_pipeline_head_timeout, []},
-                    {local_test_fun, test_head_transfer_encoding, []},
-                    {local_test_fun, test_head_response_with_body, []},
-                    {local_test_fun, test_303_response_with_a_body, []},
-                    {local_test_fun, test_binary_headers, []}
-		   ]).
+            {"http://www.google.co.uk", get},
+            {"http://www.google.com", get},
+            {"http://www.google.com", options},
+            {"https://mail.google.com", get},
+            {"http://www.sun.com", get},
+            {"http://www.oracle.com", get},
+            {"http://www.bbc.co.uk", get},
+            {"http://www.bbc.co.uk", trace},
+            {"http://www.bbc.co.uk", options},
+            {"http://yaws.hyber.org", get},
+            {"http://jigsaw.w3.org/HTTP/ChunkedScript", get},
+            {"http://jigsaw.w3.org/HTTP/TE/foo.txt", get},
+            {"http://jigsaw.w3.org/HTTP/TE/bar.txt", get},
+            {"http://jigsaw.w3.org/HTTP/connection.html", get},
+            {"http://jigsaw.w3.org/HTTP/cc.html", get},
+            {"http://jigsaw.w3.org/HTTP/cc-private.html", get},
+            {"http://jigsaw.w3.org/HTTP/cc-proxy-revalidate.html", get},
+            {"http://jigsaw.w3.org/HTTP/cc-nocache.html", get},
+            {"http://jigsaw.w3.org/HTTP/h-content-md5.html", get},
+            {"http://jigsaw.w3.org/HTTP/h-retry-after.html", get},
+            {"http://jigsaw.w3.org/HTTP/h-retry-after-date.html", get},
+            {"http://jigsaw.w3.org/HTTP/neg", get},
+            {"http://jigsaw.w3.org/HTTP/negbad", get},
+            {"http://jigsaw.w3.org/HTTP/400/toolong/", get},
+            {"http://jigsaw.w3.org/HTTP/300/", get},
+            {"http://jigsaw.w3.org/HTTP/Basic/", get, [{basic_auth, {"guest", "guest"}}]},
+            {"http://jigsaw.w3.org/HTTP/CL/", get},
+            {"http://www.httpwatch.com/httpgallery/chunked/", get},
+            {"https://github.com", get, [{ssl_options, [{depth, 2}]}]},
+            {local_test_fun, test_20122010, []},
+            {local_test_fun, test_pipeline_head_timeout, []},
+            {local_test_fun, test_head_transfer_encoding, []},
+            {local_test_fun, test_head_response_with_body, []},
+            {local_test_fun, test_303_response_with_a_body, []},
+            {local_test_fun, test_binary_headers, []}
+           ]).
 
 unit_tests() ->
     unit_tests([]).


[14/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
removes doubled repl prompt

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

Branch: refs/heads/upstream
Commit: d713f209d00aec38465d5c0bd8904a2bfad7b8d5
Parents: 200b7eb
Author: John Haugeland <st...@gmail.com>
Authored: Tue May 12 11:23:03 2015 -0700
Committer: John Haugeland <st...@gmail.com>
Committed: Tue May 12 11:23:03 2015 -0700

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/d713f209/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index b68f197..19773fd 100644
--- a/README.md
+++ b/README.md
@@ -263,7 +263,7 @@ Example of a `TRACE` request. Very interesting! yaws.hyber.org didn't
 support this. Nor did www.google.com. But good old BBC supports this:
 
 ```erlang
-35> 37> ibrowse:send_req("http://www.bbc.co.uk/", [], trace, [],
+37> ibrowse:send_req("http://www.bbc.co.uk/", [], trace, [],
                          [{proxy_user, "XXXXX"},
                           {proxy_password, "XXXXX"},
                           {proxy_host, "proxy"},


[31/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
use global rebar


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

Branch: refs/heads/upstream
Commit: 45099028d824444b0e43b837671f9cbc385c7efa
Parents: 94fab9a
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:36:09 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:37:09 2015 +0100

----------------------------------------------------------------------
 Makefile |  10 ++++++----
 rebar    | Bin 188026 -> 0 bytes
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/45099028/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index d2e61c6..4df166b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,20 +3,22 @@ IBROWSE_VSN = $(shell sed -n 's/.*{vsn,.*"\(.*\)"}.*/\1/p' src/ibrowse.app.src)
 DIALYZER_PLT=$(CURDIR)/.dialyzer_plt
 DIALYZER_APPS=erts kernel stdlib ssl crypto public_key
 
+REBAR ?= $(shell which rebar)
+
 all: compile
 
 compile:
-	./rebar compile
+	$(REBAR) compile
 
 clean:
-	./rebar clean
+	$(REBAR) clean
 
 install: compile
 	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
 	cp -r ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
 
 eunit_test: all
-	./rebar eunit
+	$(REBAR) eunit
 
 test: all
 	cd test; erl -pa ../../ibrowse/ebin -make; cd ../; \
@@ -26,7 +28,7 @@ test: all
 	-s erlang halt
 
 xref: all
-	./rebar xref
+	$(REBAR) xref
 
 docs:
 	erl -noshell \

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/45099028/rebar
----------------------------------------------------------------------
diff --git a/rebar b/rebar
deleted file mode 100755
index 8e4deb6..0000000
Binary files a/rebar and /dev/null differ


[35/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
fix travis tests


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

Branch: refs/heads/upstream
Commit: 82f61864a06b862e445965834fde18c3784c5090
Parents: a2bd348
Author: benoitc <bc...@gmail.com>
Authored: Fri Nov 6 11:49:49 2015 +0100
Committer: benoitc <bc...@gmail.com>
Committed: Fri Nov 6 11:49:49 2015 +0100

----------------------------------------------------------------------
 .travis.yml         | 12 +++++++++++-
 bootstrap_travis.sh |  5 +++++
 2 files changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/82f61864/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 4b98f46..0861069 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,14 @@
 language: erlang
 otp_release:
    - R16B
-script: "make test"
+   - R16B03-1
+   - 17.0
+   - 17.1
+   - 18.0
+   - 18.1
+before_script:
+  - curl -X PUT localhost:5984/couchbeam_testdb
+  - curl -X PUT localhost:5984/couchbeam_testdb2
+  - curl -X PUT localhost:5984/couchbeam_testdb3
+  - "./bootstrap_travis.sh"
+script: "./rebar3 eunit"

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/82f61864/bootstrap_travis.sh
----------------------------------------------------------------------
diff --git a/bootstrap_travis.sh b/bootstrap_travis.sh
new file mode 100755
index 0000000..a222df3
--- /dev/null
+++ b/bootstrap_travis.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+curl -O -L https://s3.amazonaws.com/rebar3/rebar3
+chmod +x rebar3
+./rebar3 update
\ No newline at end of file


[50/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Bug fix for spurious timeout messages being sent to the client in certain cases. Other cleanup


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

Branch: refs/heads/upstream
Commit: b28542d1e326ba44bcfaf7fd6d3c7f8761d20f08
Parents: 07e47c6
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Jun 7 16:43:50 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Jun 7 16:43:50 2016 +0100

----------------------------------------------------------------------
 .travis.yml                 |    1 +
 CHANGELOG                   |    8 +
 Makefile                    |   40 +-
 README.md                   |    2 +-
 erlang.mk                   | 1279 ++++++++++++++++++++++++++++++++++++++
 src/ibrowse.app.src         |    3 +-
 src/ibrowse.erl             |   11 +-
 src/ibrowse_http_client.erl |   13 +-
 src/ibrowse_lib.erl         |   25 +-
 test/Makefile               |    3 +-
 10 files changed, 1334 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 4875662..2dd9ad6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ otp_release:
    - 17.1
    - 18.0
    - 18.1
+   - 18.2.1
 before_script:
   - "./bootstrap_travis.sh"
 script: "./rebar3 eunit"

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index c56a57d..69e3750 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,14 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
 
+07-06-2016 - v4.3
+             * Adopted erlang.mk for compiling. I find it easier to understand
+               how 'make' behaves compared to rebar. This repo can still be built
+               using rebar for those who prefer it
+             * Removed references to lager. Introduced configurable logging function
+             * Fixed an issue where the calling process was getting an extra
+               spurious timeout message when the request was timing out
+
 19-04-2016 - v4.2.4
              * Fixed travis-ci build as it was failing in running tests. 
                No code changes to ibrowse

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index f67da07..0ff4c2d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,10 @@
-IBROWSE_VSN = $(shell sed -n 's/.*{vsn,.*"\(.*\)"}.*/\1/p' src/ibrowse.app.src)
+PROJECT=ibrowse
+PLT_APPS=erts kernel stdlib ssl crypto public_key
+TEST_ERLC_OPTS=-pa ../ibrowse/ebin
 
-DIALYZER_PLT=$(CURDIR)/.dialyzer_plt
-DIALYZER_APPS=erts kernel stdlib ssl crypto public_key
+include erlang.mk
 
-REBAR ?= $(shell which rebar3)
-
-all: compile
-
-compile:
-	$(REBAR) compile
-
-clean:
-	@$(REBAR) clean && cd test && make clean && cd ..
-
-test: compile unit_tests eunit
+test: app eunit unit_tests old_tests
 	@echo "====================================================="
 
 unit_tests:
@@ -25,24 +16,3 @@ old_tests:
 	@echo "====================================================="
 	@echo "Running old tests..."
 	@cd test && make old_tests && cd ..
-
-eunit:
-	@echo "====================================================="
-	@echo "Running eunit tests..."
-	$(REBAR) eunit
-
-xref: all
-	$(REBAR) xref
-
-docs:
-	$(REBAR) edoc
-
-dialyzer:
-	$(REBAR) dialyzer
-
-
-install: compile
-	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
-	cp -r _build/lib/default/ibrowse/ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
-
-.PHONY: test docs

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index a3985df..286f60e 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.2.4
+**Current Version:** 4.3
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/erlang.mk
----------------------------------------------------------------------
diff --git a/erlang.mk b/erlang.mk
new file mode 100644
index 0000000..972c5d1
--- /dev/null
+++ b/erlang.mk
@@ -0,0 +1,1279 @@
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+.PHONY: all deps rel app docs tests clean distclean help erlang-mk
+
+ERLANG_MK_VERSION = 1
+
+# Core configuration.
+
+PROJECT ?= $(notdir $(CURDIR))
+PROJECT := $(strip $(PROJECT))
+
+# Verbosity.
+
+V ?= 0
+
+gen_verbose_0 = @echo " GEN   " $@;
+gen_verbose = $(gen_verbose_$(V))
+
+# "erl" command.
+
+ERL = erl +A0 -noinput -boot start_clean
+
+# Core targets.
+
+ifneq ($(words $(MAKECMDGOALS)),1)
+.NOTPARALLEL:
+endif
+
+all:: deps
+	@$(MAKE) --no-print-directory app
+	#@$(MAKE) --no-print-directory rel
+
+# Noop to avoid a Make warning when there's nothing to do.
+#rel::
+#	@echo -n
+
+clean:: clean-crashdump
+
+clean-crashdump:
+ifneq ($(wildcard erl_crash.dump),)
+	$(gen_verbose) rm -f erl_crash.dump
+endif
+
+distclean:: clean
+
+help::
+	@printf "%s\n" \
+		"erlang.mk (version $(ERLANG_MK_VERSION)) is distributed under the terms of the ISC License." \
+		"Copyright (c) 2013-2014 Lo�c Hoguin <es...@ninenines.eu>" \
+		"" \
+		"Usage: [V=1] make [-jNUM] [target]" \
+		"" \
+		"Core targets:" \
+		"  all         Run deps, app and rel targets in that order" \
+		"  deps        Fetch dependencies (if needed) and compile them" \
+		"  app         Compile the project" \
+		"  rel         Build a release for this project, if applicable" \
+		"  docs        Build the documentation for this project" \
+		"  tests       Run the tests for this project" \
+		"  clean       Delete temporary and output files from most targets" \
+		"  distclean   Delete all temporary and output files" \
+		"  help        Display this help and exit" \
+		"" \
+		"The target clean only removes files that are commonly removed." \
+		"Dependencies and releases are left untouched." \
+		"" \
+		"Setting V=1 when calling make enables verbose mode." \
+		"Parallel execution is supported through the -j Make flag."
+
+# Core functions.
+
+ifeq ($(shell which wget 2>/dev/null | wc -l), 1)
+define core_http_get
+	wget --no-check-certificate -O $(1) $(2)|| rm $(1)
+endef
+else
+define core_http_get
+	$(ERL) -eval 'ssl:start(), inets:start(), case httpc:request(get, {"$(2)", []}, [{autoredirect, true}], []) of {ok, {{_, 200, _}, _, Body}} -> case file:write_file("$(1)", Body) of ok -> ok; {error, R1} -> halt(R1) end; {error, R2} -> halt(R2) end, halt(0).'
+endef
+endif
+
+# Automated update.
+
+ERLANG_MK_BUILD_CONFIG ?= build.config
+ERLANG_MK_BUILD_DIR ?= .erlang.mk.build
+
+erlang-mk:
+	git clone https://github.com/ninenines/erlang.mk $(ERLANG_MK_BUILD_DIR)
+	if [ -f $(ERLANG_MK_BUILD_CONFIG) ]; then cp $(ERLANG_MK_BUILD_CONFIG) $(ERLANG_MK_BUILD_DIR); fi
+	cd $(ERLANG_MK_BUILD_DIR) && make
+	cp $(ERLANG_MK_BUILD_DIR)/erlang.mk ./erlang.mk
+	rm -rf $(ERLANG_MK_BUILD_DIR)
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-deps distclean-pkg pkg-list pkg-search
+
+# Configuration.
+
+AUTOPATCH ?= edown gen_leader gproc
+export AUTOPATCH
+
+DEPS_DIR ?= $(CURDIR)/deps
+export DEPS_DIR
+
+REBAR_DEPS_DIR = $(DEPS_DIR)
+export REBAR_DEPS_DIR
+
+ALL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DEPS))
+
+ifeq ($(filter $(DEPS_DIR),$(subst :, ,$(ERL_LIBS))),)
+ifeq ($(ERL_LIBS),)
+	ERL_LIBS = $(DEPS_DIR)
+else
+	ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR)
+endif
+endif
+export ERL_LIBS
+
+PKG_FILE2 ?= $(CURDIR)/.erlang.mk.packages.v2
+export PKG_FILE2
+
+PKG_FILE_URL ?= https://raw.githubusercontent.com/ninenines/erlang.mk/master/packages.v2.tsv
+
+# Core targets.
+
+deps:: $(ALL_DEPS_DIRS)
+	@for dep in $(ALL_DEPS_DIRS) ; do \
+		if [ -f $$dep/rebar ] ; then \
+            cd $$dep ; ./rebar compile skip_deps=true deps_dir=.. ; \
+        elif [ -f $$dep/rebar.config ] ; then \
+        	cd $$dep ; rebar compile skip_deps=true deps_dir=.. ; \
+        elif [ -f $$dep/GNUmakefile ] || [ -f $$dep/makefile ] || [ -f $$dep/Makefile ] ; then \
+			$(MAKE) -C $$dep ; \
+		else \
+			echo "include $(CURDIR)/erlang.mk" | ERLC_OPTS=+debug_info $(MAKE) -f - -C $$dep ; \
+		fi ; \
+	done
+
+distclean:: distclean-deps distclean-pkg
+
+# Deps related targets.
+
+define dep_autopatch
+	$(ERL) -eval " \
+DepDir = \"$(DEPS_DIR)/$(1)/\", \
+fun() -> \
+	{ok, Conf} = file:consult(DepDir ++ \"rebar.config\"), \
+	File = case lists:keyfind(deps, 1, Conf) of false -> []; {_, Deps} -> \
+		[begin {Method, Repo, Commit} = case Repos of \
+			{git, R} -> {git, R, master}; \
+			{M, R, {branch, C}} -> {M, R, C}; \
+			{M, R, {tag, C}} -> {M, R, C}; \
+			{M, R, C} -> {M, R, C} \
+		end, \
+		io_lib:format(\"DEPS += ~s\ndep_~s = ~s ~s ~s~n\", [Name, Name, Method, Repo, Commit]) \
+		end || {Name, _, Repos} <- Deps] \
+	end, \
+	ok = file:write_file(\"$(DEPS_DIR)/$(1)/Makefile\", [\"ERLC_OPTS = +debug_info\n\n\", File, \"\ninclude erlang.mk\"]) \
+end(), \
+AppSrcOut = \"$(DEPS_DIR)/$(1)/src/$(1).app.src\", \
+AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> \"$(DEPS_DIR)/$(1)/ebin/$(1).app\"; true -> AppSrcOut end, \
+fun() -> \
+	{ok, [{application, $(1), L}]} = file:consult(AppSrcIn), \
+	L2 = case lists:keyfind(modules, 1, L) of {_, _} -> L; false -> [{modules, []}|L] end, \
+	L3 = case lists:keyfind(vsn, 1, L2) of {vsn, git} -> lists:keyreplace(vsn, 1, L2, {vsn, \"git\"}); _ -> L2 end, \
+	ok = file:write_file(AppSrcOut, io_lib:format(\"~p.~n\", [{application, $(1), L3}])) \
+end(), \
+case AppSrcOut of AppSrcIn -> ok; _ -> ok = file:delete(AppSrcIn) end, \
+halt()."
+endef
+
+ifeq ($(V),0)
+define dep_autopatch_verbose
+	@echo " PATCH " $(1);
+endef
+endif
+
+define dep_fetch
+	if [ "$$$$VS" = "git" ]; then \
+		git clone -n -- $$$$REPO $(DEPS_DIR)/$(1); \
+		cd $(DEPS_DIR)/$(1) && git checkout -q $$$$COMMIT; \
+	elif [ "$$$$VS" = "hg" ]; then \
+		hg clone -U $$$$REPO $(DEPS_DIR)/$(1); \
+		cd $(DEPS_DIR)/$(1) && hg update -q $$$$COMMIT; \
+	elif [ "$$$$VS" = "svn" ]; then \
+		svn checkout $$$$REPO $(DEPS_DIR)/$(1); \
+	else \
+		echo "Unknown or invalid dependency: $(1). Please consult the erlang.mk README for instructions." >&2; \
+		exit 78; \
+	fi
+endef
+
+define dep_target
+$(DEPS_DIR)/$(1):
+	@mkdir -p $(DEPS_DIR)
+ifeq (,$(dep_$(1)))
+	@if [ ! -f $(PKG_FILE2) ]; then $(call core_http_get,$(PKG_FILE2),$(PKG_FILE_URL)); fi
+	@DEPPKG=$$$$(awk 'BEGIN { FS = "\t" }; $$$$1 == "$(1)" { print $$$$2 " " $$$$3 " " $$$$4 }' $(PKG_FILE2);); \
+	VS=$$$$(echo $$$$DEPPKG | cut -d " " -f1); \
+	REPO=$$$$(echo $$$$DEPPKG | cut -d " " -f2); \
+	COMMIT=$$$$(echo $$$$DEPPKG | cut -d " " -f3); \
+	$(call dep_fetch,$(1))
+else
+	@VS=$(word 1,$(dep_$(1))); \
+	REPO=$(word 2,$(dep_$(1))); \
+	COMMIT=$(word 3,$(dep_$(1))); \
+	$(call dep_fetch,$(1))
+endif
+ifneq ($(filter $(1),$(AUTOPATCH)),)
+	$(call dep_autopatch_verbose,$(1)) if [ -f $(DEPS_DIR)/$(1)/rebar.config ]; then \
+		$(call dep_autopatch,$(1)); \
+		cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \
+	elif [ ! -f $(DEPS_DIR)/$(1)/Makefile ]; then \
+		echo "ERLC_OPTS = +debug_info\ninclude erlang.mk" > $(DEPS_DIR)/$(1)/Makefile; \
+		cd $(DEPS_DIR)/$(1)/ && ln -s ../../erlang.mk; \
+	fi
+endif
+endef
+
+$(foreach dep,$(DEPS),$(eval $(call dep_target,$(dep))))
+
+distclean-deps:
+	$(gen_verbose) rm -rf $(DEPS_DIR)
+
+# Packages related targets.
+
+$(PKG_FILE2):
+	@$(call core_http_get,$(PKG_FILE2),$(PKG_FILE_URL))
+
+pkg-list: $(PKG_FILE2)
+	@cat $(PKG_FILE2) | awk 'BEGIN { FS = "\t" }; { print \
+		"Name:\t\t" $$1 "\n" \
+		"Repository:\t" $$3 "\n" \
+		"Website:\t" $$5 "\n" \
+		"Description:\t" $$6 "\n" }'
+
+ifdef q
+pkg-search: $(PKG_FILE2)
+	@cat $(PKG_FILE2) | grep -i ${q} | awk 'BEGIN { FS = "\t" }; { print \
+		"Name:\t\t" $$1 "\n" \
+		"Repository:\t" $$3 "\n" \
+		"Website:\t" $$5 "\n" \
+		"Description:\t" $$6 "\n" }'
+else
+pkg-search:
+	$(error Usage: make pkg-search q=STRING)
+endif
+
+ifeq ($(PKG_FILE2),$(CURDIR)/.erlang.mk.packages.v2)
+distclean-pkg:
+	$(gen_verbose) rm -f $(PKG_FILE2)
+endif
+
+help::
+	@printf "%s\n" "" \
+		"Package-related targets:" \
+		"  pkg-list              List all known packages" \
+		"  pkg-search q=STRING   Search for STRING in the package index"
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: clean-app
+
+# Configuration.
+
+ERLC_OPTS ?= -Werror +debug_info +warn_export_vars +warn_shadow_vars \
+	+warn_obsolete_guard # +bin_opt_info +warn_export_all +warn_missing_spec
+COMPILE_FIRST ?=
+COMPILE_FIRST_PATHS = $(addprefix src/,$(addsuffix .erl,$(COMPILE_FIRST)))
+ERLC_EXCLUDE ?=
+ERLC_EXCLUDE_PATHS = $(addprefix src/,$(addsuffix .erl,$(ERLC_EXCLUDE)))
+
+ERLC_MIB_OPTS ?=
+COMPILE_MIB_FIRST ?=
+COMPILE_MIB_FIRST_PATHS = $(addprefix mibs/,$(addsuffix .mib,$(COMPILE_MIB_FIRST)))
+
+# Verbosity.
+
+appsrc_verbose_0 = @echo " APP   " $(PROJECT).app.src;
+appsrc_verbose = $(appsrc_verbose_$(V))
+
+erlc_verbose_0 = @echo " ERLC  " $(filter-out $(patsubst %,%.erl,$(ERLC_EXCLUDE)),\
+	$(filter %.erl %.core,$(?F)));
+erlc_verbose = $(erlc_verbose_$(V))
+
+xyrl_verbose_0 = @echo " XYRL  " $(filter %.xrl %.yrl,$(?F));
+xyrl_verbose = $(xyrl_verbose_$(V))
+
+mib_verbose_0 = @echo " MIB   " $(filter %.bin %.mib,$(?F));
+mib_verbose = $(mib_verbose_$(V))
+
+# Targets.
+
+ifeq ($(wildcard ebin/test),)
+app:: app-build
+else
+app:: clean app-build
+endif
+
+app-build: erlc-include ebin/$(PROJECT).app
+	$(eval MODULES := $(shell find ebin -type f -name \*.beam \
+		| sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//'))
+	@if [ -z "$$(grep -E '^[^%]*{modules,' src/$(PROJECT).app.src)" ]; then \
+		echo "Empty modules entry not found in $(PROJECT).app.src. Please consult the erlang.mk README for instructions." >&2; \
+		exit 1; \
+	fi
+	$(eval GITDESCRIBE := $(shell git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true))
+	$(appsrc_verbose) cat src/$(PROJECT).app.src \
+		| sed "s/{modules,[[:space:]]*\[\]}/{modules, \[$(MODULES)\]}/" \
+		| sed "s/{id,[[:space:]]*\"git\"}/{id, \"$(GITDESCRIBE)\"}/" \
+		> ebin/$(PROJECT).app
+
+erlc-include:
+	-@if [ -d ebin/ ]; then \
+		find include/ src/ -type f -name \*.hrl -newer ebin -exec touch $(shell find src/ -type f -name "*.erl") \; 2>/dev/null || printf ''; \
+	fi
+
+define compile_erl
+	$(erlc_verbose) erlc -v $(ERLC_OPTS) -o ebin/ \
+		-pa ebin/ -I include/ $(filter-out $(ERLC_EXCLUDE_PATHS),\
+		$(COMPILE_FIRST_PATHS) $(1))
+endef
+
+define compile_xyrl
+	$(xyrl_verbose) erlc -v -o ebin/ $(1)
+	$(xyrl_verbose) erlc $(ERLC_OPTS) -o ebin/ ebin/*.erl
+	@rm ebin/*.erl
+endef
+
+define compile_mib
+	$(mib_verbose) erlc -v $(ERLC_MIB_OPTS) -o priv/mibs/ \
+		-I priv/mibs/ $(COMPILE_MIB_FIRST_PATHS) $(1)
+	$(mib_verbose) erlc -o include/ -- priv/mibs/*.bin
+endef
+
+ifneq ($(wildcard src/),)
+ebin/$(PROJECT).app::
+	@mkdir -p ebin/
+
+ifneq ($(wildcard mibs/),)
+ebin/$(PROJECT).app:: $(shell find mibs -type f -name \*.mib)
+	@mkdir -p priv/mibs/ include
+	$(if $(strip $?),$(call compile_mib,$?))
+endif
+
+ebin/$(PROJECT).app:: $(shell find src -type f -name \*.erl) \
+		$(shell find src -type f -name \*.core)
+	$(if $(strip $?),$(call compile_erl,$?))
+
+ebin/$(PROJECT).app:: $(shell find src -type f -name \*.xrl) \
+		$(shell find src -type f -name \*.yrl)
+	$(if $(strip $?),$(call compile_xyrl,$?))
+endif
+
+clean:: clean-app
+
+clean-app:
+	$(gen_verbose) rm -rf ebin/ priv/mibs/ \
+		$(addprefix include/,$(addsuffix .hrl,$(notdir $(basename $(wildcard mibs/*.mib)))))
+
+# Copyright (c) 2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: test-deps test-dir test-build clean-test-dir
+
+# Configuration.
+
+TEST_DIR ?= test
+
+ALL_TEST_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(TEST_DEPS))
+
+TEST_ERLC_OPTS ?= +debug_info +warn_export_vars +warn_shadow_vars +warn_obsolete_guard
+TEST_ERLC_OPTS += -DTEST=1
+
+# Targets.
+
+$(foreach dep,$(TEST_DEPS),$(eval $(call dep_target,$(dep))))
+
+test-deps: $(ALL_TEST_DEPS_DIRS)
+	@for dep in $(ALL_TEST_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
+
+ifneq ($(strip $(TEST_DIR)),)
+test-dir:
+	$(gen_verbose) erlc -v $(TEST_ERLC_OPTS) -I include/ -o $(TEST_DIR) \
+		$(wildcard $(TEST_DIR)/*.erl $(TEST_DIR)/*/*.erl) -pa ebin/
+endif
+
+ifeq ($(wildcard ebin/test),)
+test-build: ERLC_OPTS=$(TEST_ERLC_OPTS)
+test-build: #todo clean deps test-deps
+	@$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)"
+	$(gen_verbose) touch ebin/test
+else
+test-build: ERLC_OPTS=$(TEST_ERLC_OPTS)
+test-build: #todo deps test-deps
+	@$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)"
+endif
+
+clean:: clean-test-dir
+
+clean-test-dir:
+ifneq ($(wildcard $(TEST_DIR)/*.beam),)
+	$(gen_verbose) rm -f $(TEST_DIR)/*.beam
+endif
+
+# Copyright (c) 2014-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates
+
+# Core targets.
+
+help::
+	@printf "%s\n" "" \
+		"Bootstrap targets:" \
+		"  bootstrap          Generate a skeleton of an OTP application" \
+		"  bootstrap-lib      Generate a skeleton of an OTP library" \
+		"  bootstrap-rel      Generate the files needed to build a release" \
+		"  new t=TPL n=NAME   Generate a module NAME based on the template TPL" \
+		"  list-templates     List available templates"
+
+# Bootstrap templates.
+
+bs_appsrc = "{application, $(PROJECT), [" \
+	"	{description, \"\"}," \
+	"	{vsn, \"0.1.0\"}," \
+	"	{id, \"git\"}," \
+	"	{modules, []}," \
+	"	{registered, []}," \
+	"	{applications, [" \
+	"		kernel," \
+	"		stdlib" \
+	"	]}," \
+	"	{mod, {$(PROJECT)_app, []}}," \
+	"	{env, []}" \
+	"]}."
+bs_appsrc_lib = "{application, $(PROJECT), [" \
+	"	{description, \"\"}," \
+	"	{vsn, \"0.1.0\"}," \
+	"	{id, \"git\"}," \
+	"	{modules, []}," \
+	"	{registered, []}," \
+	"	{applications, [" \
+	"		kernel," \
+	"		stdlib" \
+	"	]}" \
+	"]}."
+bs_Makefile = "PROJECT = $(PROJECT)" \
+	"include erlang.mk"
+bs_app = "-module($(PROJECT)_app)." \
+	"-behaviour(application)." \
+	"" \
+	"-export([start/2])." \
+	"-export([stop/1])." \
+	"" \
+	"start(_Type, _Args) ->" \
+	"	$(PROJECT)_sup:start_link()." \
+	"" \
+	"stop(_State) ->" \
+	"	ok."
+bs_relx_config = "{release, {$(PROJECT)_release, \"1\"}, [$(PROJECT)]}." \
+	"{extended_start_script, true}." \
+	"{sys_config, \"rel/sys.config\"}." \
+	"{vm_args, \"rel/vm.args\"}."
+bs_sys_config = "[" \
+	"]."
+bs_vm_args = "-name $(PROJECT)@127.0.0.1" \
+	"-setcookie $(PROJECT)" \
+	"-heart"
+# Normal templates.
+tpl_supervisor = "-module($(n))." \
+	"-behaviour(supervisor)." \
+	"" \
+	"-export([start_link/0])." \
+	"-export([init/1])." \
+	"" \
+	"start_link() ->" \
+	"	supervisor:start_link({local, ?MODULE}, ?MODULE, [])." \
+	"" \
+	"init([]) ->" \
+	"	Procs = []," \
+	"	{ok, {{one_for_one, 1, 5}, Procs}}."
+tpl_gen_server = "-module($(n))." \
+	"-behaviour(gen_server)." \
+	"" \
+	"%% API." \
+	"-export([start_link/0])." \
+	"" \
+	"%% gen_server." \
+	"-export([init/1])." \
+	"-export([handle_call/3])." \
+	"-export([handle_cast/2])." \
+	"-export([handle_info/2])." \
+	"-export([terminate/2])." \
+	"-export([code_change/3])." \
+	"" \
+	"-record(state, {" \
+	"})." \
+	"" \
+	"%% API." \
+	"" \
+	"-spec start_link() -> {ok, pid()}." \
+	"start_link() ->" \
+	"	gen_server:start_link(?MODULE, [], [])." \
+	"" \
+	"%% gen_server." \
+	"" \
+	"init([]) ->" \
+	"	{ok, \#state{}}." \
+	"" \
+	"handle_call(_Request, _From, State) ->" \
+	"	{reply, ignored, State}." \
+	"" \
+	"handle_cast(_Msg, State) ->" \
+	"	{noreply, State}." \
+	"" \
+	"handle_info(_Info, State) ->" \
+	"	{noreply, State}." \
+	"" \
+	"terminate(_Reason, _State) ->" \
+	"	ok." \
+	"" \
+	"code_change(_OldVsn, State, _Extra) ->" \
+	"	{ok, State}."
+tpl_gen_fsm = "-module($(n))." \
+	"-behaviour(gen_fsm)." \
+	"" \
+	"%% API." \
+	"-export([start_link/0])." \
+	"" \
+	"%% gen_fsm." \
+	"-export([init/1])." \
+	"-export([state_name/2])." \
+	"-export([handle_event/3])." \
+	"-export([state_name/3])." \
+	"-export([handle_sync_event/4])." \
+	"-export([handle_info/3])." \
+	"-export([terminate/3])." \
+	"-export([code_change/4])." \
+	"" \
+	"-record(state, {" \
+	"})." \
+	"" \
+	"%% API." \
+	"" \
+	"-spec start_link() -> {ok, pid()}." \
+	"start_link() ->" \
+	"	gen_fsm:start_link(?MODULE, [], [])." \
+	"" \
+	"%% gen_fsm." \
+	"" \
+	"init([]) ->" \
+	"	{ok, state_name, \#state{}}." \
+	"" \
+	"state_name(_Event, StateData) ->" \
+	"	{next_state, state_name, StateData}." \
+	"" \
+	"handle_event(_Event, StateName, StateData) ->" \
+	"	{next_state, StateName, StateData}." \
+	"" \
+	"state_name(_Event, _From, StateData) ->" \
+	"	{reply, ignored, state_name, StateData}." \
+	"" \
+	"handle_sync_event(_Event, _From, StateName, StateData) ->" \
+	"	{reply, ignored, StateName, StateData}." \
+	"" \
+	"handle_info(_Info, StateName, StateData) ->" \
+	"	{next_state, StateName, StateData}." \
+	"" \
+	"terminate(_Reason, _StateName, _StateData) ->" \
+	"	ok." \
+	"" \
+	"code_change(_OldVsn, StateName, StateData, _Extra) ->" \
+	"	{ok, StateName, StateData}."
+tpl_cowboy_http = "-module($(n))." \
+	"-behaviour(cowboy_http_handler)." \
+	"" \
+	"-export([init/3])." \
+	"-export([handle/2])." \
+	"-export([terminate/3])." \
+	"" \
+	"-record(state, {" \
+	"})." \
+	"" \
+	"init(_, Req, _Opts) ->" \
+	"	{ok, Req, \#state{}}." \
+	"" \
+	"handle(Req, State=\#state{}) ->" \
+	"	{ok, Req2} = cowboy_req:reply(200, Req)," \
+	"	{ok, Req2, State}." \
+	"" \
+	"terminate(_Reason, _Req, _State) ->" \
+	"	ok."
+tpl_cowboy_loop = "-module($(n))." \
+	"-behaviour(cowboy_loop_handler)." \
+	"" \
+	"-export([init/3])." \
+	"-export([info/3])." \
+	"-export([terminate/3])." \
+	"" \
+	"-record(state, {" \
+	"})." \
+	"" \
+	"init(_, Req, _Opts) ->" \
+	"	{loop, Req, \#state{}, 5000, hibernate}." \
+	"" \
+	"info(_Info, Req, State) ->" \
+	"	{loop, Req, State, hibernate}." \
+	"" \
+	"terminate(_Reason, _Req, _State) ->" \
+	"	ok."
+tpl_cowboy_rest = "-module($(n))." \
+	"" \
+	"-export([init/3])." \
+	"-export([content_types_provided/2])." \
+	"-export([get_html/2])." \
+	"" \
+	"init(_, _Req, _Opts) ->" \
+	"	{upgrade, protocol, cowboy_rest}." \
+	"" \
+	"content_types_provided(Req, State) ->" \
+	"	{[{{<<\"text\">>, <<\"html\">>, '*'}, get_html}], Req, State}." \
+	"" \
+	"get_html(Req, State) ->" \
+	"	{<<\"<html><body>This is REST!</body></html>\">>, Req, State}."
+tpl_cowboy_ws = "-module($(n))." \
+	"-behaviour(cowboy_websocket_handler)." \
+	"" \
+	"-export([init/3])." \
+	"-export([websocket_init/3])." \
+	"-export([websocket_handle/3])." \
+	"-export([websocket_info/3])." \
+	"-export([websocket_terminate/3])." \
+	"" \
+	"-record(state, {" \
+	"})." \
+	"" \
+	"init(_, _, _) ->" \
+	"	{upgrade, protocol, cowboy_websocket}." \
+	"" \
+	"websocket_init(_, Req, _Opts) ->" \
+	"	Req2 = cowboy_req:compact(Req)," \
+	"	{ok, Req2, \#state{}}." \
+	"" \
+	"websocket_handle({text, Data}, Req, State) ->" \
+	"	{reply, {text, Data}, Req, State};" \
+	"websocket_handle({binary, Data}, Req, State) ->" \
+	"	{reply, {binary, Data}, Req, State};" \
+	"websocket_handle(_Frame, Req, State) ->" \
+	"	{ok, Req, State}." \
+	"" \
+	"websocket_info(_Info, Req, State) ->" \
+	"	{ok, Req, State}." \
+	"" \
+	"websocket_terminate(_Reason, _Req, _State) ->" \
+	"	ok."
+tpl_ranch_protocol = "-module($(n))." \
+	"-behaviour(ranch_protocol)." \
+	"" \
+	"-export([start_link/4])." \
+	"-export([init/4])." \
+	"" \
+	"-type opts() :: []." \
+	"-export_type([opts/0])." \
+	"" \
+	"-record(state, {" \
+	"	socket :: inet:socket()," \
+	"	transport :: module()" \
+	"})." \
+	"" \
+	"start_link(Ref, Socket, Transport, Opts) ->" \
+	"	Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts])," \
+	"	{ok, Pid}." \
+	"" \
+	"-spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok." \
+	"init(Ref, Socket, Transport, _Opts) ->" \
+	"	ok = ranch:accept_ack(Ref)," \
+	"	loop(\#state{socket=Socket, transport=Transport})." \
+	"" \
+	"loop(State) ->" \
+	"	loop(State)."
+
+# Plugin-specific targets.
+
+bootstrap:
+ifneq ($(wildcard src/),)
+	$(error Error: src/ directory already exists)
+endif
+	@printf "%s\n" $(bs_Makefile) > Makefile
+	@mkdir src/
+	@printf "%s\n" $(bs_appsrc) > src/$(PROJECT).app.src
+	@printf "%s\n" $(bs_app) > src/$(PROJECT)_app.erl
+	$(eval n := $(PROJECT)_sup)
+	@printf "%s\n" $(tpl_supervisor) > src/$(PROJECT)_sup.erl
+
+bootstrap-lib:
+ifneq ($(wildcard src/),)
+	$(error Error: src/ directory already exists)
+endif
+	@printf "%s\n" $(bs_Makefile) > Makefile
+	@mkdir src/
+	@printf "%s\n" $(bs_appsrc_lib) > src/$(PROJECT).app.src
+
+bootstrap-rel:
+ifneq ($(wildcard relx.config),)
+	$(error Error: relx.config already exists)
+endif
+ifneq ($(wildcard rel/),)
+	$(error Error: rel/ directory already exists)
+endif
+	@printf "%s\n" $(bs_relx_config) > relx.config
+	@mkdir rel/
+	@printf "%s\n" $(bs_sys_config) > rel/sys.config
+	@printf "%s\n" $(bs_vm_args) > rel/vm.args
+
+new:
+ifeq ($(wildcard src/),)
+	$(error Error: src/ directory does not exist)
+endif
+ifndef t
+	$(error Usage: make new t=TEMPLATE n=NAME)
+endif
+ifndef tpl_$(t)
+	$(error Unknown template)
+endif
+ifndef n
+	$(error Usage: make new t=TEMPLATE n=NAME)
+endif
+	@printf "%s\n" $(tpl_$(t)) > src/$(n).erl
+
+list-templates:
+	@echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES))))
+
+# Copyright (c) 2014-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: clean-c_src distclean-c_src-env
+# todo
+
+# Configuration.
+
+C_SRC_DIR = $(CURDIR)/c_src
+C_SRC_ENV ?= $(C_SRC_DIR)/env.mk
+C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so
+
+# System type and C compiler/flags.
+
+UNAME_SYS := $(shell uname -s)
+ifeq ($(UNAME_SYS), Darwin)
+	CC ?= cc
+	CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
+	CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
+	LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
+else ifeq ($(UNAME_SYS), FreeBSD)
+	CC ?= cc
+	CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+	CXXFLAGS ?= -O3 -finline-functions -Wall
+else ifeq ($(UNAME_SYS), Linux)
+	CC ?= gcc
+	CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
+	CXXFLAGS ?= -O3 -finline-functions -Wall
+endif
+
+CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
+
+LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei
+LDFLAGS += -shared
+
+# Verbosity.
+
+c_verbose_0 = @echo " C     " $(?F);
+c_verbose = $(c_verbose_$(V))
+
+cpp_verbose_0 = @echo " CPP   " $(?F);
+cpp_verbose = $(cpp_verbose_$(V))
+
+link_verbose_0 = @echo " LD    " $(@F);
+link_verbose = $(link_verbose_$(V))
+
+# Targets.
+
+ifeq ($(wildcard $(C_SRC_DIR)),)
+else ifneq ($(wildcard $(C_SRC_DIR)/Makefile),)
+app::
+	$(MAKE) -C $(C_SRC_DIR)
+
+clean::
+	$(MAKE) -C $(C_SRC_DIR) clean
+
+else
+SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \))
+OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
+
+COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
+COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
+
+app:: $(C_SRC_ENV) $(C_SRC_OUTPUT)
+
+$(C_SRC_OUTPUT): $(OBJECTS)
+	@mkdir -p priv/
+	$(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT)
+
+%.o: %.c
+	$(COMPILE_C) $(OUTPUT_OPTION) $<
+
+%.o: %.cc
+	$(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+%.o: %.C
+	$(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+%.o: %.cpp
+	$(COMPILE_CPP) $(OUTPUT_OPTION) $<
+
+$(C_SRC_ENV):
+	@$(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \
+		io_lib:format( \
+			\"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \
+			\"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \
+			\"ERL_INTERFACE_LIB_DIR ?= ~s~n\", \
+			[code:root_dir(), erlang:system_info(version), \
+			code:lib_dir(erl_interface, include), \
+			code:lib_dir(erl_interface, lib)])), \
+		halt()."
+
+clean:: clean-c_src
+
+clean-c_src:
+	$(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS)
+
+distclean:: distclean-c_src-env
+
+distclean-c_src-env:
+	$(gen_verbose) rm -f $(C_SRC_ENV)
+
+-include $(C_SRC_ENV)
+endif
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: ct distclean-ct
+
+# Configuration.
+
+CT_OPTS ?=
+ifneq ($(wildcard $(TEST_DIR)),)
+	CT_SUITES ?= $(sort $(subst _SUITE.erl,,$(shell find $(TEST_DIR) -type f -name \*_SUITE.erl -exec basename {} \;)))
+else
+	CT_SUITES ?=
+endif
+
+# Core targets.
+
+tests:: ct
+
+distclean:: distclean-ct
+
+help::
+	@printf "%s\n" "" \
+		"Common_test targets:" \
+		"  ct          Run all the common_test suites for this project" \
+		"" \
+		"All your common_test suites have their associated targets." \
+		"A suite named http_SUITE can be ran using the ct-http target."
+
+# Plugin-specific targets.
+
+CT_RUN = ct_run \
+	-no_auto_compile \
+	-noinput \
+	-pa ebin $(DEPS_DIR)/*/ebin \
+	-dir $(TEST_DIR) \
+	-logdir logs
+
+ifeq ($(CT_SUITES),)
+ct:
+else
+ct: test-build
+	@mkdir -p logs/
+	$(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS)
+endif
+
+define ct_suite_target
+ct-$(1): test-build
+	@mkdir -p logs/
+	$(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS)
+endef
+
+$(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test))))
+
+distclean-ct:
+	$(gen_verbose) rm -rf logs/
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: plt distclean-plt dialyze
+
+# Configuration.
+
+DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt
+export DIALYZER_PLT
+
+PLT_APPS ?=
+DIALYZER_DIRS ?= --src -r src
+DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \
+	-Wunmatched_returns # -Wunderspecs
+
+# Core targets.
+
+distclean:: distclean-plt
+
+help::
+	@printf "%s\n" "" \
+		"Dialyzer targets:" \
+		"  plt         Build a PLT file for this project" \
+		"  dialyze     Analyze the project using Dialyzer"
+
+# Plugin-specific targets.
+
+$(DIALYZER_PLT): deps app
+	@dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(ALL_DEPS_DIRS)
+
+plt: $(DIALYZER_PLT)
+
+distclean-plt:
+	$(gen_verbose) rm -f $(DIALYZER_PLT)
+
+ifneq ($(wildcard $(DIALYZER_PLT)),)
+dialyze:
+else
+dialyze: $(DIALYZER_PLT)
+endif
+	@dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS)
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# Copyright (c) 2015, Viktor S�derqvist <vi...@zuiderkwast.se>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-edoc build-doc-deps
+
+# Configuration.
+
+EDOC_OPTS ?=
+
+# Core targets.
+
+docs:: distclean-edoc build-doc-deps
+	$(gen_verbose) $(ERL) -eval 'edoc:application($(PROJECT), ".", [$(EDOC_OPTS)]), halt().'
+
+distclean:: distclean-edoc
+
+# Plugin-specific targets.
+
+DOC_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(DOC_DEPS))
+
+$(foreach dep,$(DOC_DEPS),$(eval $(call dep_target,$(dep))))
+
+build-doc-deps: $(DOC_DEPS_DIRS)
+	@for dep in $(DOC_DEPS_DIRS) ; do $(MAKE) -C $$dep; done
+
+distclean-edoc:
+	$(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info
+
+# Copyright (c) 2014, Juan Facorro <ju...@inaka.net>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: elvis distclean-elvis
+
+# Configuration.
+
+ELVIS_CONFIG ?= $(CURDIR)/elvis.config
+
+ELVIS ?= $(CURDIR)/elvis
+export ELVIS
+
+ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.3/elvis
+ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.3/elvis.config
+ELVIS_OPTS ?=
+
+# Core targets.
+
+help::
+	@printf "%s\n" "" \
+		"Elvis targets:" \
+		"  elvis       Run Elvis using the local elvis.config or download the default otherwise"
+
+distclean:: distclean-elvis
+
+# Plugin-specific targets.
+
+$(ELVIS):
+	@$(call core_http_get,$(ELVIS),$(ELVIS_URL))
+	@chmod +x $(ELVIS)
+
+$(ELVIS_CONFIG):
+	@$(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL))
+
+elvis: $(ELVIS) $(ELVIS_CONFIG)
+	@$(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS)
+
+distclean-elvis:
+	$(gen_verbose) rm -rf $(ELVIS)
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+# Configuration.
+
+DTL_FULL_PATH ?= 0
+
+# Verbosity.
+
+dtl_verbose_0 = @echo " DTL   " $(filter %.dtl,$(?F));
+dtl_verbose = $(dtl_verbose_$(V))
+
+# Core targets.
+
+define compile_erlydtl
+	$(dtl_verbose) $(ERL) -pa ebin/ $(DEPS_DIR)/erlydtl/ebin/ -eval ' \
+		Compile = fun(F) -> \
+			S = fun (1) -> re:replace(filename:rootname(string:sub_string(F, 11), ".dtl"), "/",  "_",  [{return, list}, global]); \
+				(0) -> filename:basename(F, ".dtl") \
+			end, \
+			Module = list_to_atom(string:to_lower(S($(DTL_FULL_PATH))) ++ "_dtl"), \
+			{ok, _} = erlydtl:compile(F, Module, [{out_dir, "ebin/"}, return_errors, {doc_root, "templates"}]) \
+		end, \
+		_ = [Compile(F) || F <- string:tokens("$(1)", " ")], \
+		halt().'
+endef
+
+ifneq ($(wildcard src/),)
+ebin/$(PROJECT).app:: $(shell find templates -type f -name \*.dtl 2>/dev/null)
+	$(if $(strip $?),$(call compile_erlydtl,$?))
+endif
+
+# Copyright (c) 2014 Dave Cottlehuber <dc...@skunkwerks.at>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: distclean-escript escript
+
+# Configuration.
+
+ESCRIPT_NAME ?= $(PROJECT)
+ESCRIPT_COMMENT ?= This is an -*- erlang -*- file
+
+ESCRIPT_BEAMS ?= "ebin/*", "deps/*/ebin/*"
+ESCRIPT_SYS_CONFIG ?= "rel/sys.config"
+ESCRIPT_EMU_ARGS ?= -pa . \
+	-sasl errlog_type error \
+	-escript main $(ESCRIPT_NAME)
+ESCRIPT_SHEBANG ?= /usr/bin/env escript
+ESCRIPT_STATIC ?= "deps/*/priv/**", "priv/**"
+
+# Core targets.
+
+distclean:: distclean-escript
+
+help::
+	@printf "%s\n" "" \
+		"Escript targets:" \
+		"  escript     Build an executable escript archive" \
+
+# Plugin-specific targets.
+
+# Based on https://github.com/synrc/mad/blob/master/src/mad_bundle.erl
+# Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center
+# Modified MIT License, https://github.com/synrc/mad/blob/master/LICENSE :
+# Software may only be used for the great good and the true happiness of all
+# sentient beings.
+
+define ESCRIPT_RAW
+'Read = fun(F) -> {ok, B} = file:read_file(filename:absname(F)), B end,'\
+'Files = fun(L) -> A = lists:concat([filelib:wildcard(X)||X<- L ]),'\
+'  [F || F <- A, not filelib:is_dir(F) ] end,'\
+'Squash = fun(L) -> [{filename:basename(F), Read(F) } || F <- L ] end,'\
+'Zip = fun(A, L) -> {ok,{_,Z}} = zip:create(A, L, [{compress,all},memory]), Z end,'\
+'Ez = fun(Escript) ->'\
+'  Static = Files([$(ESCRIPT_STATIC)]),'\
+'  Beams = Squash(Files([$(ESCRIPT_BEAMS), $(ESCRIPT_SYS_CONFIG)])),'\
+'  Archive = Beams ++ [{ "static.gz", Zip("static.gz", Static)}],'\
+'  escript:create(Escript, [ $(ESCRIPT_OPTIONS)'\
+'    {archive, Archive, [memory]},'\
+'    {shebang, "$(ESCRIPT_SHEBANG)"},'\
+'    {comment, "$(ESCRIPT_COMMENT)"},'\
+'    {emu_args, " $(ESCRIPT_EMU_ARGS)"}'\
+'  ]),'\
+'  file:change_mode(Escript, 8#755)'\
+'end,'\
+'Ez("$(ESCRIPT_NAME)"),'\
+'halt().'
+endef
+
+ESCRIPT_COMMAND = $(subst ' ',,$(ESCRIPT_RAW))
+
+escript:: distclean-escript deps app
+	$(gen_verbose) $(ERL) -eval $(ESCRIPT_COMMAND)
+
+distclean-escript:
+	$(gen_verbose) rm -f $(ESCRIPT_NAME)
+
+# Copyright (c) 2014, Enrique Fernandez <en...@erlang-solutions.com>
+# Copyright (c) 2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is contributed to erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: eunit
+
+# Configuration
+
+ifeq ($(strip $(TEST_DIR)),)
+TAGGED_EUNIT_TESTS = {dir,"ebin"}
+else
+ifeq ($(wildcard $(TEST_DIR)),)
+TAGGED_EUNIT_TESTS = {dir,"ebin"}
+else
+# All modules in TEST_DIR
+TEST_DIR_MODS = $(notdir $(basename $(shell find $(TEST_DIR) -type f -name *.beam)))
+# All modules in 'ebin'
+EUNIT_EBIN_MODS = $(notdir $(basename $(shell find ebin -type f -name *.beam)))
+# Only those modules in TEST_DIR with no matching module in 'ebin'.
+# This is done to avoid some tests being executed twice.
+EUNIT_MODS = $(filter-out $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(TEST_DIR_MODS))
+TAGGED_EUNIT_TESTS = {dir,"ebin"} $(foreach mod,$(EUNIT_MODS),$(shell echo $(mod) | sed -e 's/\(.*\)/{module,\1}/g'))
+endif
+endif
+
+EUNIT_OPTS ?=
+
+# Utility functions
+
+define str-join
+	$(shell echo '$(strip $(1))' | sed -e "s/ /,/g")
+endef
+
+# Core targets.
+
+tests:: eunit
+
+help::
+	@printf "%s\n" "" \
+		"EUnit targets:" \
+		"  eunit       Run all the EUnit tests for this project"
+
+# Plugin-specific targets.
+
+EUNIT_RUN = $(ERL) \
+	-pa $(TEST_DIR) $(DEPS_DIR)/*/ebin \
+	-pz ebin \
+	-eval 'case eunit:test([$(call str-join,$(TAGGED_EUNIT_TESTS))], [$(EUNIT_OPTS)]) of ok -> halt(0); error -> halt(1) end.'
+
+eunit: test-build
+	$(gen_verbose) $(EUNIT_RUN)
+
+# Copyright (c) 2013-2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: relx-rel distclean-relx-rel distclean-relx
+
+# Configuration.
+
+RELX_CONFIG ?= $(CURDIR)/relx.config
+
+RELX ?= $(CURDIR)/relx
+export RELX
+
+RELX_URL ?= https://github.com/erlware/relx/releases/download/v1.2.0/relx
+RELX_OPTS ?=
+RELX_OUTPUT_DIR ?= _rel
+
+ifeq ($(firstword $(RELX_OPTS)),-o)
+	RELX_OUTPUT_DIR = $(word 2,$(RELX_OPTS))
+else
+	RELX_OPTS += -o $(RELX_OUTPUT_DIR)
+endif
+
+# Core targets.
+
+#ifneq ($(wildcard $(RELX_CONFIG)),)
+#rel:: distclean-relx-rel relx-rel
+#endif
+
+distclean:: distclean-relx-rel distclean-relx
+
+# Plugin-specific targets.
+
+define relx_fetch
+	$(call core_http_get,$(RELX),$(RELX_URL))
+	chmod +x $(RELX)
+endef
+
+$(RELX):
+	@$(call relx_fetch)
+
+relx-rel: $(RELX)
+	@$(RELX) -c $(RELX_CONFIG) $(RELX_OPTS)
+
+distclean-relx-rel:
+	$(gen_verbose) rm -rf $(RELX_OUTPUT_DIR)
+
+distclean-relx:
+	$(gen_verbose) rm -rf $(RELX)
+
+# Copyright (c) 2014, M Robert Martin <ro...@version2beta.com>
+# This file is contributed to erlang.mk and subject to the terms of the ISC License.
+
+.PHONY: shell
+
+# Configuration.
+
+SHELL_PATH ?= -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin
+SHELL_OPTS ?=
+
+ALL_SHELL_DEPS_DIRS = $(addprefix $(DEPS_DIR)/,$(SHELL_DEPS))
+
+# Core targets
+
+help::
+	@printf "%s\n" "" \
+		"Shell targets:" \
+		"  shell              Run an erlang shell with SHELL_OPTS or reasonable default"
+
+# Plugin-specific targets.
+
+$(foreach dep,$(SHELL_DEPS),$(eval $(call dep_target,$(dep))))
+
+build-shell-deps: $(ALL_SHELL_DEPS_DIRS)
+	@for dep in $(ALL_SHELL_DEPS_DIRS) ; do $(MAKE) -C $$dep ; done
+
+shell: build-shell-deps
+	$(gen_verbose) erl $(SHELL_PATH) $(SHELL_OPTS)
+
+# Copyright (c) 2015, Lo�c Hoguin <es...@ninenines.eu>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+ifneq ($(wildcard $(DEPS_DIR)/triq),)
+.PHONY: triq
+
+# Targets.
+
+tests:: triq
+
+define triq_run
+$(ERL) -pa $(CURDIR)/ebin $(DEPS_DIR)/*/ebin \
+	-eval "try $(1) of true -> halt(0); _ -> halt(1) catch error:undef -> io:format(\"Undefined property or module~n\"), halt() end."
+endef
+
+ifdef t
+ifeq (,$(findstring :,$(t)))
+triq: test-build
+	@$(call triq_run,triq:check($(t)))
+else
+triq: test-build
+	@echo Testing $(t)/0
+	@$(call triq_run,triq:check($(t)()))
+endif
+else
+triq: test-build
+	$(eval MODULES := $(shell find ebin -type f -name \*.beam \
+		| sed "s/ebin\//'/;s/\.beam/',/" | sed '$$s/.$$//'))
+	$(gen_verbose) $(call triq_run,[true] =:= lists:usort([triq:check(M) || M <- [$(MODULES)]]))
+endif
+endif

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index 026a6ac..7aaffcb 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,12 +1,13 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.2.4"},
+         {vsn, "4.3"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},
 	 {mod, {ibrowse_app, []}},
          {maintainers, ["Chandrashekhar Mullaparthi"]},
          {licenses, ["GPLv2", "BSD"]},
+	 {modules, []},
          {links, [{"Github", "https://github.com/cmullaparthi/ibrowse"}]}
         ]
 }.

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/src/ibrowse.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse.erl b/src/ibrowse.erl
index c412f25..b243f36 100644
--- a/src/ibrowse.erl
+++ b/src/ibrowse.erl
@@ -111,7 +111,8 @@
 -import(ibrowse_lib, [
                       parse_url/1,
                       get_value/3,
-                      do_trace/2
+                      do_trace/2,
+                      log_msg/2
                      ]).
                       
 -record(state, {trace = false}).
@@ -496,12 +497,12 @@ do_send_req(Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout) ->
                             _ ->
                                 process_info_not_available
                         end,
-            (catch lager:error("{ibrowse_http_client, send_req, ~1000.p} gen_server call timeout.~nProcess info: ~p~n",
-                               [[Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout], P_info])),
+            log_msg("{ibrowse_http_client, send_req, ~1000.p} gen_server call timeout.~nProcess info: ~p~n",
+                    [[Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout], P_info]),
             {error, req_timedout};
         {'EXIT', {normal, _}} = Ex_rsn ->
-            (catch lager:error("{ibrowse_http_client, send_req, ~1000.p} gen_server call got ~1000.p~n",
-                              [[Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout], Ex_rsn])),
+            log_msg("{ibrowse_http_client, send_req, ~1000.p} gen_server call got ~1000.p~n",
+                    [[Conn_Pid, Parsed_url, Headers, Method, Body, Options, Timeout], Ex_rsn]),
             {error, req_timedout};
         {error, X} when X == connection_closed;
                         X == {send_failed, {error, enotconn}};

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index 92ac431..b43b541 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -262,17 +262,22 @@ handle_info({ssl_error, _Sock, Reason}, State) ->
     delayed_stop_timer(),
     {noreply, State_1};
 
-handle_info({req_timedout, From}, State) ->
-    case lists:keysearch(From, #request.from, queue:to_list(State#state.reqs)) of
+handle_info({req_timedout, From}, #state{reqs = Reqs} = State) ->
+    Reqs_list = queue:to_list(Reqs),
+    case lists:keysearch(From, #request.from, Reqs_list) of
         false ->
             {noreply, State};
         {value, #request{stream_to = StreamTo, req_id = ReqId}} ->
             catch StreamTo ! {ibrowse_async_response_timeout, ReqId},
             State_1 = State#state{proc_state = ?dead_proc_walking},
             shutting_down(State_1),
-            do_error_reply(State_1, req_timedout),
+            Reqs_1 = lists:filter(fun(#request{from = X_from}) ->
+                                          X_from /= From
+                                  end, Reqs_list),
+            State_2 = State_1#state{reqs = queue:from_list(Reqs_1)},
+            do_error_reply(State_2, req_timedout),
             delayed_stop_timer(),
-            {noreply, State_1}
+            {noreply, State_2}
     end;
 
 handle_info(timeout, State) ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/src/ibrowse_lib.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_lib.erl b/src/ibrowse_lib.erl
index 1f0a61a..6c1883d 100644
--- a/src/ibrowse_lib.erl
+++ b/src/ibrowse_lib.erl
@@ -20,6 +20,7 @@
          get_trace_status/2,
          do_trace/2,
          do_trace/3,
+         log_msg/2,
          url_encode/1,
          decode_rfc822_date/1,
          status_code/1,
@@ -398,13 +399,31 @@ do_trace(_, Fmt, Args) ->
                get(ibrowse_trace_token) | Args]).
 -else.
 do_trace(true, Fmt, Args) ->
-    io:format("~s -- (~s) - "++Fmt,
-              [printable_date(), 
-               get(ibrowse_trace_token) | Args]);
+    Fmt_1  = "~s -- (~s) - "++Fmt,
+    Args_1 = [printable_date(), 
+              get(ibrowse_trace_token) | Args],
+    case application:get_env(ibrowse, logger_mf) of
+        {ok, {M, F}} ->
+            log_msg(M, F, Fmt_1, Args_1);
+        _ ->
+            log_msg(io, format, Fmt_1, Args_1)
+    end;
 do_trace(_, _, _) ->
     ok.
 -endif.
 
+log_msg(Fmt, Args) ->
+    case application:get_env(ibrowse, logger_mf) of
+        {ok, {M, F}} ->
+            log_msg(M, F, Fmt, Args),
+            ok;
+        _ ->
+            ok
+    end.
+
+log_msg(M, F, Fmt, Args) ->
+    catch apply(M, F, [Fmt, Args]).
+
 -ifdef(EUNIT).
 
 parse_url_test() ->

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b28542d1/test/Makefile
----------------------------------------------------------------------
diff --git a/test/Makefile b/test/Makefile
index 7277499..50a292c 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,5 +1,4 @@
-REBAR ?= $(shell which rebar3)
-IBROWSE_EBIN_PATH=../_build/default/lib/ibrowse/ebin
+IBROWSE_EBIN_PATH=../../ibrowse/ebin
 
 compile:
 	@erl -pa $(IBROWSE_EBIN_PATH) -make


[41/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Fixed links


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

Branch: refs/heads/upstream
Commit: a1be5369c94920e3fbb8729ac81125524acb56a6
Parents: 96ea3cb
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Wed Nov 25 08:32:14 2015 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Wed Nov 25 08:32:14 2015 +0000

----------------------------------------------------------------------
 CHANGELOG           | 3 +++
 README.md           | 2 +-
 src/ibrowse.app.src | 2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a1be5369/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index ad15c1f..17fa072 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,9 @@
 CONTRIBUTIONS & CHANGE HISTORY
 ==============================
 
+25-11-2015 - v4.2.2
+             * Fix to ibrowse.app.src to enable publishing using Hex
+
 25-11-2015 - v4.2.1
              * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/132
              * Merged pull request https://github.com/cmullaparthi/ibrowse/pull/137

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a1be5369/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index ae060ae..396a25f 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang.
 
 **Comments to:** chandrashekhar.mullaparthi@gmail.com
 
-**Current Version:** 4.2.1
+**Current Version:** 4.2.2
 
 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/a1be5369/src/ibrowse.app.src
----------------------------------------------------------------------
diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src
index b3a0e8f..84781fc 100644
--- a/src/ibrowse.app.src
+++ b/src/ibrowse.app.src
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "Erlang HTTP client application"},
-         {vsn, "4.2.1"},
+         {vsn, "4.2.2"},
          {registered, [ibrowse_sup, ibrowse]},
          {applications, [kernel,stdlib]},
 	 {env, []},


[43/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Clean up tests


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

Branch: refs/heads/upstream
Commit: 1917a70868cdb985969a346ea1bd31708a5b0efe
Parents: 411468d
Author: Chandrashekhar Mullaparthi <ch...@gmail.com>
Authored: Tue Jan 19 00:13:17 2016 +0000
Committer: Chandrashekhar Mullaparthi <ch...@gmail.com>
Committed: Tue Jan 19 00:13:17 2016 +0000

----------------------------------------------------------------------
 Makefile                     | 19 ++++++++++++--
 src/ibrowse_http_client.erl  |  6 ++---
 test/Makefile                |  9 ++++---
 test/ibrowse_test.erl        | 54 +++++++++++++++++++++++++++++----------
 test/ibrowse_test_server.erl | 51 ++++++++++++++++++++++++++++++++----
 test/ibrowse_tests.erl       |  4 +--
 6 files changed, 115 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index 918f33b..396140e 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,22 @@ compile:
 clean:
 	$(REBAR) clean
 
-test:
+test: unit_tests old_tests eunit
+	@echo "====================================================="
+
+unit_tests:
+	@echo "====================================================="
+	@echo "Running tests..."
+	@cd test && make test && cd ..
+
+old_tests:
+	@echo "====================================================="
+	@echo "Running old tests..."
+	@cd test && make old_tests && cd ..
+
+eunit:
+	@echo "====================================================="
+	@echo "Running eunit tests..."
 	$(REBAR) eunit
 
 xref: all
@@ -30,4 +45,4 @@ install: compile
 	mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
 	cp -r _build/lib/default/ibrowse/ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/
 
-.PHONY: test docs
\ No newline at end of file
+.PHONY: test docs

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/src/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl
index b7f4622..2d700a7 100644
--- a/src/ibrowse_http_client.erl
+++ b/src/ibrowse_http_client.erl
@@ -539,9 +539,9 @@ handle_sock_closed(#state{reply_buffer = Buf, reqs = Reqs, http_status_code = SC
                         true ->
                             {ok, Status_line, Raw_headers, Body, Raw_req};
                         false when Give_raw_req == false ->
-                            {ok, SC, Headers, Buf};
+                            {ok, SC, Headers, Body};
                         false ->
-                            {ok, SC, Headers, Buf, Raw_req}
+                            {ok, SC, Headers, Body, Raw_req}
                     end,
             State_1 = do_reply(State, From, StreamTo, ReqId, Resp_format, Reply),
             case Retry_state of
@@ -1257,7 +1257,7 @@ parse_response(Data, #state{reply_buffer = Acc, reqs = Reqs,
                 undefined when HttpVsn =:= "HTTP/1.0";
                                ConnClose =:= "close" ->
                     send_async_headers(ReqId, StreamTo, Give_raw_headers, State_1),
-                    State_1#state{reply_buffer = Data_1};
+                    accumulate_response(Data_1, State_1);
                 undefined when StatCode =:= "303" ->
                     %% Some servers send 303 requests without a body.
                     %% RFC2616 says that they SHOULD, but they dont.

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/test/Makefile
----------------------------------------------------------------------
diff --git a/test/Makefile b/test/Makefile
index c7d6f42..8211bb7 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,10 +1,13 @@
 REBAR ?= $(shell which rebar3)
 
-all: compile
-	erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test local_unit_tests -s erlang halt
+test: compile
+	@erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test local_unit_tests -s erlang halt
+
+old_tests: compile
+	@erl -noshell -boot start_clean -pa ../../ibrowse/ebin -s ibrowse_test unit_tests -s erlang halt
 
 compile:
-	erl -pa ../../ibrowse/ebin -make
+	@erl -pa ../../ibrowse/ebin -make
 
 clean:
 	$(REBAR) clean

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 2bf46a9..89d5d06 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -37,7 +37,8 @@
          test_binary_headers/1,
          test_generate_body_0/0,
          test_retry_of_requests/0,
-         test_retry_of_requests/1
+         test_retry_of_requests/1,
+	 test_save_to_file_no_content_length/0
 	]).
 
 -include_lib("ibrowse/include/ibrowse.hrl").
@@ -220,8 +221,13 @@ dump_errors(Key, Iod) ->
                       {local_test_fun, test_head_transfer_encoding, []},
                       {local_test_fun, test_head_response_with_body, []},
                       {local_test_fun, test_303_response_with_a_body, []},
+		      {local_test_fun, test_303_response_with_no_body, []},
                       {local_test_fun, test_binary_headers, []},
-                      {local_test_fun, test_retry_of_requests, []}
+                      {local_test_fun, test_retry_of_requests, []},
+		      {local_test_fun, test_save_to_file_no_content_length, []},
+		      {local_test_fun, verify_chunked_streaming, []},
+		      {local_test_fun, test_chunked_streaming_once, []},
+		      {local_test_fun, test_generate_body_0, []}
                      ]).
 
 -define(TEST_LIST, [{"http://intranet/messenger", get},
@@ -254,17 +260,16 @@ dump_errors(Key, Iod) ->
 		    {"http://jigsaw.w3.org/HTTP/CL/", get},
 		    {"http://www.httpwatch.com/httpgallery/chunked/", get},
                     {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}
-		   ] ++ ?LOCAL_TESTS).
+		   ]).
 
 local_unit_tests() ->
     unit_tests([], ?LOCAL_TESTS).
 
 unit_tests() ->
-    error_logger:tty(false),
-    unit_tests([], ?TEST_LIST),
-    error_logger:tty(true).
+    unit_tests([], ?TEST_LIST).
 
 unit_tests(Options, Test_list) ->
+    error_logger:tty(false),
     application:start(crypto),
     application:start(asn1),
     application:start(public_key),
@@ -284,6 +289,7 @@ unit_tests(Options, Test_list) ->
 	    io:format("Timed out waiting for tests to complete~n", [])
     end,
     catch ibrowse_test_server:stop_server(8181),
+    error_logger:tty(true),
     ok.
 
 unit_tests_1(Parent, Options, Test_list) ->
@@ -320,7 +326,8 @@ verify_chunked_streaming(Options) ->
     Res2 = compare_responses(Result_without_streaming, Async_response_list, Async_response_bin_once),
     case {Res1, Res2} of
         {success, success} ->
-            io:format("  Chunked streaming working~n", []);
+            io:format("  Chunked streaming working~n", []),
+	    success;
         _ ->
             ok
     end.
@@ -335,7 +342,7 @@ test_chunked_streaming_once(Options) ->
     io:format("  Fetching data with streaming as binary, {active, once}...~n", []),
     case do_async_req_list(Url, get, [once, {response_format, binary} | Options]) of
         {ok, _, _, _} ->
-            io:format("  Success!~n", []);
+            success;
         Err ->
             io:format("  Fail: ~p~n", [Err])
     end.
@@ -445,8 +452,8 @@ maybe_stream_next(Req_id, Options) ->
 
 execute_req(local_test_fun, Method, Args) ->
     reset_ibrowse(),
-    io:format("     ~-54.54w: ", [Method]),
     Result = (catch apply(?MODULE, Method, Args)),
+    io:format("     ~-54.54w: ", [Method]),
     io:format("~p~n", [Result]);
 execute_req(Url, Method, Options) ->
     io:format("~7.7w, ~50.50s: ", [Method, Url]),
@@ -559,6 +566,29 @@ test_303_response_with_a_body(Url) ->
     end.
 
 %%------------------------------------------------------------------------------
+%% Test that when the save_response_to_file option is used with a server which
+%% does not send the Content-Length header, the response is saved correctly to
+%% a file
+%%------------------------------------------------------------------------------
+test_save_to_file_no_content_length() ->
+    clear_msg_q(),
+    {{Y, M, D}, {H, Mi, S}} = calendar:local_time(),
+    Test_file = filename:join
+		  ([".", 
+		    lists:flatten(
+		      io_lib:format("test_save_to_file_no_content_length_~p~p~p_~p~p~p.txt", [Y, M, D, H, Mi, S]))]),
+    try
+	case ibrowse:send_req("http://localhost:8181/ibrowse_send_file_conn_close", [], get, [], [{save_response_to_file, Test_file}]) of
+	    {ok, "200", _, {file, Test_file}} ->
+		success;
+	    Res ->
+		{test_failed, Res}
+	end
+    after
+	file:delete(Test_file)
+    end.
+
+%%------------------------------------------------------------------------------
 %% Test that retry of requests happens correctly, and that ibrowse doesn't retry
 %% if there is not enough time left
 %%------------------------------------------------------------------------------
@@ -775,11 +805,10 @@ do_test_20122010_1(Expected_resp, Req_id, Acc) ->
 %% Test requests where body is generated using a Fun
 %%------------------------------------------------------------------------------
 test_generate_body_0() ->
-    io:format("Testing that generation of body using fun works...~n", []),
     Tid = ets:new(ibrowse_test_state, [public]),
     try
         Body_1 = <<"Part 1 of the body">>,
-        Body_2 = <<"Part 2 of the body\r\n\r\n">>,
+        Body_2 = <<"Part 2 of the body\r\n">>,
         Size = size(Body_1) + size(Body_2),
         Body = list_to_binary([Body_1, Body_2]),
         Fun = fun() ->
@@ -799,9 +828,8 @@ test_generate_body_0() ->
                               post,
                               Fun,
                               [{response_format, binary},
-                               {http_vsn, {1,0}}]) of
+                               {http_vsn, {1,1}}]) of
             {ok, "200", _, Body} ->
-                io:format("    Success~n", []),
                 success;
             Err ->
                 io:format("Test failed : ~p~n", [Err]),

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/test/ibrowse_test_server.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl
index 90c46c4..067e627 100644
--- a/test/ibrowse_test_server.erl
+++ b/test/ibrowse_test_server.erl
@@ -10,10 +10,10 @@
          get_conn_pipeline_depth/0
         ]).
 
--record(request, {method, uri, version, headers = [], body = []}).
+-record(request, {method, uri, version, headers = [], body = [], state}).
 
 -define(dec2hex(X), erlang:integer_to_list(X, 16)).
--define(ACCEPT_TIMEOUT_MS, 1000).
+-define(ACCEPT_TIMEOUT_MS, 10000).
 -define(CONN_PIPELINE_DEPTH, conn_pipeline_depth).
 
 start_server(Port, Sock_type) ->
@@ -45,7 +45,7 @@ start_server(Port, Sock_type) ->
     spawn_link(Fun).
 
 stop_server(Port) ->
-    server_proc_name(Port) ! stop,
+    catch server_proc_name(Port) ! stop,
     timer:sleep(2000),  % wait for server to receive msg and unregister
     ok.
 
@@ -72,7 +72,6 @@ accept_loop(Sock, Sock_type) ->
         {ok, Conn} ->
             Pid = spawn_link(fun() -> connection(Conn, Sock_type) end),
             set_controlling_process(Conn, Sock_type, Pid),
-            Pid ! {setopts, [{active, true}]},
             accept_loop(Sock, Sock_type);
         {error, timeout} ->
             receive
@@ -88,6 +87,7 @@ accept_loop(Sock, Sock_type) ->
 connection(Conn, Sock_type) ->
     catch ets:insert(?CONN_PIPELINE_DEPTH, {self(), 0}),
     try
+	inet:setopts(Conn, [{packet, http}, {active, true}]),
         server_loop(Conn, Sock_type, #request{})
     after
         catch ets:delete(?CONN_PIPELINE_DEPTH, self())
@@ -118,10 +118,22 @@ server_loop(Sock, Sock_type, #request{headers = Headers} = Req) ->
                     gen_tcp:shutdown(Sock, read_write);
                 not_done ->
                     ok;
+		collect_body ->
+		    server_loop(Sock, Sock_type, Req#request{state = collect_body});
                 _ ->
                     catch ets:update_counter(?CONN_PIPELINE_DEPTH, self(), -1)
             end,
             server_loop(Sock, Sock_type, #request{});
+        {http, Sock, {http_error, Packet}} when Req#request.state == collect_body ->
+	    Req_1 = Req#request{body = list_to_binary([Packet, Req#request.body])},
+	    case process_request(Sock, Sock_type, Req_1) of
+		close_connection ->
+                    gen_tcp:shutdown(Sock, read_write);
+                ok ->
+                    server_loop(Sock, Sock_type, #request{});
+		collect_body ->
+		    server_loop(Sock, Sock_type, Req_1)
+	    end;	    
         {http, Sock, {http_error, Err}} ->
             io:format("Error parsing HTTP request:~n"
                       "Req so far : ~p~n"
@@ -186,6 +198,19 @@ process_request(Sock, Sock_type,
     Resp = <<"HTTP/1.1 400 Bad Request\r\nServer: Apache-Coyote/1.1\r\nContent-Length:5\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\n\r\nabcde">>,
     do_send(Sock, Sock_type, Resp);
 process_request(Sock, Sock_type,
+                #request{method='POST',
+                         headers = Headers,
+                         uri = {abs_path, "/echo_body"},
+			body = Body}) ->
+    Content_len = get_content_length(Headers),
+    case iolist_size(Body) == Content_len of
+	true ->
+	    Resp = [<<"HTTP/1.1 200 OK\r\nContent-Length: ">>, integer_to_list(Content_len), <<"\r\nServer: ibrowse_test_server\r\n\r\n">>, Body],
+	    do_send(Sock, Sock_type, list_to_binary(Resp));
+	false ->
+	    collect_body
+    end;
+process_request(Sock, Sock_type,
                 #request{method='GET',
                          headers = Headers,
                          uri = {abs_path, "/ibrowse_echo_header"}}) ->
@@ -213,7 +238,7 @@ process_request(Sock, Sock_type,
                 #request{method='POST',
                          headers = _Headers,
                          uri = {abs_path, "/ibrowse_303_no_body_test"}}) ->
-    Resp = <<"HTTP/1.1 303 See Other\r\nLocation: http://example.org\r\n">>,
+    Resp = <<"HTTP/1.1 303 See Other\r\nLocation: http://example.org\r\n\r\n">>,
     do_send(Sock, Sock_type, Resp);
 process_request(Sock, Sock_type,
                 #request{method='POST',
@@ -236,6 +261,15 @@ process_request(Sock, Sock_type,
     Resp = <<"HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\nConnection: close\r\n\r\n">>,
     do_send(Sock, Sock_type, Resp),
     close_connection;
+process_request(Sock, Sock_type,
+    #request{method='GET',
+        headers = _Headers,
+        uri = {abs_path, "/ibrowse_send_file_conn_close"}}) ->
+    Resp = <<"HTTP/1.1 200 OK\r\nServer: Apache-Coyote/1.1\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\nConnection: close\r\n\r\nblahblah-">>,    
+    do_send(Sock, Sock_type, Resp),
+    timer:sleep(1000),
+    do_send(Sock, Sock_type, <<"blahblah">>),
+    close_connection;
 process_request(_Sock, _Sock_type, #request{uri = {abs_path, "/never_respond"} } ) ->
     not_done;
 process_request(Sock, Sock_type, Req) ->
@@ -300,3 +334,10 @@ to_lower(X) when is_atom(X) ->
     list_to_atom(to_lower(atom_to_list(X)));
 to_lower(X) when is_list(X) ->
     string:to_lower(X).
+
+get_content_length([{http_header, _, 'Content-Length', _, V} | _]) ->
+    list_to_integer(V);
+get_content_length([{http_header, _, _X, _, _Y} | T]) ->
+    get_content_length(T);
+get_content_length([]) ->
+    undefined.

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/1917a708/test/ibrowse_tests.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_tests.erl b/test/ibrowse_tests.erl
index 3517011..d3b07b1 100644
--- a/test/ibrowse_tests.erl
+++ b/test/ibrowse_tests.erl
@@ -1,11 +1,11 @@
-%%% File    : ibrowse_functional_tests.erl
+%%% File    : ibrowse_tests.erl
 %%% Authors : Benjamin Lee <http://github.com/benjaminplee>
 %%%           Dan Schwabe <http://github.com/dfschwabe>
 %%%           Brian Richards <http://github.com/richbria>
 %%% Description : Functional tests of the ibrowse library using a live test HTTP server
 %%% Created : 18 November 2014 by Benjamin Lee <ya...@gmail.com>
 
--module(ibrowse_functional_tests).
+-module(ibrowse_tests).
 
 -include_lib("eunit/include/eunit.hrl").
 -define(PER_TEST_TIMEOUT_SEC, 60).


[48/50] ibrowse commit: updated refs/heads/upstream to b28542d

Posted by rn...@apache.org.
Modified build to get travis builds to succeed


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

Branch: refs/heads/upstream
Commit: b1e9ad427f95229a46bd09f4a18808cbb1ec053d
Parents: 7aa39ea
Author: Chandru Mullaparthi <ch...@bet365.com>
Authored: Tue Apr 19 19:38:28 2016 +0100
Committer: Chandru Mullaparthi <ch...@bet365.com>
Committed: Tue Apr 19 19:38:28 2016 +0100

----------------------------------------------------------------------
 test/ibrowse_test.erl | 11 -----------
 1 file changed, 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/b1e9ad42/test/ibrowse_test.erl
----------------------------------------------------------------------
diff --git a/test/ibrowse_test.erl b/test/ibrowse_test.erl
index 56c16b8..cd78049 100644
--- a/test/ibrowse_test.erl
+++ b/test/ibrowse_test.erl
@@ -12,8 +12,6 @@
 	 unit_tests/0,
          unit_tests/2,
          unit_tests_1/3,
-	 ue_test_/0,
-	 ue_test_/1,
 	 verify_chunked_streaming/0,
 	 verify_chunked_streaming/1,
          test_chunked_streaming_once/0,
@@ -503,15 +501,6 @@ execute_req(Url, Method, Options) ->
 	    io:format("~p~n", [Err])
     end.
 
-ue_test_() ->
-    ue_test_(lists:duplicate(1024, $?)).
-ue_test_(Data) ->
-    {Time, Res} = timer:tc(ibrowse_lib, url_encode, [Data]),
-    io:format("Time -> ~p~n", [Time]),
-    io:format("Data Length -> ~p~n", [length(Data)]),
-    io:format("Res Length -> ~p~n", [length(Res)]).
-%    io:format("Result -> ~s~n", [Res]).
-
 log_msg(Fmt, Args) ->
     io:format("~s -- " ++ Fmt,
 	      [ibrowse_lib:printable_date() | Args]).