diff options
author | Volker Mische <volker.mische@gmail.com> | 2013-03-10 18:34:59 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2013-03-10 17:39:16 -0500 |
commit | 7648e1537bccd5eae6a8a6697ce2aa4b0fc32c73 (patch) | |
tree | 2f8dbb0128c5b3de7dd12cbb71f80c643b8ba38f | |
parent | 06c3f351f158f107a8293c7c6c9b2415b942f0e9 (diff) | |
download | couchdb-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-- | CHANGES | 9 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 8 | ||||
-rw-r--r-- | test/etap/231-cors.t | 35 |
3 files changed, 47 insertions, 5 deletions
@@ -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", |