summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/couch/THANKS1
-rw-r--r--apps/couch/src/couch_httpd_show.erl16
-rw-r--r--apps/couch/src/couch_rep_changes_feed.erl25
-rw-r--r--apps/couch/src/test_util.erl28
-rw-r--r--rel/overlay/share/www/script/test/update_documents.js24
-rwxr-xr-xtest/etap/072-cleanup.t8
6 files changed, 83 insertions, 19 deletions
diff --git a/apps/couch/THANKS b/apps/couch/THANKS
index 76a0c19b..470c3937 100644
--- a/apps/couch/THANKS
+++ b/apps/couch/THANKS
@@ -82,5 +82,6 @@ suggesting improvements or submitting changes. Some of these people are:
* Caolan McMahon <caolan.mcmahon@googlemail.com>
* Alexander Shorin <kxepal@gmail.com>
* Christopher Bonhage <queezey@me.com>
+ * Christian Carter <cdcarter@gmail.com>
For a list of authors see the `AUTHORS` file.
diff --git a/apps/couch/src/couch_httpd_show.erl b/apps/couch/src/couch_httpd_show.erl
index 742b0f20..58f046e4 100644
--- a/apps/couch/src/couch_httpd_show.erl
+++ b/apps/couch/src/couch_httpd_show.erl
@@ -127,7 +127,7 @@ handle_doc_update_req(Req, _Db, _DDoc) ->
send_doc_update_response(Req, Db, DDoc, UpdateName, Doc, DocId) ->
JsonReq = couch_httpd_external:json_req_obj(Req, Db, DocId),
JsonDoc = couch_query_servers:json_doc(Doc),
- {Code, JsonResp1} = case couch_query_servers:ddoc_prompt(DDoc,
+ JsonResp1 = case couch_query_servers:ddoc_prompt(DDoc,
[<<"updates">>, UpdateName], [JsonDoc, JsonReq]) of
[<<"up">>, {NewJsonDoc}, {JsonResp}] ->
Options = case couch_httpd:header_value(Req, "X-Couch-Full-Commit",
@@ -140,16 +140,14 @@ send_doc_update_response(Req, Db, DDoc, UpdateName, Doc, DocId) ->
NewDoc = couch_doc:from_json_obj({NewJsonDoc}),
{ok, NewRev} = couch_db:update_doc(Db, NewDoc, Options),
NewRevStr = couch_doc:rev_to_str(NewRev),
- JsonRespWithRev = {[{<<"headers">>,
- {[{<<"X-Couch-Update-NewRev">>, NewRevStr}]}} | JsonResp]},
- {201, JsonRespWithRev};
- [<<"up">>, _Other, JsonResp] ->
- {200, JsonResp}
+ {[{<<"code">>, 201}, {<<"headers">>,
+ {[{<<"X-Couch-Update-NewRev">>, NewRevStr}]}} | JsonResp]};
+ [<<"up">>, _Other, {JsonResp}] ->
+ {[{<<"code">>, 200} | JsonResp]}
end,
-
- JsonResp2 = couch_util:json_apply_field({<<"code">>, Code}, JsonResp1),
+
% todo set location field
- couch_httpd_external:send_external_response(Req, JsonResp2).
+ couch_httpd_external:send_external_response(Req, JsonResp1).
% view-list request with view and list from same design doc.
diff --git a/apps/couch/src/couch_rep_changes_feed.erl b/apps/couch/src/couch_rep_changes_feed.erl
index 49edf7cc..7a9573d6 100644
--- a/apps/couch/src/couch_rep_changes_feed.erl
+++ b/apps/couch/src/couch_rep_changes_feed.erl
@@ -491,13 +491,30 @@ purge_req_messages(ReqId) ->
ok
end.
-queue_changes_row(Row, #state{doc_ids = nil, count = Count, rows = Rows}) ->
- {queue:in(Row, Rows), Count + 1};
+queue_changes_row(Row, #state{doc_ids = nil} = State) ->
+ maybe_queue_row(Row, State);
queue_changes_row({RowProps} = Row,
- #state{doc_ids = Ids, count = Count, rows = Rows}) ->
+ #state{doc_ids = Ids, count = Count, rows = Rows} = State) ->
case lists:member(get_value(<<"id">>, RowProps), Ids) of
true ->
- {queue:in(Row, Rows), Count + 1};
+ maybe_queue_row(Row, State);
false ->
{Rows, Count}
end.
+
+maybe_queue_row({Props} = Row, #state{count = Count, rows = Rows} = State) ->
+ case get_value(<<"id">>, Props) of
+ <<>> ->
+ [_, Db | _] = State#state.init_args,
+ ?LOG_ERROR("Replicator: ignoring document with empty ID in source "
+ "database `~s` (_changes sequence ~p)",
+ [dbname(Db), couch_util:get_value(<<"seq">>, Props)]),
+ {Rows, Count};
+ _ ->
+ {queue:in(Row, Rows), Count + 1}
+ end.
+
+dbname(#http_db{url = Url}) ->
+ couch_util:url_strip_password(Url);
+dbname(#db{name = Name}) ->
+ Name.
diff --git a/apps/couch/src/test_util.erl b/apps/couch/src/test_util.erl
index 55b95139..f086bf94 100644
--- a/apps/couch/src/test_util.erl
+++ b/apps/couch/src/test_util.erl
@@ -14,6 +14,7 @@
-export([init_code_path/0]).
-export([source_file/1, build_file/1, config_files/0]).
+-export([request/3, request/4]).
init_code_path() ->
code:load_abs("apps/couch/test/etap/etap").
@@ -31,3 +32,30 @@ config_files() ->
source_file("test/etap/random_port.ini")
].
+request(Url, Headers, Method) ->
+ request(Url, Headers, Method, []).
+
+request(Url, Headers, Method, Body) ->
+ request(Url, Headers, Method, Body, 3).
+
+request(_Url, _Headers, _Method, _Body, 0) ->
+ {error, request_failed};
+request(Url, Headers, Method, Body, N) ->
+ case code:is_loaded(ibrowse) of
+ false ->
+ {ok, _} = ibrowse:start();
+ _ ->
+ ok
+ end,
+ case ibrowse:send_req(Url, Headers, Method, Body) of
+ {ok, Code0, RespHeaders, RespBody0} ->
+ Code = list_to_integer(Code0),
+ RespBody = iolist_to_binary(RespBody0),
+ {ok, Code, RespHeaders, RespBody};
+ {error, {'EXIT', {normal, _}}} ->
+ % Connection closed right after a successful request that
+ % used the same connection.
+ request(Url, Headers, Method, Body, N - 1);
+ Error ->
+ Error
+ end.
diff --git a/rel/overlay/share/www/script/test/update_documents.js b/rel/overlay/share/www/script/test/update_documents.js
index 4d2b29fc..59af4597 100644
--- a/rel/overlay/share/www/script/test/update_documents.js
+++ b/rel/overlay/share/www/script/test/update_documents.js
@@ -75,6 +75,17 @@ couchTests.update_documents = function(debug) {
}),
"get-uuid" : stringFun(function(doc, req) {
return [null, req.uuid];
+ }),
+ "code-n-bump" : stringFun(function(doc,req) {
+ if (!doc.counter) doc.counter = 0;
+ doc.counter += 1;
+ var message = "<h1>bumped it!</h1>";
+ resp = {"code": 302, "body": message}
+ return [doc, resp];
+ }),
+ "resp-code" : stringFun(function(doc,req) {
+ resp = {"code": 302}
+ return [null, resp];
})
}
};
@@ -179,4 +190,17 @@ couchTests.update_documents = function(debug) {
var doc = db.open("with/slash");
TEquals(2, doc.counter, "counter should be 2");
+
+ // COUCHDB-648 - the code in the JSON response should be honored
+
+ xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/code-n-bump/"+docid, {
+ headers : {"X-Couch-Full-Commit":"true"}
+ });
+ T(xhr.status == 302);
+ T(xhr.responseText == "<h1>bumped it!</h1>");
+ doc = db.open(docid);
+ T(doc.counter == 3);
+
+ xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/resp-code/");
+ T(xhr.status == 302);
};
diff --git a/test/etap/072-cleanup.t b/test/etap/072-cleanup.t
index 61790bc6..6f97193d 100755
--- a/test/etap/072-cleanup.t
+++ b/test/etap/072-cleanup.t
@@ -41,7 +41,6 @@ main(_) ->
test() ->
{ok, _} = couch_server_sup:start_link(test_util:config_files()),
- ok = application:start(inets),
couch_server:delete(?TEST_DB, []),
timer:sleep(1000),
@@ -110,11 +109,8 @@ db_url() ->
binary_to_list(?TEST_DB).
query_view(DDoc, View) ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- get,
- {db_url() ++ "/_design/" ++ DDoc ++ "/_view/" ++ View, []},
- [],
- [{sync, true}]),
+ {ok, Code, _Headers, _Body} = test_util:request(
+ db_url() ++ "/_design/" ++ DDoc ++ "/_view/" ++ View, [], get),
etap:is(Code, 200, "Built view index for " ++ DDoc ++ "."),
ok.