From c48e8ef02d8ba7a93dbb3e72c7be3441cb6bacbf Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Sun, 6 Jul 2008 18:52:56 +0000 Subject: Add RESTful API for document attachments as per http://groups.google.com/group/couchdb/browse_thread/thread/c84c5f35afb5db2a with not yet comprehensive tests. git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@674334 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_httpd.erl | 108 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 6ae51411..5615ac3e 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -633,8 +633,114 @@ handle_attachment_request(Req, 'GET', _DbName, Db, DocId, FileName) -> throw(Error) end; +handle_attachment_request(Req, 'DELETE', _DbName, Db, DocId, FileName) -> + QueryRev = proplists:get_value("rev", Req:parse_qs()), + Etag = case Req:get_header_value("If-Match") of + undefined -> + undefined; + Tag -> + string:strip(Tag, both, $") + end, + case {QueryRev, Etag} of + {undefined, undefined} -> + throw({missing_rev, "Document rev/etag must be specified to delete"}); + {_, undefined} -> + QueryRev; + {undefined, _} -> + Etag; + _ when QueryRev == Etag -> + Etag; + _ -> + throw({bad_request, "Document rev and etag have different values"}) + end, + + case couch_db:open_doc(Db, DocId, []) of + {ok, Doc} -> + #doc{attachments=Attachments,revs=Revs} = Doc, + case proplists:get_value(FileName, Attachments) of + undefined -> + throw({not_found, missing}); + {_Type, _Bin} -> + + NewAttachmentList = proplists:delete(FileName, Attachments), + + {ok, NewRev} = couch_db:update_doc(Db, Doc#doc{ + id=DocId, + revs=Revs, + attachments=NewAttachmentList + }, []), + + send_json(Req, 200, {obj, [ + {ok, true}, + {id, DocId}, + {rev, NewRev} + ]}) + end; + Error -> + throw(Error) + end; + +handle_attachment_request(Req, 'PUT', _DbName, Db, DocId, FileName) -> + case couch_db:open_doc(Db, DocId, []) of + {ok, Doc} -> + #doc{attachments=Attachments,revs=OldRevs} = Doc, + + NewAttachments = + case proplists:get_value(FileName, Attachments) of + undefined -> % new attachment, just append to list + Revs = OldRevs, + lists:append(Attachments, [{FileName, { + Req:get_header_value("Content-Type"), + Req:recv_body() + }}]); + + {_Type, _Bin} -> % update of an existing attachment, delete and re-add + QueryRev = proplists:get_value("rev", Req:parse_qs()), + Etag = case Req:get_header_value("If-Match") of + undefined -> + undefined; + Tag -> + string:strip(Tag, both, $") + end, + Revs = case {QueryRev, Etag} of + {undefined, undefined} -> + throw({missing_rev, "Document rev/etag must be specified to delete"}); + {_, undefined} -> + [QueryRev]; + {undefined, _} -> + [Etag]; + _ when QueryRev == Etag -> + [Etag]; + _ -> + throw({bad_request, "Document rev and etag have different values"}) + end, + + lists:append( + proplists:delete(FileName, Attachments), + [{FileName, { + Req:get_header_value("Content-Type"), + Req:recv_body() + } + }]) + end, + + {ok, NewRev} = couch_db:update_doc(Db, Doc#doc{ + id=DocId, + revs=Revs, + attachments=NewAttachments + }, []), + + send_json(Req, 201, {obj, [ + {ok, true}, + {id, DocId}, + {rev, NewRev} + ]}); + Error -> + throw(Error) + end; + handle_attachment_request(_Req, _Method, _DbName, _Db, _DocId, _FileName) -> - throw({method_not_allowed, "GET,HEAD"}). + throw({method_not_allowed, "GET,HEAD,DELETE,PUT"}). % View request handling internals -- cgit v1.2.3