summaryrefslogtreecommitdiff
path: root/apps/couch/src/couch_rep_httpc.erl
diff options
context:
space:
mode:
Diffstat (limited to 'apps/couch/src/couch_rep_httpc.erl')
-rw-r--r--apps/couch/src/couch_rep_httpc.erl44
1 files changed, 33 insertions, 11 deletions
diff --git a/apps/couch/src/couch_rep_httpc.erl b/apps/couch/src/couch_rep_httpc.erl
index 8153fdcf..e22c8f81 100644
--- a/apps/couch/src/couch_rep_httpc.erl
+++ b/apps/couch/src/couch_rep_httpc.erl
@@ -14,8 +14,9 @@
-include("couch_db.hrl").
-include_lib("ibrowse/include/ibrowse.hrl").
--export([db_exists/1, db_exists/2, full_url/1, request/1, redirected_request/2,
- redirect_url/2, spawn_worker_process/1, spawn_link_worker_process/1]).
+-export([db_exists/1, db_exists/2]).
+-export([full_url/1, request/1, redirected_request/3]).
+-export([spawn_worker_process/1, spawn_link_worker_process/1]).
-export([ssl_options/1]).
request(#http_db{} = Req) ->
@@ -100,6 +101,9 @@ db_exists(Req, CanonicalUrl, CreateDB) ->
{ok, "302", RespHeaders, _} ->
RedirectUrl = redirect_url(RespHeaders, Req#http_db.url),
db_exists(Req#http_db{url = RedirectUrl}, CanonicalUrl);
+ {ok, "303", RespHeaders, _} ->
+ RedirectUrl = redirect_url(RespHeaders, Req#http_db.url),
+ db_exists(Req#http_db{method = get, url = RedirectUrl}, CanonicalUrl);
{ok, "401", _, _} ->
throw({unauthorized, ?l2b(Url)});
Error ->
@@ -123,15 +127,24 @@ config_http(Url) ->
redirect_url(RespHeaders, OrigUrl) ->
MochiHeaders = mochiweb_headers:make(RespHeaders),
RedUrl = mochiweb_headers:get_value("Location", MochiHeaders),
- {url, _, Base, Port, _, _, Path, Proto} = ibrowse_lib:parse_url(RedUrl),
- {url, _, _, _, User, Passwd, _, _} = ibrowse_lib:parse_url(OrigUrl),
+ #url{
+ host = Host, host_type = HostType, port = Port,
+ path = Path, protocol = Proto
+ } = ibrowse_lib:parse_url(RedUrl),
+ #url{username = User, password = Passwd} = ibrowse_lib:parse_url(OrigUrl),
Creds = case is_list(User) andalso is_list(Passwd) of
true ->
User ++ ":" ++ Passwd ++ "@";
false ->
[]
end,
- atom_to_list(Proto) ++ "://" ++ Creds ++ Base ++ ":" ++
+ HostPart = case HostType of
+ ipv6_address ->
+ "[" ++ Host ++ "]";
+ _ ->
+ Host
+ end,
+ atom_to_list(Proto) ++ "://" ++ Creds ++ HostPart ++ ":" ++
integer_to_list(Port) ++ Path.
full_url(#http_db{url=Url} = Req) when is_binary(Url) ->
@@ -154,9 +167,8 @@ process_response({ok, Status, Headers, Body}, Req) ->
Code = list_to_integer(Status),
if Code =:= 200; Code =:= 201 ->
?JSON_DECODE(maybe_decompress(Headers, Body));
- Code =:= 301; Code =:= 302 ->
- RedirectUrl = redirect_url(Headers, Req#http_db.url),
- do_request(redirected_request(Req, RedirectUrl));
+ Code =:= 301; Code =:= 302 ; Code =:= 303 ->
+ do_request(redirected_request(Code, Headers, Req));
Code =:= 409 ->
throw(conflict);
Code >= 400, Code < 500 ->
@@ -205,16 +217,26 @@ process_response({error, Reason}, Req) ->
do_request(Req#http_db{retries = Retries-1, pause = 2*Pause})
end.
-redirected_request(Req, RedirectUrl) ->
+redirected_request(Code, Headers, Req) ->
+ RedirectUrl = redirect_url(Headers, Req#http_db.url),
{Base, QStr, _} = mochiweb_util:urlsplit_path(RedirectUrl),
QS = mochiweb_util:parse_qs(QStr),
- Hdrs = case couch_util:get_value(<<"oauth">>, Req#http_db.auth) of
+ ReqHeaders = case couch_util:get_value(<<"oauth">>, Req#http_db.auth) of
undefined ->
Req#http_db.headers;
_Else ->
lists:keydelete("Authorization", 1, Req#http_db.headers)
end,
- Req#http_db{url=Base, resource="", qs=QS, headers=Hdrs}.
+ Req#http_db{
+ method = case couch_util:to_integer(Code) of
+ 303 -> get;
+ _ -> Req#http_db.method
+ end,
+ url = Base,
+ resource = "",
+ qs = QS,
+ headers = ReqHeaders
+ }.
spawn_worker_process(Req) ->
Url = ibrowse_lib:parse_url(Req#http_db.url),