From c3e08db6c5abc021481cfff1365dbde283de5b1b Mon Sep 17 00:00:00 2001 From: benoitc Date: Wed, 4 May 2011 08:56:44 +0200 Subject: [PATCH] Revert "use ejson NIF module to speed encoding/decoding json and remove mochiweb" This reverts commit 42b5e59c6799120bc33abdd2799838a990cb50f8. Needed to keep RB013 support. This patch will be reintroduced in next release after freezing current version. Next version of couchbeam will only be compatible with erlang R13B04. --- NOTICE | 28 ----- rebar.config | 2 +- src/couchbeam.erl | 34 +++--- src/couchbeam_attachments.erl | 2 +- src/couchbeam_changes.erl | 6 +- src/couchbeam_mime.erl | 74 ------------ src/couchbeam_util.erl | 210 ++++------------------------------ src/couchbeam_view.erl | 10 +- 8 files changed, 48 insertions(+), 318 deletions(-) delete mode 100644 src/couchbeam_mime.erl diff --git a/NOTICE b/NOTICE index 9d5bfbc6..b4f78adc 100644 --- a/NOTICE +++ b/NOTICE @@ -9,31 +9,3 @@ couchbeam is released under the MIT license. See the LICENSE file for the comple couchbeam:couchbeam_deps ------------------------ Copyright 2007-2008 Basho Technologies - -couchbeam_util, couchbeam_mime ------------------------------- - -parse_qs, quote_pluys, urldecode, urlsplit function have been taken from -Mochiweb project under MIT license. - -Copyright (c) 2007 Mochi Media, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/rebar.config b/rebar.config index e3fda122..8247116a 100644 --- a/rebar.config +++ b/rebar.config @@ -6,7 +6,7 @@ {deps, [ %% mochiweb for JSON and header parsing - {ejson, ".*", {git,"http://github.com/benoitc/ejson.git","master"}}, + {mochiweb, ".*", {git,"http://github.com/mochi/mochiweb.git","master"}}, %% erlang-oauth for oauth authentification {oauth, ".*", {git,"http://github.com/benoitc/erlang-oauth.git","master"}}, diff --git a/src/couchbeam.erl b/src/couchbeam.erl index 3ccdde3e..bac5c764 100644 --- a/src/couchbeam.erl +++ b/src/couchbeam.erl @@ -177,7 +177,7 @@ server_info(#server{options=IbrowseOpts}=Server) -> Url = binary_to_list(iolist_to_binary(server_url(Server))), case request(get, Url, ["200"], IbrowseOpts) of {ok, _Status, _Headers, Body} -> - Version = ejson:decode(Body), + Version = couchbeam_util:json_decode(Body), {ok, Version}; Error -> Error end. @@ -208,7 +208,7 @@ get_uuids(Server, Count) -> replicate(#server{options=IbrowseOpts}=Server, RepObj) -> Url = make_url(Server, "_replicate", []), Headers = [{"Content-Type", "application/json"}], - JsonObj = ejson:encode(RepObj), + JsonObj = couchbeam_util:json_encode(RepObj), case request_stream({self(), once}, post, Url, IbrowseOpts, Headers, JsonObj) of @@ -246,7 +246,7 @@ all_dbs(#server{options=IbrowseOpts}=Server) -> Url = make_url(Server, "_all_dbs", []), case request(get, Url, ["200"], IbrowseOpts) of {ok, _, _, Body} -> - AllDbs = ejson:decode(Body), + AllDbs = couchbeam_util:json_decode(Body), {ok, AllDbs}; Error -> Error @@ -345,7 +345,7 @@ delete_db(#server{options=IbrowseOpts}=Server, DbName) -> Url = make_url(Server, dbname(DbName), []), case request(delete, Url, ["200"], IbrowseOpts) of {ok, _, _, Body} -> - {ok, ejson:decode(Body)}; + {ok, couchbeam_util:json_decode(Body)}; Error -> Error end. @@ -356,7 +356,7 @@ db_info(#db{server=Server, name=DbName, options=IbrowseOpts}) -> Url = make_url(Server, DbName, []), case request(get, Url, ["200"], IbrowseOpts) of {ok, _Status, _Headers, Body} -> - Infos = ejson:decode(Body), + Infos = couchbeam_util:json_decode(Body), {ok, Infos}; {error, {ok, "404", _, _}} -> {error, db_not_found}; @@ -388,7 +388,7 @@ open_doc(#db{server=Server, options=IbrowseOpts}=Db, DocId, Params) -> Url = make_url(Server, doc_url(Db, DocId1), Params), case db_request(get, Url, ["200", "201"], IbrowseOpts) of {ok, _, _, Body} -> - {ok, ejson:decode(Body)}; + {ok, couchbeam_util:json_decode(Body)}; Error -> Error end. @@ -421,11 +421,11 @@ save_doc(#db{server=Server, options=IbrowseOpts}=Db, {Props}=Doc, Options) -> couchbeam_util:encode_docid(DocId1) end, Url = make_url(Server, doc_url(Db, DocId), Options), - Body = ejson:encode(Doc), + Body = couchbeam_util:json_encode(Doc), Headers = [{"Content-Type", "application/json"}], case db_request(put, Url, ["201", "202"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {JsonProp} = ejson:decode(RespBody), + {JsonProp} = couchbeam_util:json_decode(RespBody), NewRev = couchbeam_util:get_value(<<"rev">>, JsonProp), NewDocId = couchbeam_util:get_value(<<"id">>, JsonProp), Doc1 = couchbeam_doc:set_value(<<"_rev">>, NewRev, @@ -491,21 +491,21 @@ save_docs(#db{server=Server, options=IbrowseOpts}=Db, Docs, Options) -> {Options2, Body} = case couchbeam_util:get_value("all_or_nothing", Options1, false) of true -> - Body1 = ejson:encode({[ + Body1 = couchbeam_util:json_encode({[ {<<"all_or_nothing">>, true}, {<<"docs">>, Docs1} ]}), {proplists:delete("all_or_nothing", Options1), Body1}; _ -> - Body1 = ejson:encode({[{<<"docs">>, Docs1}]}), + Body1 = couchbeam_util:json_encode({[{<<"docs">>, Docs1}]}), {Options1, Body1} end, Url = make_url(Server, [db_url(Db), "/", "_bulk_docs"], Options2), Headers = [{"Content-Type", "application/json"}], case db_request(post, Url, ["201"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {ok, ejson:decode(RespBody)}; + {ok, couchbeam_util:json_decode(RespBody)}; Error -> Error end. @@ -624,7 +624,7 @@ put_attachment(#db{server=Server, options=IbrowseOpts}=Db, DocId, Name, Body, Op case db_request(put, Url, ["201"], IbrowseOpts, FinalHeaders, Body) of {ok, _, _, RespBody} -> - {[{<<"ok">>, true}|R]} = ejson:decode(RespBody), + {[{<<"ok">>, true}|R]} = couchbeam_util:json_decode(RespBody), {ok, {R}}; Error -> Error @@ -661,7 +661,7 @@ delete_attachment(#db{server=Server, options=IbrowseOpts}=Db, DocOrDocId, Name, Url = make_url(Server, [db_url(Db), "/", DocId, "/", Name], Options2), case db_request(delete, Url, ["200"], IbrowseOpts) of {ok, _, _, RespBody} -> - {[{<<"ok">>,true}|R]} = ejson:decode(RespBody), + {[{<<"ok">>,true}|R]} = couchbeam_util:json_decode(RespBody), {ok, {R}}; Error -> @@ -738,7 +738,7 @@ view(#db{server=Server}=Db, ViewName, Options) -> undefined -> {get, Options1, []}; Keys -> - Body1 = ejson:encode({[{<<"keys">>, Keys}]}), + Body1 = couchbeam_util:json_encode({[{<<"keys">>, Keys}]}), {post, proplists:delete("keys", Options1), Body1} end, Headers = case Method of @@ -771,7 +771,7 @@ ensure_full_commit(#db{server=Server, options=IbrowseOpts}=Db, Options) -> Headers = [{"Content-Type", "application/json"}], case db_request(post, Url, ["201"], IbrowseOpts, Headers) of {ok, _, _, Body} -> - {[{<<"ok">>, true}|R]} = ejson:decode(Body), + {[{<<"ok">>, true}|R]} = couchbeam_util:json_decode(Body), {ok, R}; Error -> Error @@ -922,7 +922,7 @@ make_url(Server=#server{prefix=Prefix}, Path, Query) -> [server_url(Server), Prefix, "/", Path, - [ ["?", couchbeam_util:urlencode(Query1)] || Query1 =/= [] ] + [ ["?", mochiweb_util:urlencode(Query1)] || Query1 =/= [] ] ])). db_request(Method, Url, Expect, Options) -> @@ -1053,7 +1053,7 @@ get_new_uuids(Server=#server{host=Host, port=Port, options=IbrowseOptions}) -> Url = make_url(Server, "_uuids", [{"count", "1000"}]), case request(get, Url, ["200"], IbrowseOptions) of {ok, _Status, _Headers, Body} -> - {[{<<"uuids">>, Uuids}]} = ejson:decode(Body), + {[{<<"uuids">>, Uuids}]} = couchbeam_util:json_decode(Body), ServerUuids = #server_uuids{host_port={Host, Port}, uuids=Uuids}, ets:insert(couchbeam_uuids, ServerUuids), diff --git a/src/couchbeam_attachments.erl b/src/couchbeam_attachments.erl index 30cae221..bb349448 100644 --- a/src/couchbeam_attachments.erl +++ b/src/couchbeam_attachments.erl @@ -74,7 +74,7 @@ attachment_acceptor(Pid, PidRef, Timeout, IbrowseRef) -> %% AName::string()) -> json_obj() %% @doc add attachment to a doc and encode it. Give possibility to send attachments inline. add_inline(Doc, Content, AName) -> - ContentType = couchbeam_util:guess_mime(AName), + ContentType = mochiweb_util:guess_mime(AName), add_inline(Doc, Content, AName, ContentType). %% @spec add_inline(Doc::json_obj(), Content::attachment_content(), diff --git a/src/couchbeam_changes.erl b/src/couchbeam_changes.erl index 2c77ef5c..a146f187 100644 --- a/src/couchbeam_changes.erl +++ b/src/couchbeam_changes.erl @@ -22,9 +22,9 @@ wait_for_change(Reqid, ReqStatus, Acc) -> Change = iolist_to_binary(lists:reverse(Acc)), try if ReqStatus >= 400 -> - {error, {ReqStatus, ejson:decode(Change)}}; + {error, {ReqStatus, couchbeam_util:json_decode(Change)}}; true -> - {ok, ejson:decode(Change)} + {ok, couchbeam_util:json_decode(Change)} end catch throw:{invalid_json, Error} -> @@ -106,7 +106,7 @@ handle_messages([Chunk|Rest], Pid, PidRef, IbrowseRef, State) -> decode_row(<<",", Rest/binary>>) -> decode_row(Rest); decode_row(Row) -> - ejson:decode(Row). + couchbeam_util:json_decode(Row). diff --git a/src/couchbeam_mime.erl b/src/couchbeam_mime.erl deleted file mode 100644 index ab25fd25..00000000 --- a/src/couchbeam_mime.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% @author Bob Ippolito -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Gives a good MIME type guess based on file extension. - --module(couchbeam_mime). --author('bob@mochimedia.com'). --export([from_extension/1]). - -%% @spec from_extension(S::string()) -> string() | undefined -%% @doc Given a filename extension (e.g. ".html") return a guess for the MIME -%% type such as "text/html". Will return the atom undefined if no good -%% guess is available. -from_extension(".html") -> - "text/html"; -from_extension(".xhtml") -> - "application/xhtml+xml"; -from_extension(".xml") -> - "application/xml"; -from_extension(".css") -> - "text/css"; -from_extension(".js") -> - "application/x-javascript"; -from_extension(".jpg") -> - "image/jpeg"; -from_extension(".gif") -> - "image/gif"; -from_extension(".png") -> - "image/png"; -from_extension(".swf") -> - "application/x-shockwave-flash"; -from_extension(".zip") -> - "application/zip"; -from_extension(".bz2") -> - "application/x-bzip2"; -from_extension(".gz") -> - "application/x-gzip"; -from_extension(".tar") -> - "application/x-tar"; -from_extension(".tgz") -> - "application/x-gzip"; -from_extension(".txt") -> - "text/plain"; -from_extension(".doc") -> - "application/msword"; -from_extension(".pdf") -> - "application/pdf"; -from_extension(".xls") -> - "application/vnd.ms-excel"; -from_extension(".rtf") -> - "application/rtf"; -from_extension(".mov") -> - "video/quicktime"; -from_extension(".mp3") -> - "audio/mpeg"; -from_extension(".z") -> - "application/x-compress"; -from_extension(".wav") -> - "audio/x-wav"; -from_extension(".ico") -> - "image/x-icon"; -from_extension(".bmp") -> - "image/bmp"; -from_extension(".m4a") -> - "audio/mpeg"; -from_extension(".m3u") -> - "audio/x-mpegurl"; -from_extension(".exe") -> - "application/octet-stream"; -from_extension(".csv") -> - "text/csv"; -from_extension(_) -> - undefined. - diff --git a/src/couchbeam_util.erl b/src/couchbeam_util.erl index f4018b3f..49c7877a 100644 --- a/src/couchbeam_util.erl +++ b/src/couchbeam_util.erl @@ -5,6 +5,7 @@ -module(couchbeam_util). +-export([json_encode/1, json_decode/1]). -export([encode_docid/1, encode_att_name/1]). -export([parse_options/1, parse_options/2]). -export([to_list/1, to_binary/1, to_integer/1, to_atom/1]). @@ -12,20 +13,25 @@ -export([oauth_header/3]). -export([propmerge/3, propmerge1/2]). -export([get_value/2, get_value/3]). --export([guess_mime/1, quote_plus/1, urlencode/1]). --export([parse_qs/1, urlsplit/1]). --define(PERCENT, 37). % $\% -define(ENCODE_DOCID, true). --define(FULLSTOP, 46). % $\. --define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse - (C >= $a andalso C =< $f) orelse - (C >= $A andalso C =< $F))). --define(QS_SAFE(C), ((C >= $a andalso C =< $z) orelse - (C >= $A andalso C =< $Z) orelse - (C >= $0 andalso C =< $9) orelse - (C =:= ?FULLSTOP orelse C =:= $- orelse C =:= $~ orelse - C =:= $_))). + + +json_encode(V) -> + Handler = + fun({L}) when is_list(L) -> + {struct,L}; + (Bad) -> + exit({json_encode, {bad_term, Bad}}) + end, + (mochijson2:encoder([{handler, Handler}]))(V). + +json_decode(V) -> + try (mochijson2:decoder([{object_hook, fun({struct,L}) -> {L} end}]))(V) + catch + _Type:_Error -> + throw({invalid_json,V}) + end. encode_att_name(Name) when is_binary(Name) -> encode_att_name(xmerl_ucs:from_utf8(Name)); @@ -77,13 +83,13 @@ encode_query_value(K, V) -> end. encode_value(V) -> - V1 = ejson:encode(V), + V1 = json_encode(V), binary_to_list(iolist_to_binary(V1)). % build oauth header oauth_header(Url, Action, OauthProps) -> - {_, _, _, QS, _} = urlsplit(Url), - QSL = parse_qs(QS), + {_, _, _, QS, _} = mochiweb_util:urlsplit(Url), + QSL = mochiweb_util:parse_qs(QS), % get oauth paramerers ConsumerKey = to_list(get_value(consumer_key, OauthProps)), @@ -201,177 +207,3 @@ to_atom(V) when is_binary(V) -> list_to_atom(binary_to_list(V)); to_atom(V) -> list_to_atom(lists:flatten(io_lib:format("~p", [V]))). - - -%% @spec guess_mime(string()) -> string() -%% @doc Guess the mime type of a file by the extension of its filename. -guess_mime(File) -> - case couchbeam_mime:from_extension(filename:extension(File)) of - undefined -> - "text/plain"; - Mime -> - Mime - end. - - -hexdigit(C) when C < 10 -> $0 + C; -hexdigit(C) when C < 16 -> $A + (C - 10). - -unhexdigit(C) when C >= $0, C =< $9 -> C - $0; -unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10; -unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10. - -%% @spec quote_plus(atom() | integer() | float() | string() | binary()) -> string() -%% @doc URL safe encoding of the given term. -quote_plus(Atom) when is_atom(Atom) -> - quote_plus(atom_to_list(Atom)); -quote_plus(Int) when is_integer(Int) -> - quote_plus(integer_to_list(Int)); -quote_plus(Binary) when is_binary(Binary) -> - quote_plus(binary_to_list(Binary)); -quote_plus(Float) when is_float(Float) -> - quote_plus(mochinum:digits(Float)); -quote_plus(String) -> - quote_plus(String, []). - -quote_plus([], Acc) -> - lists:reverse(Acc); -quote_plus([C | Rest], Acc) when ?QS_SAFE(C) -> - quote_plus(Rest, [C | Acc]); -quote_plus([$\s | Rest], Acc) -> - quote_plus(Rest, [$+ | Acc]); -quote_plus([C | Rest], Acc) -> - <> = <>, - quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]). - -%% @spec urlencode([{Key, Value}]) -> string() -%% @doc URL encode the property list. -urlencode(Props) -> - Pairs = lists:foldr( - fun ({K, V}, Acc) -> - [quote_plus(K) ++ "=" ++ quote_plus(V) | Acc] - end, [], Props), - string:join(Pairs, "&"). - - -%% @spec parse_qs(string() | binary()) -> [{Key, Value}] -%% @doc Parse a query string or application/x-www-form-urlencoded. -parse_qs(Binary) when is_binary(Binary) -> - parse_qs(binary_to_list(Binary)); -parse_qs(String) -> - parse_qs(String, []). - -parse_qs([], Acc) -> - lists:reverse(Acc); -parse_qs(String, Acc) -> - {Key, Rest} = parse_qs_key(String), - {Value, Rest1} = parse_qs_value(Rest), - parse_qs(Rest1, [{Key, Value} | Acc]). - -parse_qs_key(String) -> - parse_qs_key(String, []). - -parse_qs_key([], Acc) -> - {qs_revdecode(Acc), ""}; -parse_qs_key([$= | Rest], Acc) -> - {qs_revdecode(Acc), Rest}; -parse_qs_key(Rest=[$; | _], Acc) -> - {qs_revdecode(Acc), Rest}; -parse_qs_key(Rest=[$& | _], Acc) -> - {qs_revdecode(Acc), Rest}; -parse_qs_key([C | Rest], Acc) -> - parse_qs_key(Rest, [C | Acc]). - -parse_qs_value(String) -> - parse_qs_value(String, []). - -parse_qs_value([], Acc) -> - {qs_revdecode(Acc), ""}; -parse_qs_value([$; | Rest], Acc) -> - {qs_revdecode(Acc), Rest}; -parse_qs_value([$& | Rest], Acc) -> - {qs_revdecode(Acc), Rest}; -parse_qs_value([C | Rest], Acc) -> - parse_qs_value(Rest, [C | Acc]). - - - -qs_revdecode(S) -> - qs_revdecode(S, []). - -qs_revdecode([], Acc) -> - Acc; -qs_revdecode([$+ | Rest], Acc) -> - qs_revdecode(Rest, [$\s | Acc]); -qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) -> - qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]); -qs_revdecode([C | Rest], Acc) -> - qs_revdecode(Rest, [C | Acc]). - -%% @spec urlsplit(Url) -> {Scheme, Netloc, Path, Query, Fragment} -%% @doc Return a 5-tuple, does not expand % escapes. Only supports HTTP style -%% URLs. -urlsplit(Url) -> - {Scheme, Url1} = urlsplit_scheme(Url), - {Netloc, Url2} = urlsplit_netloc(Url1), - {Path, Query, Fragment} = urlsplit_path(Url2), - {Scheme, Netloc, Path, Query, Fragment}. - -urlsplit_scheme(Url) -> - case urlsplit_scheme(Url, []) of - no_scheme -> - {"", Url}; - Res -> - Res - end. - -urlsplit_scheme([C | Rest], Acc) when ((C >= $a andalso C =< $z) orelse - (C >= $A andalso C =< $Z) orelse - (C >= $0 andalso C =< $9) orelse - C =:= $+ orelse C =:= $- orelse - C =:= $.) -> - urlsplit_scheme(Rest, [C | Acc]); -urlsplit_scheme([$: | Rest], Acc=[_ | _]) -> - {string:to_lower(lists:reverse(Acc)), Rest}; -urlsplit_scheme(_Rest, _Acc) -> - no_scheme. - -urlsplit_netloc("//" ++ Rest) -> - urlsplit_netloc(Rest, []); -urlsplit_netloc(Path) -> - {"", Path}. - -urlsplit_netloc("", Acc) -> - {lists:reverse(Acc), ""}; -urlsplit_netloc(Rest=[C | _], Acc) when C =:= $/; C =:= $?; C =:= $# -> - {lists:reverse(Acc), Rest}; -urlsplit_netloc([C | Rest], Acc) -> - urlsplit_netloc(Rest, [C | Acc]). - -%% @spec urlsplit_path(Url) -> {Path, Query, Fragment} -%% @doc Return a 3-tuple, does not expand % escapes. Only supports HTTP style -%% paths. -urlsplit_path(Path) -> - urlsplit_path(Path, []). - -urlsplit_path("", Acc) -> - {lists:reverse(Acc), "", ""}; -urlsplit_path("?" ++ Rest, Acc) -> - {Query, Fragment} = urlsplit_query(Rest), - {lists:reverse(Acc), Query, Fragment}; -urlsplit_path("#" ++ Rest, Acc) -> - {lists:reverse(Acc), "", Rest}; -urlsplit_path([C | Rest], Acc) -> - urlsplit_path(Rest, [C | Acc]). - -urlsplit_query(Query) -> - urlsplit_query(Query, []). - -urlsplit_query("", Acc) -> - {lists:reverse(Acc), ""}; -urlsplit_query("#" ++ Rest, Acc) -> - {lists:reverse(Acc), Rest}; -urlsplit_query([C | Rest], Acc) -> - urlsplit_query(Rest, [C | Acc]). - - diff --git a/src/couchbeam_view.erl b/src/couchbeam_view.erl index 08dfe4ea..6ef78446 100644 --- a/src/couchbeam_view.erl +++ b/src/couchbeam_view.erl @@ -19,7 +19,7 @@ count(#view{db=Db,url=Url, options=Options, method=Method, body=Body, case couchbeam:db_request(Method, Url, ["200"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {Props} = ejson:decode(RespBody), + {Props} = couchbeam_util:json_decode(RespBody), case proplists:get_value("limit", Options) of 0 -> {ok, proplists:get_value(<<"total_rows">>, Props)}; @@ -39,7 +39,7 @@ fetch(#view{db=Db, url=Url, method=Method, body=Body, headers=Headers}) -> case couchbeam:db_request(Method, Url, ["200"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - JsonBody = ejson:decode(RespBody), + JsonBody = couchbeam_util:json_decode(RespBody), {ok, JsonBody}; Error -> Error @@ -70,7 +70,7 @@ first(View) -> case couchbeam:db_request(Method, Url, ["200"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {Props} = ejson:decode(RespBody), + {Props} = couchbeam_util:json_decode(RespBody), case proplists:get_value(<<"rows">>, Props) of [] -> {ok, []}; @@ -101,7 +101,7 @@ fold(View, Fun) -> case couchbeam:db_request(Method, Url, ["200"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {Props} = ejson:decode(RespBody), + {Props} = couchbeam_util:json_decode(RespBody), Rows = proplists:get_value(<<"rows">>, Props), fold_fun(Rows, Fun, []); Error -> @@ -127,7 +127,7 @@ foreach(View, Fun) -> case couchbeam:db_request(Method, Url, ["200"], IbrowseOpts, Headers, Body) of {ok, _, _, RespBody} -> - {Props} = ejson:decode(RespBody), + {Props} = couchbeam_util:json_decode(RespBody), Rows = proplists:get_value(<<"rows">>, Props), do_foreach(Rows, Fun); Error ->