On Wed, Nov 9, 2011 at 11:07 AM, <[email protected]> wrote: > Updated Branches: > refs/heads/master 866769f34 -> 7e3c69ba9 > > > some refactoring in couch_httpd_db.erl > > Fix COUCHDB-1277. These changes are largely for code clarity and > conciseness, but have a few other nice effects as well. > > * Responses to documents created/modified via form data POST to /db/doc > or copied with COPY should now include a Location header. > * ?batch=ok updates should include a Location header. > * Form data POST to /db/doc now includes an ETag response header. > * ?batch=ok is now supported for COPY and POST /db/doc updates. > * ?new_edits=false is now supported for more update paths. This change > is likely not generally useful, but listed here for completeness. > > > Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo > Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/7e3c69ba > Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/7e3c69ba > Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/7e3c69ba > > Branch: refs/heads/master > Commit: 7e3c69ba951de7cfaa095145ba49c58d539a28ea > Parents: e41d226 > Author: Randall Leeds <[email protected]> > Authored: Thu Sep 8 20:44:09 2011 -0700 > Committer: Randall Leeds <[email protected]> > Committed: Wed Nov 9 02:06:52 2011 -0800 > > ---------------------------------------------------------------------- > src/couchdb/couch_httpd_db.erl | 148 ++++++++++++---------------------- > 1 files changed, 52 insertions(+), 96 deletions(-) > ---------------------------------------------------------------------- > > > http://git-wip-us.apache.org/repos/asf/couchdb/blob/7e3c69ba/src/couchdb/couch_httpd_db.erl > ---------------------------------------------------------------------- > diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl > index dad8705..4691143 100644 > --- a/src/couchdb/couch_httpd_db.erl > +++ b/src/couchdb/couch_httpd_db.erl > @@ -203,7 +203,7 @@ db_req(#httpd{method='GET',path_parts=[_DbName]}=Req, Db) > -> > {ok, DbInfo} = couch_db:get_db_info(Db), > send_json(Req, {DbInfo}); > > -db_req(#httpd{method='POST',path_parts=[DbName]}=Req, Db) -> > +db_req(#httpd{method='POST',path_parts=[_DbName]}=Req, Db) -> > couch_httpd:validate_ctype(Req, "application/json"), > Doc = couch_doc:from_json_obj(couch_httpd:json_body(Req)), > validate_attachment_names(Doc), > @@ -214,33 +214,7 @@ db_req(#httpd{method='POST',path_parts=[DbName]}=Req, > Db) -> > Doc > end, > DocId = Doc2#doc.id, > - case couch_httpd:qs_value(Req, "batch") of > - "ok" -> > - % async_batching > - spawn(fun() -> > - case catch(couch_db:update_doc(Db, Doc2, [])) of > - {ok, _} -> ok; > - Error -> > - ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error]) > - end > - end), > - > - send_json(Req, 202, [], {[ > - {ok, true}, > - {id, DocId} > - ]}); > - _Normal -> > - % normal > - {ok, NewRev} = couch_db:update_doc(Db, Doc2, []), > - DocUrl = absolute_uri( > - Req, binary_to_list(<<"/",DbName/binary,"/", DocId/binary>>)), > - send_json(Req, 201, [{"Location", DocUrl}], {[ > - {ok, true}, > - {id, DocId}, > - {rev, couch_doc:rev_to_str(NewRev)} > - ]}) > - end; > - > + update_doc(Req, Db, DocId, Doc2); > > db_req(#httpd{path_parts=[_DbName]}=Req, _Db) -> > send_method_not_allowed(Req, "DELETE,GET,HEAD,POST"); > @@ -673,29 +647,18 @@ db_doc_req(#httpd{method='POST'}=Req, Db, DocId) -> > NewDoc = Doc#doc{ > atts = UpdatedAtts ++ OldAtts2 > }, > - {ok, NewRev} = couch_db:update_doc(Db, NewDoc, []), > - > - send_json(Req, 201, [{"ETag", "\"" ++ ?b2l(couch_doc:rev_to_str(NewRev)) > ++ "\""}], {[ > - {ok, true}, > - {id, DocId}, > - {rev, couch_doc:rev_to_str(NewRev)} > - ]}); > + update_doc(Req, Db, DocId, NewDoc); > > db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> > - #doc_query_args{ > - update_type = UpdateType > - } = parse_doc_query(Req), > couch_doc:validate_docid(DocId), > > - Loc = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)), > - RespHeaders = [{"Location", Loc}], > case couch_util:to_list(couch_httpd:header_value(Req, "Content-Type")) of > ("multipart/related;" ++ _) = ContentType -> > {ok, Doc0, WaitFun, Parser} = couch_doc:doc_from_multi_part_stream( > ContentType, fun() -> receive_request_data(Req) end), > Doc = couch_doc_from_req(Req, DocId, Doc0), > try > - Result = update_doc(Req, Db, DocId, Doc, RespHeaders, > UpdateType), > + Result = update_doc(Req, Db, DocId, Doc), > WaitFun(), > Result > catch throw:Err -> > @@ -704,28 +667,9 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> > throw(Err) > end; > _Else -> > - case couch_httpd:qs_value(Req, "batch") of > - "ok" -> > - % batch > - Doc = couch_doc_from_req(Req, DocId, couch_httpd:json_body(Req)), > - > - spawn(fun() -> > - case catch(couch_db:update_doc(Db, Doc, [])) of > - {ok, _} -> ok; > - Error -> > - ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error]) > - end > - end), > - send_json(Req, 202, [], {[ > - {ok, true}, > - {id, DocId} > - ]}); > - _Normal -> > - % normal > - Body = couch_httpd:json_body(Req), > - Doc = couch_doc_from_req(Req, DocId, Body), > - update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType) > - end > + Body = couch_httpd:json_body(Req), > + Doc = couch_doc_from_req(Req, DocId, Body), > + update_doc(Req, Db, DocId, Doc) > end; > > db_doc_req(#httpd{method='COPY'}=Req, Db, SourceDocId) -> > @@ -738,12 +682,7 @@ db_doc_req(#httpd{method='COPY'}=Req, Db, SourceDocId) -> > % open old doc > Doc = couch_doc_open(Db, SourceDocId, SourceRev, []), > % save new doc > - {ok, NewTargetRev} = couch_db:update_doc(Db, > - Doc#doc{id=TargetDocId, revs=TargetRevs}, []), > - % respond > - send_json(Req, 201, > - [{"ETag", "\"" ++ ?b2l(couch_doc:rev_to_str(NewTargetRev)) ++ "\""}], > - update_doc_result_to_json(TargetDocId, {ok, NewTargetRev})); > + update_doc(Req, Db, TargetDocId, Doc#doc{id=TargetDocId, > revs=TargetRevs}); > > db_doc_req(Req, _Db, _DocId) -> > send_method_not_allowed(Req, "DELETE,GET,HEAD,POST,PUT,COPY"). > @@ -863,11 +802,17 @@ update_doc_result_to_json(DocId, Error) -> > {[{id, DocId}, {error, ErrorStr}, {reason, Reason}]}. > > > +update_doc(Req, Db, DocId, #doc{deleted=false}=Doc) -> > + Loc = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)), > + update_doc(Req, Db, DocId, Doc, [{"Location", Loc}]); > update_doc(Req, Db, DocId, Doc) -> > update_doc(Req, Db, DocId, Doc, []). > > update_doc(Req, Db, DocId, Doc, Headers) -> > - update_doc(Req, Db, DocId, Doc, Headers, interactive_edit). > + #doc_query_args{ > + update_type = UpdateType > + } = parse_doc_query(Req), > + update_doc(Req, Db, DocId, Doc, Headers, UpdateType). > > update_doc(Req, Db, DocId, #doc{deleted=Deleted}=Doc, Headers, UpdateType) -> > case couch_httpd:header_value(Req, "X-Couch-Full-Commit") of > @@ -878,14 +823,33 @@ update_doc(Req, Db, DocId, #doc{deleted=Deleted}=Doc, > Headers, UpdateType) -> > _ -> > Options = [] > end, > - {ok, NewRev} = couch_db:update_doc(Db, Doc, Options, UpdateType), > - NewRevStr = couch_doc:rev_to_str(NewRev), > - ResponseHeaders = [{"ETag", <<"\"", NewRevStr/binary, "\"">>}] ++ > Headers, > - send_json(Req, if Deleted -> 200; true -> 201 end, > - ResponseHeaders, {[ > + case couch_httpd:qs_value(Req, "batch") of > + "ok" -> > + % async batching > + spawn(fun() -> > + case catch(couch_db:update_doc(Db, Doc, Options, > UpdateType)) of > + {ok, _} -> ok; > + Error -> > + ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error]) > + end > + end), > + send_json(Req, 202, Headers, {[ > {ok, true}, > - {id, DocId}, > - {rev, NewRevStr}]}). > + {id, DocId} > + ]}); > + _Normal -> > + % normal > + {ok, NewRev} = couch_db:update_doc(Db, Doc, Options, UpdateType), > + NewRevStr = couch_doc:rev_to_str(NewRev), > + ResponseHeaders = [{"ETag", <<"\"", NewRevStr/binary, "\"">>}] ++ > Headers, > + send_json(Req, > + if Deleted orelse Req#httpd.method == 'DELETE' -> 200; > + true -> 201 end, > + ResponseHeaders, {[ > + {ok, true}, > + {id, DocId}, > + {rev, NewRevStr}]}) > + end. > > couch_doc_from_req(Req, DocId, #doc{revs=Revs}=Doc) -> > validate_attachment_names(Doc), > @@ -917,7 +881,6 @@ couch_doc_from_req(Req, DocId, #doc{revs=Revs}=Doc) -> > couch_doc_from_req(Req, DocId, Json) -> > couch_doc_from_req(Req, DocId, couch_doc:from_json_obj(Json)). > > - > % Useful for debugging > % couch_doc_open(Db, DocId) -> > % couch_doc_open(Db, DocId, nil, []). > @@ -1132,25 +1095,18 @@ > db_attachment_req(#httpd{method=Method,mochi_req=MochiReq}=Req, Db, DocId, > FileN > DocEdited = Doc#doc{ > atts = NewAtt ++ [A || A <- Atts, A#att.name /= FileName] > }, > - {ok, UpdatedRev} = couch_db:update_doc(Db, DocEdited, []), > - #db{name=DbName} = Db, > > - {Status, Headers} = case Method of > - 'DELETE' -> > - {200, []}; > - _ -> > - {201, [{"ETag", "\"" ++ ?b2l(couch_doc:rev_to_str(UpdatedRev)) > ++ "\""}, > - {"Location", absolute_uri(Req, "/" ++ > - binary_to_list(DbName) ++ "/" ++ > - binary_to_list(DocId) ++ "/" ++ > - binary_to_list(FileName) > - )}]} > - end, > - send_json(Req,Status, Headers, {[ > - {ok, true}, > - {id, DocId}, > - {rev, couch_doc:rev_to_str(UpdatedRev)} > - ]}); > + Headers = case Method of > + 'DELETE' -> > + []; > + _ -> > + [{"Location", absolute_uri(Req, "/" ++ > + ?b2l(Db#db.name) ++ "/" ++ > + ?b2l(DocId) ++ "/" ++ > + ?b2l(FileName) > + )}] > + end, > + update_doc(Req, Db, DocId, DocEdited, Headers); > > db_attachment_req(Req, _Db, _DocId, _FileNameParts) -> > send_method_not_allowed(Req, "DELETE,GET,HEAD,PUT"). > >
nice!
