You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2012/11/14 15:00:19 UTC

git commit: Send attachment headers in multipart responses

Updated Branches:
  refs/heads/1368-fix-multipart-header-parts [created] 18971de71


Send attachment headers in multipart responses

Closes COUCHDB-1368


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

Branch: refs/heads/1368-fix-multipart-header-parts
Commit: 18971de71c93c3a00e408b3d4eb67be8c695150c
Parents: d7f2037
Author: Jan Lehnardt <ja...@apache.org>
Authored: Wed Nov 14 14:59:58 2012 +0100
Committer: Jan Lehnardt <ja...@apache.org>
Committed: Wed Nov 14 15:00:04 2012 +0100

----------------------------------------------------------------------
 share/www/script/test/attachments_multipart.js |   29 ++++++++---
 src/couchdb/couch_doc.erl                      |   52 +++++++++++++++++--
 2 files changed, 69 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/18971de7/share/www/script/test/attachments_multipart.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/attachments_multipart.js b/share/www/script/test/attachments_multipart.js
index 9b9ddbd..a306f51 100644
--- a/share/www/script/test/attachments_multipart.js
+++ b/share/www/script/test/attachments_multipart.js
@@ -18,7 +18,7 @@ couchTests.attachments_multipart= function(debug) {
   
   // mime multipart
             
-  xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
+  var xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
     headers: {"Content-Type": "multipart/related;boundary=\"abc123\""},
     body:
       "--abc123\r\n" +
@@ -177,14 +177,27 @@ couchTests.attachments_multipart= function(debug) {
   // parse out the multipart
   
   var sections = parseMultipart(xhr);
-  
+
   T(sections.length == 3);
-  
-  // The first section is the json doc. Check it's content-type. It contains
-  // the metadata for all the following attachments
-  
-  T(sections[0].headers['content-type'] == "application/json");
-  
+  // The first section is the json doc. Check it's content-type.
+  // Each part carries their own meta data.
+  TEquals("application/json", sections[0].headers['content-type'],
+    "Content-Type should be application/json for section[0]");
+  TEquals("application/test", sections[1].headers['Content-Type'],
+    "Content-Type should be application/test for section[1]");
+  TEquals("application/test", sections[2].headers['Content-Type'],
+    "Content-Type should be application/test for section[2]");
+
+  TEquals("21", sections[1].headers['Content-Length'],
+    "Content-Length should be 21 section[1]");
+  TEquals("18", sections[2].headers['Content-Length'],
+    "Content-Length should be 18 section[2]");
+
+  TEquals("foo.txt", sections[1].headers['Content-ID'],
+    "Content-ID should be foo.txt section[1]");
+  TEquals("bar.txt", sections[2].headers['Content-ID'],
+    "Content-ID should be bar.txt section[2]");
+
   var doc = JSON.parse(sections[0].body);
   
   T(doc._attachments['foo.txt'].follows == true);

http://git-wip-us.apache.org/repos/asf/couchdb/blob/18971de7/src/couchdb/couch_doc.erl
----------------------------------------------------------------------
diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl
index 349df4a..2c9fc8e 100644
--- a/src/couchdb/couch_doc.erl
+++ b/src/couchdb/couch_doc.erl
@@ -445,7 +445,15 @@ fold_streamed_data(RcvFun, LenLeft, Fun, Acc) when LenLeft > 0->
     fold_streamed_data(RcvFun, LenLeft - size(Bin), Fun, ResultAcc).
 
 len_doc_to_multi_part_stream(Boundary, JsonBytes, Atts, SendEncodedAtts) ->
-    AttsSize = lists:foldl(fun(#att{data=Data} = Att, AccAttsSize) ->
+    AttsSize = lists:foldl(fun(Att, AccAttsSize) ->
+            #att{
+                data=Data,
+                name=Name,
+                att_len=AttLen,
+                disk_len=DiskLen,
+                type=Type,
+                encoding=Encoding
+            } = Att,
             case Data of
             stub ->
                 AccAttsSize;
@@ -454,12 +462,29 @@ len_doc_to_multi_part_stream(Boundary, JsonBytes, Atts, SendEncodedAtts) ->
                 4 + % "\r\n\r\n"
                 case SendEncodedAtts of
                 true ->
-                    Att#att.att_len;
+                    % header
+                    length(integer_to_list(AttLen)) +
+                    AttLen;
                 _ ->
-                    Att#att.disk_len
+                    % header
+                    length(integer_to_list(DiskLen)) +
+                    DiskLen
+                end +
+                case Encoding of
+                identity -> 4;
+                _ -> size(list_to_binary(atom_to_list(Encoding)))
                 end +
                 4 + % "\r\n--"
-                size(Boundary)
+                size(Boundary) +
+
+                % attachment headers
+                size(Name) +
+                size(Type) +
+                48
+                % "\r\nContent-ID: "
+                % "\r\nContent-Type: "
+                % "\r\nContent-Length: "
+                % "\r\nContent-Transfer-Encoding: "
             end
         end, 0, Atts),
     if AttsSize == 0 ->
@@ -496,6 +521,25 @@ atts_to_mp([#att{data=stub} | RestAtts], Boundary, WriteFun,
     atts_to_mp(RestAtts, Boundary, WriteFun, SendEncodedAtts);
 atts_to_mp([Att | RestAtts], Boundary, WriteFun,
         SendEncodedAtts)  ->
+    #att{
+        name=Name,
+        att_len=Length,
+        type=Type,
+        encoding=Encoding
+    } = Att,
+
+    % write headers
+    LengthBin = list_to_binary(integer_to_list(Length)),
+    TransferEncoding = case Encoding of
+    identity -> <<"7bit">>; % eh?
+    _ -> list_to_binary(atom_to_list(Encoding)) % send encoded
+    end,
+    WriteFun(<<"\r\nContent-ID: ", Name/binary>>),
+    WriteFun(<<"\r\nContent-Type: ", Type/binary>>),
+    WriteFun(<<"\r\nContent-Length: ", LengthBin/binary>>),
+    WriteFun(<<"\r\nContent-Transfer-Encoding: ", TransferEncoding/binary>>),
+
+    % write data
     WriteFun(<<"\r\n\r\n">>),
     AttFun = case SendEncodedAtts of
     false ->