You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by fd...@apache.org on 2010/10/16 20:25:13 UTC

svn commit: r1023345 - in /couchdb/trunk/src/couchdb: couch_rep_att.erl couch_rep_changes_feed.erl couch_rep_httpc.erl

Author: fdmanana
Date: Sat Oct 16 18:25:12 2010
New Revision: 1023345

URL: http://svn.apache.org/viewvc?rev=1023345&view=rev
Log:
Replicator: deal with 303 HTTP redirects. Closes COUCHDB-918.

Modified:
    couchdb/trunk/src/couchdb/couch_rep_att.erl
    couchdb/trunk/src/couchdb/couch_rep_changes_feed.erl
    couchdb/trunk/src/couchdb/couch_rep_httpc.erl

Modified: couchdb/trunk/src/couchdb/couch_rep_att.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_rep_att.erl?rev=1023345&r1=1023344&r2=1023345&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_rep_att.erl (original)
+++ couchdb/trunk/src/couchdb/couch_rep_att.erl Sat Oct 16 18:25:12 2010
@@ -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),

Modified: couchdb/trunk/src/couchdb/couch_rep_changes_feed.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_rep_changes_feed.erl?rev=1023345&r1=1023344&r2=1023345&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_rep_changes_feed.erl (original)
+++ couchdb/trunk/src/couchdb/couch_rep_changes_feed.erl Sat Oct 16 18:25:12 2010
@@ -95,10 +95,10 @@ init([Parent, #http_db{}=Source, Since, 
     {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),

Modified: couchdb/trunk/src/couchdb/couch_rep_httpc.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_rep_httpc.erl?rev=1023345&r1=1023344&r2=1023345&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_rep_httpc.erl (original)
+++ couchdb/trunk/src/couchdb/couch_rep_httpc.erl Sat Oct 16 18:25:12 2010
@@ -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, B
     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),