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, []).