summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@apache.org>2010-10-16 18:25:12 +0000
committerFilipe David Borba Manana <fdmanana@apache.org>2010-10-16 18:25:12 +0000
commite0b39b55f581867327728f8e0af470144c77915a (patch)
tree6a647aee586f0917f31d15ac891f9d0fc92cb0a7 /src
parentec69a1b7916b8952fb8bcc8f054654d5681a9457 (diff)
Replicator: deal with 303 HTTP redirects. Closes COUCHDB-918.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1023345 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/couchdb/couch_rep_att.erl3
-rw-r--r--src/couchdb/couch_rep_changes_feed.erl13
-rw-r--r--src/couchdb/couch_rep_httpc.erl28
3 files changed, 27 insertions, 17 deletions
diff --git a/src/couchdb/couch_rep_att.erl b/src/couchdb/couch_rep_att.erl
index 3c09b90a..6bb993a8 100644
--- a/src/couchdb/couch_rep_att.erl
+++ b/src/couchdb/couch_rep_att.erl
@@ -106,8 +106,7 @@ validate_headers(_Req, 200, Headers) ->
MochiHeaders = mochiweb_headers:make(Headers),
{ok, mochiweb_headers:get_value("Content-Encoding", MochiHeaders)};
validate_headers(Req, Code, Headers) when Code > 299, Code < 400 ->
- Url = couch_rep_httpc:redirect_url(Headers, Req#http_db.url),
- NewReq = couch_rep_httpc:redirected_request(Req, Url),
+ NewReq = couch_rep_httpc:redirected_request(Code, Headers, Req),
{ibrowse_req_id, ReqId} = couch_rep_httpc:request(NewReq),
receive {ibrowse_async_headers, ReqId, NewCode, NewHeaders} ->
{ok, Encoding} = validate_headers(NewReq, list_to_integer(NewCode),
diff --git a/src/couchdb/couch_rep_changes_feed.erl b/src/couchdb/couch_rep_changes_feed.erl
index 7f7d3a38..98e929fe 100644
--- a/src/couchdb/couch_rep_changes_feed.erl
+++ b/src/couchdb/couch_rep_changes_feed.erl
@@ -95,10 +95,10 @@ init([Parent, #http_db{}=Source, Since, PostProps]) ->
{ibrowse_async_headers, ReqId, "200", _} ->
ibrowse:stream_next(ReqId),
{ok, #state{conn=Pid, last_seq=Since, reqid=ReqId, init_args=Args}};
- {ibrowse_async_headers, ReqId, Code, Hdrs} when Code=="301"; Code=="302" ->
+ {ibrowse_async_headers, ReqId, Code, Hdrs}
+ when Code =:= "301"; Code =:= "302"; Code =:= "303" ->
stop_link_worker(Pid),
- Url2 = couch_rep_httpc:redirect_url(Hdrs, Req#http_db.url),
- Req2 = couch_rep_httpc:redirected_request(Req, Url2),
+ Req2 = couch_rep_httpc:redirected_request(Code, Hdrs, Req),
Pid2 = couch_rep_httpc:spawn_link_worker_process(Req2),
Req3 = Req2#http_db{conn = Pid2},
{ibrowse_req_id, ReqId2} = couch_rep_httpc:request(Req3),
@@ -271,11 +271,10 @@ handle_headers(200, _, State) ->
maybe_stream_next(State),
{noreply, State};
handle_headers(Code, Hdrs, #state{init_args = InitArgs} = State)
- when Code =:= 301 ; Code =:= 302 ->
+ when Code =:= 301 ; Code =:= 302 ; Code =:= 303 ->
stop_link_worker(State#state.conn),
- [Parent, #http_db{url = Url1} = Source, Since, PostProps] = InitArgs,
- Url = couch_rep_httpc:redirect_url(Hdrs, Url1),
- Source2 = couch_rep_httpc:redirected_request(Source, Url),
+ [Parent, Source, Since, PostProps] = InitArgs,
+ Source2 = couch_rep_httpc:redirected_request(Code, Hdrs, Source),
Pid2 = couch_rep_httpc:spawn_link_worker_process(Source2),
Source3 = Source2#http_db{conn = Pid2},
{ibrowse_req_id, ReqId} = couch_rep_httpc:request(Source3),
diff --git a/src/couchdb/couch_rep_httpc.erl b/src/couchdb/couch_rep_httpc.erl
index bc4d7054..fea50355 100644
--- a/src/couchdb/couch_rep_httpc.erl
+++ b/src/couchdb/couch_rep_httpc.erl
@@ -14,8 +14,8 @@
-include("couch_db.hrl").
-include("../ibrowse/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, full_url/1, request/1, redirected_request/3,
+ spawn_worker_process/1, spawn_link_worker_process/1]).
-export([ssl_options/1]).
request(#http_db{} = Req) ->
@@ -98,6 +98,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);
Error ->
?LOG_DEBUG("DB at ~s could not be found because ~p", [Url, Error]),
throw({db_not_found, ?l2b(Url)})
@@ -140,9 +143,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 ->
@@ -191,16 +193,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),