summaryrefslogtreecommitdiff
path: root/src/mango/src/mango_httpd.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mango/src/mango_httpd.erl')
-rw-r--r--src/mango/src/mango_httpd.erl235
1 files changed, 125 insertions, 110 deletions
diff --git a/src/mango/src/mango_httpd.erl b/src/mango/src/mango_httpd.erl
index 624691bb9..002c45b2f 100644
--- a/src/mango/src/mango_httpd.erl
+++ b/src/mango/src/mango_httpd.erl
@@ -12,12 +12,10 @@
-module(mango_httpd).
-
-export([
handle_req/2
]).
-
-include_lib("couch/include/couch_db.hrl").
-include("mango.hrl").
-include("mango_idx.hrl").
@@ -46,41 +44,42 @@ handle_req(#httpd{} = Req, Db0) ->
end
end.
-
-handle_req_int(#httpd{path_parts=[_, <<"_index">> | _]} = Req, Db) ->
+handle_req_int(#httpd{path_parts = [_, <<"_index">> | _]} = Req, Db) ->
handle_index_req(Req, Db);
-handle_req_int(#httpd{path_parts=[_, <<"_explain">> | _]} = Req, Db) ->
+handle_req_int(#httpd{path_parts = [_, <<"_explain">> | _]} = Req, Db) ->
handle_explain_req(Req, Db);
-handle_req_int(#httpd{path_parts=[_, <<"_find">> | _]} = Req, Db) ->
+handle_req_int(#httpd{path_parts = [_, <<"_find">> | _]} = Req, Db) ->
handle_find_req(Req, Db);
handle_req_int(_, _) ->
throw({not_found, missing}).
-
-handle_index_req(#httpd{method='GET', path_parts=[_, _]}=Req, Db) ->
- Params = lists:flatmap(fun({K, V}) -> parse_index_param(K, V) end,
- chttpd:qs(Req)),
+handle_index_req(#httpd{method = 'GET', path_parts = [_, _]} = Req, Db) ->
+ Params = lists:flatmap(
+ fun({K, V}) -> parse_index_param(K, V) end,
+ chttpd:qs(Req)
+ ),
Idxs = lists:sort(mango_idx:list(Db)),
JsonIdxs0 = lists:map(fun mango_idx:to_json/1, Idxs),
TotalRows = length(JsonIdxs0),
- Limit = case couch_util:get_value(limit, Params, TotalRows) of
- Limit0 when Limit0 < 1 ->
- ?MANGO_ERROR(invalid_list_index_params);
- Limit0 ->
- Limit0
- end,
- Skip = case couch_util:get_value(skip, Params, 0) of
- Skip0 when Skip0 < 0 ->
- ?MANGO_ERROR(invalid_list_index_params);
- Skip0 when Skip0 > TotalRows ->
- TotalRows;
- Skip0 ->
- Skip0
- end,
- JsonIdxs = lists:sublist(JsonIdxs0, Skip+1, Limit),
- chttpd:send_json(Req, {[{total_rows, TotalRows}, {indexes, JsonIdxs}]});
-
-handle_index_req(#httpd{method='POST', path_parts=[_, _]}=Req, Db) ->
+ Limit =
+ case couch_util:get_value(limit, Params, TotalRows) of
+ Limit0 when Limit0 < 1 ->
+ ?MANGO_ERROR(invalid_list_index_params);
+ Limit0 ->
+ Limit0
+ end,
+ Skip =
+ case couch_util:get_value(skip, Params, 0) of
+ Skip0 when Skip0 < 0 ->
+ ?MANGO_ERROR(invalid_list_index_params);
+ Skip0 when Skip0 > TotalRows ->
+ TotalRows;
+ Skip0 ->
+ Skip0
+ end,
+ JsonIdxs = lists:sublist(JsonIdxs0, Skip + 1, Limit),
+ chttpd:send_json(Req, {[{total_rows, TotalRows}, {indexes, JsonIdxs}]});
+handle_index_req(#httpd{method = 'POST', path_parts = [_, _]} = Req, Db) ->
chttpd:validate_ctype(Req, "application/json"),
{ok, Opts} = mango_opts:validate_idx_create(chttpd:json_body_obj(Req)),
{ok, Idx0} = mango_idx:new(Db, Opts),
@@ -89,62 +88,89 @@ handle_index_req(#httpd{method='POST', path_parts=[_, _]}=Req, Db) ->
{ok, DDoc} = mango_util:load_ddoc(Db, mango_idx:ddoc(Idx), DbOpts),
Id = Idx#idx.ddoc,
Name = Idx#idx.name,
- Status = case mango_idx:add(DDoc, Idx) of
- {ok, DDoc} ->
- <<"exists">>;
- {ok, NewDDoc} ->
- CreateOpts = get_idx_w_opts(Opts),
- case mango_crud:insert(Db, NewDDoc, CreateOpts) of
- {ok, [{RespProps}]} ->
- case lists:keyfind(error, 1, RespProps) of
- {error, Reason} ->
- ?MANGO_ERROR({error_saving_ddoc, Reason});
- _ ->
- <<"created">>
- end;
- _ ->
- ?MANGO_ERROR(error_saving_ddoc)
- end
- end,
- chttpd:send_json(Req, {[{result, Status}, {id, Id}, {name, Name}]});
-
-handle_index_req(#httpd{path_parts=[_, _]}=Req, _Db) ->
+ Status =
+ case mango_idx:add(DDoc, Idx) of
+ {ok, DDoc} ->
+ <<"exists">>;
+ {ok, NewDDoc} ->
+ CreateOpts = get_idx_w_opts(Opts),
+ case mango_crud:insert(Db, NewDDoc, CreateOpts) of
+ {ok, [{RespProps}]} ->
+ case lists:keyfind(error, 1, RespProps) of
+ {error, Reason} ->
+ ?MANGO_ERROR({error_saving_ddoc, Reason});
+ _ ->
+ <<"created">>
+ end;
+ _ ->
+ ?MANGO_ERROR(error_saving_ddoc)
+ end
+ end,
+ chttpd:send_json(Req, {[{result, Status}, {id, Id}, {name, Name}]});
+handle_index_req(#httpd{path_parts = [_, _]} = Req, _Db) ->
chttpd:send_method_not_allowed(Req, "GET,POST");
-
%% Essentially we just iterate through the list of ddoc ids passed in and
%% delete one by one. If an error occurs, all previous documents will be
%% deleted, but an error will be thrown for the current ddoc id.
-handle_index_req(#httpd{method='POST', path_parts=[_, <<"_index">>,
- <<"_bulk_delete">>]}=Req, Db) ->
+handle_index_req(
+ #httpd{
+ method = 'POST',
+ path_parts = [
+ _,
+ <<"_index">>,
+ <<"_bulk_delete">>
+ ]
+ } = Req,
+ Db
+) ->
chttpd:validate_ctype(Req, "application/json"),
{ok, Opts} = mango_opts:validate_bulk_delete(chttpd:json_body_obj(Req)),
Idxs = mango_idx:list(Db),
DDocs = get_bulk_delete_ddocs(Opts),
DelOpts = get_idx_w_opts(Opts),
- {Success, Fail} = lists:foldl(fun(DDocId0, {Success0, Fail0}) ->
- DDocId = convert_to_design_id(DDocId0),
- Filt = fun(Idx) -> mango_idx:ddoc(Idx) == DDocId end,
- Id = {<<"id">>, DDocId},
- case mango_idx:delete(Filt, Db, Idxs, DelOpts) of
- {ok, true} ->
- {[{[Id, {<<"ok">>, true}]} | Success0], Fail0};
- {error, Error} ->
- {Success0, [{[Id, {<<"error">>, Error}]} | Fail0]}
- end
- end, {[], []}, DDocs),
+ {Success, Fail} = lists:foldl(
+ fun(DDocId0, {Success0, Fail0}) ->
+ DDocId = convert_to_design_id(DDocId0),
+ Filt = fun(Idx) -> mango_idx:ddoc(Idx) == DDocId end,
+ Id = {<<"id">>, DDocId},
+ case mango_idx:delete(Filt, Db, Idxs, DelOpts) of
+ {ok, true} ->
+ {[{[Id, {<<"ok">>, true}]} | Success0], Fail0};
+ {error, Error} ->
+ {Success0, [{[Id, {<<"error">>, Error}]} | Fail0]}
+ end
+ end,
+ {[], []},
+ DDocs
+ ),
chttpd:send_json(Req, {[{<<"success">>, Success}, {<<"fail">>, Fail}]});
-
-handle_index_req(#httpd{path_parts=[_, <<"_index">>,
- <<"_bulk_delete">>]}=Req, _Db) ->
+handle_index_req(
+ #httpd{
+ path_parts = [
+ _,
+ <<"_index">>,
+ <<"_bulk_delete">>
+ ]
+ } = Req,
+ _Db
+) ->
chttpd:send_method_not_allowed(Req, "POST");
-
-handle_index_req(#httpd{method='DELETE',
- path_parts=[A, B, <<"_design">>, DDocId0, Type, Name]}=Req, Db) ->
+handle_index_req(
+ #httpd{
+ method = 'DELETE',
+ path_parts = [A, B, <<"_design">>, DDocId0, Type, Name]
+ } = Req,
+ Db
+) ->
PathParts = [A, B, <<"_design/", DDocId0/binary>>, Type, Name],
- handle_index_req(Req#httpd{path_parts=PathParts}, Db);
-
-handle_index_req(#httpd{method='DELETE',
- path_parts=[_, _, DDocId0, Type, Name]}=Req, Db) ->
+ handle_index_req(Req#httpd{path_parts = PathParts}, Db);
+handle_index_req(
+ #httpd{
+ method = 'DELETE',
+ path_parts = [_, _, DDocId0, Type, Name]
+ } = Req,
+ Db
+) ->
Idxs = mango_idx:list(Db),
DDocId = convert_to_design_id(DDocId0),
DelOpts = get_idx_del_opts(Req),
@@ -162,24 +188,20 @@ handle_index_req(#httpd{method='DELETE',
{error, Error} ->
?MANGO_ERROR({error_saving_ddoc, Error})
end;
-
-handle_index_req(#httpd{path_parts=[_, _, _DDocId0, _Type, _Name]}=Req, _Db) ->
+handle_index_req(#httpd{path_parts = [_, _, _DDocId0, _Type, _Name]} = Req, _Db) ->
chttpd:send_method_not_allowed(Req, "DELETE").
-
-handle_explain_req(#httpd{method='POST'}=Req, Db) ->
+handle_explain_req(#httpd{method = 'POST'} = Req, Db) ->
chttpd:validate_ctype(Req, "application/json"),
Body = maybe_set_partition(Req),
{ok, Opts0} = mango_opts:validate_find(Body),
{value, {selector, Sel}, Opts} = lists:keytake(selector, 1, Opts0),
Resp = mango_crud:explain(Db, Sel, Opts),
chttpd:send_json(Req, Resp);
-
handle_explain_req(Req, _Db) ->
chttpd:send_method_not_allowed(Req, "POST").
-
-handle_find_req(#httpd{method='POST'}=Req, Db) ->
+handle_find_req(#httpd{method = 'POST'} = Req, Db) ->
chttpd:validate_ctype(Req, "application/json"),
Body = maybe_set_partition(Req),
{ok, Opts0} = mango_opts:validate_find(Body),
@@ -191,17 +213,13 @@ handle_find_req(#httpd{method='POST'}=Req, Db) ->
{error, Error} ->
chttpd:send_error(Req, Error)
end;
-
-
handle_find_req(Req, _Db) ->
chttpd:send_method_not_allowed(Req, "POST").
-
-set_user_ctx(#httpd{user_ctx=Ctx}, Db) ->
+set_user_ctx(#httpd{user_ctx = Ctx}, Db) ->
{ok, NewDb} = couch_db:set_user_ctx(Db, Ctx),
NewDb.
-
get_idx_w_opts(Opts) ->
case lists:keyfind(w, 1, Opts) of
{w, N} when is_integer(N), N > 0 ->
@@ -210,7 +228,6 @@ get_idx_w_opts(Opts) ->
[{w, "2"}]
end.
-
get_bulk_delete_ddocs(Opts) ->
case lists:keyfind(docids, 1, Opts) of
{docids, DDocs} when is_list(DDocs) ->
@@ -219,17 +236,16 @@ get_bulk_delete_ddocs(Opts) ->
[]
end.
-
get_idx_del_opts(Req) ->
try
WStr = chttpd:qs_value(Req, "w", "2"),
_ = list_to_integer(WStr),
[{w, WStr}]
- catch _:_ ->
- [{w, "2"}]
+ catch
+ _:_ ->
+ [{w, "2"}]
end.
-
maybe_set_partition(Req) ->
{Props} = chttpd:json_body_obj(Req),
case chttpd:qs_value(Req, "partition", undefined) of
@@ -246,31 +262,31 @@ maybe_set_partition(Req) ->
end
end.
-
convert_to_design_id(DDocId) ->
case DDocId of
<<"_design/", _/binary>> -> DDocId;
_ -> <<"_design/", DDocId/binary>>
end.
-
start_find_resp(Req) ->
chttpd:start_delayed_json_response(Req, 200, [], "{\"docs\":[").
-
end_find_resp(Acc0) ->
- #vacc{resp=Resp00, buffer=Buf, kvs=KVs, threshold=Max} = Acc0,
+ #vacc{resp = Resp00, buffer = Buf, kvs = KVs, threshold = Max} = Acc0,
{ok, Resp0} = chttpd:close_delayed_json_object(Resp00, Buf, "\r\n]", Max),
- FinalAcc = lists:foldl(fun({K, V}, Acc) ->
- JK = ?JSON_ENCODE(K),
- JV = ?JSON_ENCODE(V),
- [JV, ": ", JK, ",\r\n" | Acc]
- end, [], KVs),
+ FinalAcc = lists:foldl(
+ fun({K, V}, Acc) ->
+ JK = ?JSON_ENCODE(K),
+ JV = ?JSON_ENCODE(V),
+ [JV, ": ", JK, ",\r\n" | Acc]
+ end,
+ [],
+ KVs
+ ),
Chunk = lists:reverse(FinalAcc, ["}\r\n"]),
{ok, Resp1} = chttpd:send_delayed_chunk(Resp0, Chunk),
chttpd:end_delayed_json_response(Resp1).
-
run_find(Resp, Db, Sel, Opts) ->
Acc0 = #vacc{
resp = Resp,
@@ -280,18 +296,18 @@ run_find(Resp, Db, Sel, Opts) ->
},
mango_crud:find(Db, Sel, fun handle_doc/2, Acc0, Opts).
-
handle_doc({add_key, Key, Value}, Acc0) ->
- #vacc{kvs=KVs} = Acc0,
+ #vacc{kvs = KVs} = Acc0,
NewKVs = lists:keystore(Key, 1, KVs, {Key, Value}),
{ok, Acc0#vacc{kvs = NewKVs}};
handle_doc({row, Doc}, Acc0) ->
- #vacc{prepend=Prepend} = Acc0,
+ #vacc{prepend = Prepend} = Acc0,
Chunk = [Prepend, ?JSON_ENCODE(Doc)],
maybe_flush_response(Acc0, Chunk, iolist_size(Chunk)).
-maybe_flush_response(#vacc{bufsize=Size, threshold=Max} = Acc, Data, Len)
- when Size > 0 andalso (Size + Len) > Max ->
+maybe_flush_response(#vacc{bufsize = Size, threshold = Max} = Acc, Data, Len) when
+ Size > 0 andalso (Size + Len) > Max
+->
#vacc{buffer = Buffer, resp = Resp} = Acc,
{ok, R1} = chttpd:send_delayed_chunk(Resp, Buffer),
{ok, Acc#vacc{prepend = ",\r\n", buffer = Data, bufsize = Len, resp = R1}};
@@ -304,18 +320,17 @@ maybe_flush_response(Acc0, Data, Len) ->
},
{ok, Acc}.
-
parse_index_param("limit", Value) ->
[{limit, parse_val(Value)}];
parse_index_param("skip", Value) ->
[{skip, parse_val(Value)}];
parse_index_param(_Key, _Value) ->
- [].
+ [].
parse_val(Value) ->
case (catch list_to_integer(Value)) of
- IntVal when is_integer(IntVal) ->
- IntVal;
- _ ->
- ?MANGO_ERROR(invalid_list_index_params)
+ IntVal when is_integer(IntVal) ->
+ IntVal;
+ _ ->
+ ?MANGO_ERROR(invalid_list_index_params)
end.