summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Mische <volker.mische@gmail.com>2013-03-10 18:34:59 +0100
committerRobert Newson <rnewson@apache.org>2013-03-10 17:39:16 -0500
commit7648e1537bccd5eae6a8a6697ce2aa4b0fc32c73 (patch)
tree2f8dbb0128c5b3de7dd12cbb71f80c643b8ba38f
parent06c3f351f158f107a8293c7c6c9b2415b942f0e9 (diff)
downloadcouchdb-7648e1537bccd5eae6a8a6697ce2aa4b0fc32c73.tar.gz
Fix CORS error with attachments
When attachments were returned (?attachments=true) while CORS was enabled and used, an error occured. The reason for this error were headers that were encoded as binaries instead of lists. String operations on binaries throw errors. This commit fixes COUCHDB-1689.
-rw-r--r--CHANGES9
-rw-r--r--src/couchdb/couch_httpd_db.erl8
-rw-r--r--test/etap/231-cors.t35
3 files changed, 47 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index bdfda9dfd..19f9d1923 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
Apache CouchDB CHANGES
======================
+Version 1.3.1
+-------------
+
+This version has not been released yet.
+
+HTTP Interface:
+
+* Fix bug in CORS when retrieving attachments.
+
Version 1.3.0
-------------
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 4b345da6c..f270fef1b 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -627,7 +627,7 @@ send_doc_efficiently(#httpd{mochi_req = MochiReq} = Req,
[attachments, follows, att_encoding_info | Options])),
{ContentType, Len} = couch_doc:len_doc_to_multi_part_stream(
Boundary,JsonBytes, Atts, true),
- CType = {<<"Content-Type">>, ContentType},
+ CType = {"Content-Type", ?b2l(ContentType)},
{ok, Resp} = start_response_length(Req, 200, [CType|Headers], Len),
couch_doc:doc_to_multi_part_stream(Boundary,JsonBytes,Atts,
fun(Data) -> couch_httpd:send(Resp, Data) end, true)
@@ -673,7 +673,7 @@ send_ranges_multipart(Req, ContentType, Len, Att, Ranges) ->
{ok, Resp} = start_chunked_response(Req, 206, [CType]),
couch_httpd:send_chunk(Resp, <<"--", Boundary/binary>>),
lists:foreach(fun({From, To}) ->
- ContentRange = make_content_range(From, To, Len),
+ ContentRange = ?l2b(make_content_range(From, To, Len)),
couch_httpd:send_chunk(Resp,
<<"\r\nContent-Type: ", ContentType/binary, "\r\n",
"Content-Range: ", ContentRange/binary, "\r\n",
@@ -697,7 +697,7 @@ receive_request_data(_Req, _) ->
throw(<<"expected more data">>).
make_content_range(From, To, Len) ->
- ?l2b(io_lib:format("bytes ~B-~B/~B", [From, To, Len])).
+ io_lib:format("bytes ~B-~B/~B", [From, To, Len]).
update_doc_result_to_json({{Id, Rev}, Error}) ->
{_Code, Err, Msg} = couch_httpd:error_info(Error),
@@ -894,7 +894,7 @@ db_attachment_req(#httpd{method='GET',mochi_req=MochiReq}=Req, Db, DocId, FileNa
Ranges = parse_ranges(MochiReq:get(range), Len),
case {Enc, Ranges} of
{identity, [{From, To}]} ->
- Headers1 = [{<<"Content-Range">>, make_content_range(From, To, Len)}]
+ Headers1 = [{"Content-Range", make_content_range(From, To, Len)}]
++ Headers,
{ok, Resp} = start_response_length(Req, 206, Headers1, To - From + 1),
couch_doc:range_att_foldl(Att, From, To + 1,
diff --git a/test/etap/231-cors.t b/test/etap/231-cors.t
index ad92ae9a6..a15086760 100644
--- a/test/etap/231-cors.t
+++ b/test/etap/231-cors.t
@@ -32,7 +32,7 @@ server() ->
main(_) ->
test_util:init_code_path(),
- etap:plan(28),
+ etap:plan(30),
case (catch test()) of
ok ->
etap:end_tests();
@@ -85,6 +85,8 @@ test() ->
test_preflight_request(),
test_db_request(),
+ test_doc_with_attachment_request(),
+ test_doc_with_attachment_range_request(),
test_db_preflight_request(),
test_db_origin_request(),
test_db1_origin_request(),
@@ -223,6 +225,37 @@ test_db_request(VHost) ->
etap:is(false, true, "ibrowse failed")
end.
+% COUCHDB-1689
+test_doc_with_attachment_request() ->
+ DocUrl = server() ++ "etap-test-db/doc1",
+ ibrowse:send_req(DocUrl ++ "/attachment.txt",
+ [{"Content-Type", "text/plain"}], put, "this is a text attachment"),
+
+ Headers = [{"Origin", "http://example.com"}],
+ Url = DocUrl ++ "?attachments=true",
+ case ibrowse:send_req(Url, Headers, get, []) of
+ {ok, Code, _RespHeaders, _Body} ->
+ etap:is(Code, "200", "Response without errors");
+ _ ->
+ etap:is(false, true, "ibrowse failed")
+ end.
+
+% COUCHDB-1689
+test_doc_with_attachment_range_request() ->
+ AttachmentUrl = server() ++ "etap-test-db/doc2/attachment.bin",
+ % Use a Content-Type that doesn't get compressed
+ ibrowse:send_req(AttachmentUrl,
+ [{"Content-Type", "application/octet-stream"}], put,
+ "this is an attachment"),
+
+ Headers = [{"Origin", "http://example.com"}, {"Range", "bytes=0-6"}],
+ case ibrowse:send_req(AttachmentUrl, Headers, get, []) of
+ {ok, Code, _RespHeaders, _Body} ->
+ etap:is(Code, "206", "Response without errors");
+ _ ->
+ etap:is(false, true, "ibrowse failed")
+ end.
+
test_db_request_credentials_header_off() ->
Headers = [{"Origin", "http://example.com"}],
Url = server() ++ "etap-test-db",