couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fdman...@apache.org
Subject svn commit: r1172389 - /couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl
Date Sun, 18 Sep 2011 22:32:55 GMT
Author: fdmanana
Date: Sun Sep 18 22:32:55 2011
New Revision: 1172389

URL: http://svn.apache.org/viewvc?rev=1172389&view=rev
Log:
Replicator: don't use chunked encoding for _bulk_docs

Nginx and a few other servers don't like PUT/POST requests
without a Content-Length header, making it impossible to
do a chunked transfer encoding for these requests.
Issue and patch tested by Dale Harvey, thanks.

Closes COUCHDB-1286.

This is a backport of revision 1172388 from trunk.

Modified:
    couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl

Modified: couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl?rev=1172389&r1=1172388&r2=1172389&view=diff
==============================================================================
--- couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl (original)
+++ couchdb/branches/1.2.x/src/couchdb/couch_api_wrap.erl Sun Sep 18 22:32:55 2011
@@ -250,41 +250,49 @@ update_doc(Db, Doc, Options, Type) ->
 update_docs(Db, DocList, Options) ->
     update_docs(Db, DocList, Options, interactive_edit).
 
+update_docs(_Db, [], _Options, _UpdateType) ->
+    {ok, []};
 update_docs(#httpdb{} = HttpDb, DocList, Options, UpdateType) ->
     FullCommit = atom_to_list(not lists:member(delay_commit, Options)),
-    Prefix1 = case UpdateType of
+    Prefix = case UpdateType of
     replicated_changes ->
-        {prefix, <<"{\"new_edits\":false,\"docs\":[">>};
+        <<"{\"new_edits\":false,\"docs\":[">>;
     interactive_edit ->
-        {prefix, <<"{\"docs\":[">>}
+        <<"{\"docs\":[">>
     end,
+    Suffix = <<"]}">>,
+    % Note: nginx and other servers don't like PUT/POST requests without
+    % a Content-Length header, so we can't do a chunked transfer encoding
+    % and JSON encode each doc only before sending it through the socket.
+    {Docs, Len} = lists:mapfoldl(
+        fun(#doc{} = Doc, Acc) ->
+            Json = ?JSON_ENCODE(couch_doc:to_json_obj(Doc, [revs, attachments])),
+            {Json, Acc + iolist_size(Json)};
+        (Doc, Acc) ->
+            {Doc, Acc + iolist_size(Doc)}
+        end,
+        byte_size(Prefix) + byte_size(Suffix) + length(DocList) - 1,
+        DocList),
     BodyFun = fun(eof) ->
             eof;
         ([]) ->
-            {ok, <<"]}">>, eof};
-        ([{prefix, Prefix} | Rest]) ->
+            {ok, Suffix, eof};
+        ([prefix | Rest]) ->
             {ok, Prefix, Rest};
-        ([Doc]) when is_record(Doc, doc) ->
-            DocJson = couch_doc:to_json_obj(Doc, [revs, attachments]),
-            {ok, ?JSON_ENCODE(DocJson), []};
-        ([Doc | RestDocs]) when is_record(Doc, doc) ->
-            DocJson = couch_doc:to_json_obj(Doc, [revs, attachments]),
-            {ok, [?JSON_ENCODE(DocJson), ","], RestDocs};
         ([Doc]) ->
-            % IO list
             {ok, Doc, []};
         ([Doc | RestDocs]) ->
-            % IO list
             {ok, [Doc, ","], RestDocs}
     end,
+    Headers = [
+        {"Content-Length", Len},
+        {"Content-Type", "application/json"},
+        {"X-Couch-Full-Commit", FullCommit}
+    ],
     send_req(
         HttpDb,
         [{method, post}, {path, "_bulk_docs"},
-            {body, {BodyFun, [Prefix1 | DocList]}},
-            {ibrowse_options, [{transfer_encoding, chunked}]},
-            {headers, [
-                {"X-Couch-Full-Commit", FullCommit},
-                {"Content-Type", "application/json"} ]}],
+            {body, {BodyFun, [prefix | Docs]}}, {headers, Headers}],
         fun(201, _, Results) when is_list(Results) ->
                 {ok, bulk_results_to_errors(DocList, Results, remote)};
            (417, _, Results) when is_list(Results) ->



Mime
View raw message