summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjiangphcn <jiangph@cn.ibm.com>2017-12-18 20:52:17 +0800
committerPaul J. Davis <paul.joseph.davis@gmail.com>2018-01-26 10:50:47 -0600
commit52e7cbe659c1125bea52f1ebd025bf092ed391aa (patch)
treeb2dde34f16843e9000e4fce7ce3745dd0f1b61f0
parent4e35b36f5d089f8dd567033f3b1db1cc846c7b14 (diff)
downloadcouchdb-52e7cbe659c1125bea52f1ebd025bf092ed391aa.tar.gz
Decode destination header for doc copy
Fixes #977
-rw-r--r--src/chttpd/src/chttpd_db.erl3
-rw-r--r--src/chttpd/test/chttpd_db_test.erl26
-rw-r--r--src/couch/src/couch_httpd_db.erl3
-rw-r--r--src/couch/src/test_request.erl10
4 files changed, 39 insertions, 3 deletions
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index e621d657a..3dc9f5794 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -851,7 +851,8 @@ db_doc_req(#httpd{method='COPY', user_ctx=Ctx}=Req, Db, SourceDocId) ->
missing_rev -> nil;
Rev -> Rev
end,
- {TargetDocId, TargetRevs} = couch_httpd_db:parse_copy_destination_header(Req),
+ {TargetDocId0, TargetRevs} = couch_httpd_db:parse_copy_destination_header(Req),
+ TargetDocId = list_to_binary(mochiweb_util:unquote(TargetDocId0)),
% open old doc
Doc = couch_doc_open(Db, SourceDocId, SourceRev, []),
% save new doc
diff --git a/src/chttpd/test/chttpd_db_test.erl b/src/chttpd/test/chttpd_db_test.erl
index f6732939c..1725f87a9 100644
--- a/src/chttpd/test/chttpd_db_test.erl
+++ b/src/chttpd/test/chttpd_db_test.erl
@@ -19,6 +19,10 @@
-define(PASS, "pass").
-define(AUTH, {basic_auth, {?USER, ?PASS}}).
-define(CONTENT_JSON, {"Content-Type", "application/json"}).
+-define(DESTHEADER1, {"Destination", "foo%E5%95%8Abar"}).
+-define(DESTHEADER2, {"Destination", "foo%2Fbar%23baz%3Fpow%3Afiz"}).
+
+
-define(FIXTURE_TXT, ?ABS_PATH(?FILE)).
-define(i2l(I), integer_to_list(I)).
@@ -70,7 +74,8 @@ all_test_() ->
fun should_succeed_on_all_docs_with_queries_limit_skip/1,
fun should_succeed_on_all_docs_with_multiple_queries/1,
fun should_succeed_on_design_docs_with_multiple_queries/1,
- fun should_fail_on_multiple_queries_with_keys_and_queries/1
+ fun should_fail_on_multiple_queries_with_keys_and_queries/1,
+ fun should_return_correct_id_on_doc_copy/1
]
}
}
@@ -303,6 +308,25 @@ should_fail_on_multiple_queries_with_keys_and_queries(Url) ->
end).
+should_return_correct_id_on_doc_copy(Url) ->
+ ?_test(begin
+ {ok, _, _, _} = create_doc(Url, "testdoc"),
+ {_, _, _, ResultBody1} = test_request:copy(Url ++ "/testdoc/",
+ [?CONTENT_JSON, ?AUTH, ?DESTHEADER1]),
+ {ResultJson1} = ?JSON_DECODE(ResultBody1),
+ Id1 = couch_util:get_value(<<"id">>, ResultJson1),
+
+ {_, _, _, ResultBody2} = test_request:copy(Url ++ "/testdoc/",
+ [?CONTENT_JSON, ?AUTH, ?DESTHEADER2]),
+ {ResultJson2} = ?JSON_DECODE(ResultBody2),
+ Id2 = couch_util:get_value(<<"id">>, ResultJson2),
+ [
+ ?assertEqual(<<102,111,111,229,149,138,98,97,114>>, Id1),
+ ?assertEqual(<<"foo/bar#baz?pow:fiz">>, Id2)
+ ]
+ end).
+
+
attachment_doc() ->
{ok, Data} = file:read_file(?FIXTURE_TXT),
{[
diff --git a/src/couch/src/couch_httpd_db.erl b/src/couch/src/couch_httpd_db.erl
index 05e63ba97..79ba84dab 100644
--- a/src/couch/src/couch_httpd_db.erl
+++ b/src/couch/src/couch_httpd_db.erl
@@ -616,7 +616,8 @@ db_doc_req(#httpd{method='COPY'}=Req, Db, SourceDocId) ->
missing_rev -> nil;
Rev -> Rev
end,
- {TargetDocId, TargetRevs} = parse_copy_destination_header(Req),
+ {TargetDocId0, TargetRevs} = parse_copy_destination_header(Req),
+ TargetDocId = list_to_binary(mochiweb_util:unquote(TargetDocId0)),
% open old doc
Doc = couch_doc_open(Db, SourceDocId, SourceRev, []),
% save new doc
diff --git a/src/couch/src/test_request.erl b/src/couch/src/test_request.erl
index a1b8b57c5..4dfde1a33 100644
--- a/src/couch/src/test_request.erl
+++ b/src/couch/src/test_request.erl
@@ -12,6 +12,7 @@
-module(test_request).
+-export([copy/1, copy/2, copy/3]).
-export([get/1, get/2, get/3]).
-export([post/2, post/3, post/4]).
-export([put/2, put/3, put/4]).
@@ -19,6 +20,15 @@
-export([options/1, options/2, options/3]).
-export([request/3, request/4, request/5]).
+copy(Url) ->
+ copy(Url, []).
+
+copy(Url, Headers) ->
+ copy(Url, Headers, []).
+
+copy(Url, Headers, Opts) ->
+ request(copy, Url, Headers, [], Opts).
+
get(Url) ->
get(Url, []).