Use chttpd provided functions
couch_mrview_show's usage of couch_chttp:send_external_response
brakes CORS support. Since couch_httpd's version of send_external_response
doesn't have support for CORS compared to chttpd's version.
Other couch_http's functions are switched to corresponding chttpd's
versions as well.
COUCHDB-2656
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index 99a6c2d..ccc8dc1 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -45,35 +45,35 @@
handle_all_docs_req(#httpd{method='GET'}=Req, Db) ->
all_docs_req(Req, Db, undefined);
handle_all_docs_req(#httpd{method='POST'}=Req, Db) ->
- Keys = couch_mrview_util:get_view_keys(couch_httpd:json_body_obj(Req)),
+ Keys = couch_mrview_util:get_view_keys(chttpd:json_body_obj(Req)),
all_docs_req(Req, Db, Keys);
handle_all_docs_req(Req, _Db) ->
- couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
+ chttpd:send_method_not_allowed(Req, "GET,POST,HEAD").
handle_local_docs_req(#httpd{method='GET'}=Req, Db) ->
all_docs_req(Req, Db, undefined, <<"_local">>);
handle_local_docs_req(#httpd{method='POST'}=Req, Db) ->
- Keys = couch_mrview_util:get_view_keys(couch_httpd:json_body_obj(Req)),
+ Keys = couch_mrview_util:get_view_keys(chttpd:json_body_obj(Req)),
all_docs_req(Req, Db, Keys, <<"_local">>);
handle_local_docs_req(Req, _Db) ->
- couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
+ chttpd:send_method_not_allowed(Req, "GET,POST,HEAD").
handle_design_docs_req(#httpd{method='GET'}=Req, Db) ->
all_docs_req(Req, Db, undefined, <<"_design">>);
handle_design_docs_req(#httpd{method='POST'}=Req, Db) ->
- Keys = couch_mrview_util:get_view_keys(couch_httpd:json_body_obj(Req)),
+ Keys = couch_mrview_util:get_view_keys(chttpd:json_body_obj(Req)),
all_docs_req(Req, Db, Keys, <<"_design">>);
handle_design_docs_req(Req, _Db) ->
- couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
+ chttpd:send_method_not_allowed(Req, "GET,POST,HEAD").
handle_reindex_req(#httpd{method='POST',
path_parts=[_, _, DName,<<"_reindex">>]}=Req,
Db, _DDoc) ->
ok = couch_db:check_is_admin(Db),
couch_mrview:trigger_update(Db, <<"_design/", DName/binary>>),
- couch_httpd:send_json(Req, 201, {[{<<"ok">>, true}]});
+ chttpd:send_json(Req, 201, {[{<<"ok">>, true}]});
handle_reindex_req(Req, _Db, _DDoc) ->
- couch_httpd:send_method_not_allowed(Req, "POST").
+ chttpd:send_method_not_allowed(Req, "POST").
handle_view_changes_req(#httpd{path_parts=[_,<<"_design">>,DDocName,<<"_view_changes">>,ViewName]}=Req, Db, DDoc) ->
@@ -105,14 +105,14 @@
FinalInfo = [{db_name, Db#db.name},
{ddoc, DDocId},
{view, VName}] ++ Info,
- couch_httpd:send_json(Req, 200, {FinalInfo});
+ chttpd:send_json(Req, 200, {FinalInfo});
handle_view_req(#httpd{method='GET'}=Req, Db, DDoc) ->
[_, _, _, _, ViewName] = Req#httpd.path_parts,
couch_stats:increment_counter([couchdb, httpd, view_reads]),
design_doc_view(Req, Db, DDoc, ViewName, undefined);
handle_view_req(#httpd{method='POST'}=Req, Db, DDoc) ->
[_, _, _, _, ViewName] = Req#httpd.path_parts,
- Props = couch_httpd:json_body_obj(Req),
+ Props = chttpd:json_body_obj(Req),
Keys = couch_mrview_util:get_view_keys(Props),
Queries = couch_mrview_util:get_view_queries(Props),
case {Queries, Keys} of
@@ -132,48 +132,48 @@
throw({bad_request, "`keys` and `queries` are mutually exclusive"})
end;
handle_view_req(Req, _Db, _DDoc) ->
- couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
+ chttpd:send_method_not_allowed(Req, "GET,POST,HEAD").
handle_temp_view_req(#httpd{method='POST'}=Req, Db) ->
couch_httpd:validate_ctype(Req, "application/json"),
ok = couch_db:check_is_admin(Db),
- {Body} = couch_httpd:json_body_obj(Req),
+ {Body} = chttpd:json_body_obj(Req),
DDoc = couch_mrview_util:temp_view_to_ddoc({Body}),
Keys = couch_mrview_util:get_view_keys({Body}),
couch_stats:increment_counter([couchdb, httpd, temporary_view_reads]),
design_doc_view(Req, Db, DDoc, <<"temp">>, Keys);
handle_temp_view_req(Req, _Db) ->
- couch_httpd:send_method_not_allowed(Req, "POST").
+ chttpd:send_method_not_allowed(Req, "POST").
handle_info_req(#httpd{method='GET'}=Req, Db, DDoc) ->
[_, _, Name, _] = Req#httpd.path_parts,
{ok, Info} = couch_mrview:get_info(Db, DDoc),
- couch_httpd:send_json(Req, 200, {[
+ chttpd:send_json(Req, 200, {[
{name, Name},
{view_index, {Info}}
]});
handle_info_req(Req, _Db, _DDoc) ->
- couch_httpd:send_method_not_allowed(Req, "GET").
+ chttpd:send_method_not_allowed(Req, "GET").
handle_compact_req(#httpd{method='POST'}=Req, Db, DDoc) ->
ok = couch_db:check_is_admin(Db),
couch_httpd:validate_ctype(Req, "application/json"),
ok = couch_mrview:compact(Db, DDoc),
- couch_httpd:send_json(Req, 202, {[{ok, true}]});
+ chttpd:send_json(Req, 202, {[{ok, true}]});
handle_compact_req(Req, _Db, _DDoc) ->
- couch_httpd:send_method_not_allowed(Req, "POST").
+ chttpd:send_method_not_allowed(Req, "POST").
handle_cleanup_req(#httpd{method='POST'}=Req, Db) ->
ok = couch_db:check_is_admin(Db),
couch_httpd:validate_ctype(Req, "application/json"),
ok = couch_mrview:cleanup(Db),
- couch_httpd:send_json(Req, 202, {[{ok, true}]});
+ chttpd:send_json(Req, 202, {[{ok, true}]});
handle_cleanup_req(Req, _Db) ->
- couch_httpd:send_method_not_allowed(Req, "POST").
+ chttpd:send_method_not_allowed(Req, "POST").
all_docs_req(Req, Db, Keys) ->
@@ -411,7 +411,7 @@
parse_params(#httpd{}=Req, Keys) ->
- parse_params(couch_httpd:qs(Req), Keys);
+ parse_params(chttpd:qs(Req), Keys);
parse_params(Props, Keys) ->
Args = #mrargs{},
parse_params(Props, Keys, Args).
@@ -548,8 +548,8 @@
check_view_etag(Sig, Acc0, Req) ->
- ETag = couch_httpd:make_etag(Sig),
- case couch_httpd:etag_match(Req, ETag) of
+ ETag = chttpd:make_etag(Sig),
+ case chttpd:etag_match(Req, ETag) of
true -> throw({etag_match, ETag});
false -> {ok, Acc0#vacc{etag=ETag}}
end.
diff --git a/src/couch_mrview_show.erl b/src/couch_mrview_show.erl
index fecfd3b..1d67bc9 100644
--- a/src/couch_mrview_show.erl
+++ b/src/couch_mrview_show.erl
@@ -65,7 +65,7 @@
handle_doc_show(Req, Db, DDoc, ShowName, nil);
handle_doc_show_req(Req, _Db, _DDoc) ->
- couch_httpd:send_error(Req, 404, <<"show_error">>, <<"Invalid path.">>).
+ chttpd:send_error(Req, 404, <<"show_error">>, <<"Invalid path.">>).
handle_doc_show(Req, Db, DDoc, ShowName, Doc) ->
handle_doc_show(Req, Db, DDoc, ShowName, Doc, null).
@@ -73,24 +73,24 @@
handle_doc_show(Req, Db, DDoc, ShowName, Doc, DocId) ->
% get responder for ddoc/showname
CurrentEtag = show_etag(Req, Doc, DDoc, []),
- couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
- JsonReq = couch_httpd_external:json_req_obj(Req, Db, DocId),
+ chttpd:etag_respond(Req, CurrentEtag, fun() ->
+ JsonReq = chttpd_external:json_req_obj(Req, Db, DocId),
JsonDoc = couch_query_servers:json_doc(Doc),
[<<"resp">>, ExternalResp] =
couch_query_servers:ddoc_prompt(DDoc, [<<"shows">>, ShowName],
[JsonDoc, JsonReq]),
JsonResp = apply_etag(ExternalResp, CurrentEtag),
- couch_httpd_external:send_external_response(Req, JsonResp)
+ chttpd_external:send_external_response(Req, JsonResp)
end).
show_etag(#httpd{user_ctx=UserCtx}=Req, Doc, DDoc, More) ->
- Accept = couch_httpd:header_value(Req, "Accept"),
+ Accept = chttpd:header_value(Req, "Accept"),
DocPart = case Doc of
nil -> nil;
- Doc -> couch_httpd:doc_etag(Doc)
+ Doc -> chttpd:doc_etag(Doc)
end,
- couch_httpd:make_etag({couch_httpd:doc_etag(DDoc), DocPart, Accept,
+ chttpd:make_etag({chttpd:doc_etag(DDoc), DocPart, Accept,
{UserCtx#user_ctx.name, UserCtx#user_ctx.roles}, More}).
% updates a doc based on a request
@@ -116,16 +116,16 @@
handle_doc_update_req(Req, _Db, _DDoc) ->
- couch_httpd:send_error(Req, 404, <<"update_error">>, <<"Invalid path.">>).
+ chttpd:send_error(Req, 404, <<"update_error">>, <<"Invalid path.">>).
send_doc_update_response(Req, Db, DDoc, UpdateName, Doc, DocId) ->
- JsonReq = couch_httpd_external:json_req_obj(Req, Db, DocId),
+ JsonReq = chttpd_external:json_req_obj(Req, Db, DocId),
JsonDoc = couch_query_servers:json_doc(Doc),
Cmd = [<<"updates">>, UpdateName],
UpdateResp = couch_query_servers:ddoc_prompt(DDoc, Cmd, [JsonDoc, JsonReq]),
JsonResp = case UpdateResp of
[<<"up">>, {NewJsonDoc}, {JsonResp0}] ->
- case couch_httpd:header_value(
+ case chttpd:header_value(
Req, "X-Couch-Full-Commit", "false") of
"true" ->
Options = [full_commit, {user_ctx, Req#httpd.user_ctx}];
@@ -147,7 +147,7 @@
{[{<<"code">>, 200} | JsonResp0]}
end,
% todo set location field
- couch_httpd_external:send_external_response(Req, JsonResp).
+ chttpd_external:send_external_response(Req, JsonResp).
handle_view_list_req(#httpd{method=Method}=Req, Db, DDoc)
@@ -162,10 +162,10 @@
{ok, VDDoc} = couch_db:open_doc(Db, VDocId, [ejson_body]),
handle_view_list(Req, Db, DDoc, LName, VDDoc, VName, undefined);
_ ->
- couch_httpd:send_error(Req, 404, <<"list_error">>, <<"Bad path.">>)
+ chttpd:send_error(Req, 404, <<"list_error">>, <<"Bad path.">>)
end;
handle_view_list_req(#httpd{method='POST'}=Req, Db, DDoc) ->
- {Props} = couch_httpd:json_body_obj(Req),
+ {Props} = chttpd:json_body_obj(Req),
Keys = proplists:get_value(<<"keys">>, Props),
case Req#httpd.path_parts of
[_, _, _DName, _, LName, VName] ->
@@ -176,10 +176,10 @@
{ok, VDDoc} = couch_db:open_doc(Db, VDocId, [ejson_body]),
handle_view_list(Req, Db, DDoc, LName, VDDoc, VName, Keys);
_ ->
- couch_httpd:send_error(Req, 404, <<"list_error">>, <<"Bad path.">>)
+ chttpd:send_error(Req, 404, <<"list_error">>, <<"Bad path.">>)
end;
handle_view_list_req(Req, _Db, _DDoc) ->
- couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
+ chttpd:send_method_not_allowed(Req, "GET,POST,HEAD").
handle_view_list(Req, Db, DDoc, LName, VDDoc, VName, Keys) ->
@@ -188,10 +188,10 @@
UserCtx = Req#httpd.user_ctx,
Name = UserCtx#user_ctx.name,
Roles = UserCtx#user_ctx.roles,
- Accept = couch_httpd:header_value(Req, "Accept"),
- Parts = {couch_httpd:doc_etag(DDoc), Accept, {Name, Roles}},
- ETag = couch_httpd:make_etag({BaseSig, Parts}),
- case couch_httpd:etag_match(Req, ETag) of
+ Accept = chttpd:header_value(Req, "Accept"),
+ Parts = {chttpd:doc_etag(DDoc), Accept, {Name, Roles}},
+ ETag = chttpd:make_etag({BaseSig, Parts}),
+ case chttpd:etag_match(Req, ETag) of
true -> throw({etag_match, ETag});
false -> {ok, Acc0#lacc{etag=ETag}}
end
@@ -241,7 +241,7 @@
[<<"end">>, Data] ->
#lacc{resp = Resp2} = send_non_empty_chunk(Acc#lacc{resp=Resp}, Data)
end,
- couch_httpd:last_chunk(Resp2),
+ last_chunk(Resp2),
{ok, Resp2}.
start_list_resp(Head, Acc) ->
@@ -259,8 +259,8 @@
code = Code,
ctype = CType,
headers = ExtHeaders
- } = couch_httpd_external:parse_external_response(Headers2),
- Headers3 = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
+ } = chttpd_external:parse_external_response(Headers2),
+ Headers3 = chttpd_external:default_or_content_type(CType, ExtHeaders),
Acc#lacc{code=Code, headers=Headers3}.
send_list_row(Row, #lacc{qserver = {Proc, _}, resp = Resp} = Acc) ->
@@ -287,23 +287,23 @@
[<<"end">>, Chunk, Headers] ->
Acc2 = send_non_empty_chunk(fixup_headers(Headers, Acc), Chunk),
#lacc{resp = Resp2} = Acc2,
- couch_httpd:last_chunk(Resp2),
+ last_chunk(Resp2),
{stop, Acc2};
[<<"end">>, Chunk] ->
Acc2 = send_non_empty_chunk(Acc, Chunk),
#lacc{resp = Resp2} = Acc2,
- couch_httpd:last_chunk(Resp2),
+ last_chunk(Resp2),
{stop, Acc2}
catch Error ->
case Resp of
undefined ->
- {Code, _, _} = couch_httpd:error_info(Error),
+ {Code, _, _} = chttpd:error_info(Error),
#lacc{req=Req, headers=Headers} = Acc,
- {ok, Resp2} = couch_httpd:start_chunked_response(Req, Code, Headers),
+ {ok, Resp2} = chttpd:start_chunked_response(Req, Code, Headers),
Acc2 = Acc#lacc{resp=Resp2, code=Code};
_ -> Resp2 = Resp, Acc2 = Acc
end,
- couch_httpd:send_chunked_error(Resp2, Error),
+ chttpd:send_chunked_error(Resp2, Error),
{stop, Acc2}
end.
@@ -311,10 +311,10 @@
Acc;
send_non_empty_chunk(#lacc{resp=undefined} = Acc, Chunk) ->
#lacc{req=Req, code=Code, headers=Headers} = Acc,
- {ok, Resp} = couch_httpd:start_chunked_response(Req, Code, Headers),
+ {ok, Resp} = chttpd:start_chunked_response(Req, Code, Headers),
send_non_empty_chunk(Acc#lacc{resp = Resp}, Chunk);
send_non_empty_chunk(#lacc{resp=Resp} = Acc, Chunk) ->
- couch_httpd:send_chunk(Resp, Chunk),
+ chttpd:send_chunk(Resp, Chunk),
Acc.
@@ -360,9 +360,12 @@
% This loads the db info if we have a fully loaded db record, but we might not
% have the db locally on this node, so then load the info through fabric.
json_req_obj(Req, #db{main_pid=Pid}=Db) when is_pid(Pid) ->
- couch_httpd_external:json_req_obj(Req, Db);
+ chttpd_external:json_req_obj(Req, Db);
json_req_obj(Req, Db) ->
% use a separate process because we're already in a receive loop, and
% json_req_obj calls fabric:get_db_info()
spawn_monitor(fun() -> exit(chttpd_external:json_req_obj(Req, Db)) end),
receive {'DOWN', _, _, _, JsonReq} -> JsonReq end.
+
+last_chunk(Resp) ->
+ chttpd:send_chunk(Resp, []).