WIP: port to webmachine
diff --git a/src/config.erl b/src/config.erl
index d123b12..78176c0 100644
--- a/src/config.erl
+++ b/src/config.erl
@@ -23,6 +23,7 @@
-export([start_link/1, stop/0, reload/0]).
-export([all/0]).
+-export([all_list/0, section_list/1]).
-export([get/1, get/2, get/3]).
-export([set/3, set/4, set/5]).
-export([delete/2, delete/3, delete/4]).
@@ -37,6 +38,8 @@
-export([init/1, terminate/2, code_change/3]).
-export([handle_call/3, handle_cast/2, handle_info/2]).
+-export([couch_dispatch/0]).
+
-record(config, {
notify_funs=[],
ini_files=undefined,
@@ -57,6 +60,23 @@
all() ->
lists:sort(gen_server:call(?MODULE, all, infinity)).
+all_list() ->
+ Grouped = lists:foldl(fun({{Section, Key}, Value}, Acc) ->
+ case dict:is_key(Section, Acc) of
+ true ->
+ dict:append(Section, {list_to_binary(Key), list_to_binary(Value)}, Acc);
+ false ->
+ dict:store(Section, [{list_to_binary(Key), list_to_binary(Value)}], Acc)
+ end
+ end, dict:new(), config:all()),
+ dict:fold(fun(Section, Values, Acc) ->
+ [{list_to_binary(Section), {Values}} | Acc]
+ end, [], Grouped).
+
+section_list(Section) ->
+ [{list_to_binary(Key), list_to_binary(Value)}
+ || {Key, Value} <- config:get(Section)].
+
get_integer(Section, Key, Default) when is_integer(Default) ->
try
to_integer(get(Section, Key, Default))
@@ -347,3 +367,6 @@
ok
end.
+
+couch_dispatch() ->
+ {["_config", '*'], config_httpr, []}.
diff --git a/src/config_httpr.erl b/src/config_httpr.erl
new file mode 100644
index 0000000..f4f4019
--- /dev/null
+++ b/src/config_httpr.erl
@@ -0,0 +1,110 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(config_httpr).
+
+
+-export([
+ init/1,
+ allowed_methods/2,
+ content_types_provided/2,
+ content_types_accepted/2,
+ resource_exists/2,
+ delete_resource/2,
+ to_json/2,
+ from_json/2
+]).
+
+
+-include_lib("webmachine/include/webmachine.hrl").
+-include_lib("chttpd2/include/chttpd2.hrl").
+
+
+-spec init(list()) -> {ok, term()}.
+init([]) ->
+ {ok, undefined}.
+
+
+content_types_provided(ReqData, Context) ->
+ {[{"application/json", to_json}], ReqData, Context}.
+
+
+content_types_accepted(ReqData, Context) ->
+ {[{"application/json", from_json}], ReqData, Context}.
+
+
+allowed_methods(ReqData, Context) ->
+ {['GET', 'PUT', 'DELETE'], ReqData, Context}.
+
+
+resource_exists(ReqData, Context) ->
+ {true, ReqData, Context}.
+
+
+-spec to_json(wrq:reqdata(), term()) -> {iodata(), wrq:reqdata(), term()}.
+to_json(ReqData, State) ->
+ Parts = wrq:path_tokens(ReqData),
+ Data = get_config(Parts),
+ couch_log:error("PATH IS(~p): ~p", [Parts, Data]),
+ {?JSON_ENCODE(Data), ReqData, State}.
+
+
+-spec from_json(wrq:reqdata(), term()) -> {iodata(), wrq:reqdata(), term()}.
+from_json(ReqData, State) ->
+ %% how to handle intentional pattern matching fail on malformed requests?
+ [Section, Key] = wrq:path_tokens(ReqData),
+ %% this will also throw an error when body is undefined
+ Value = chttpd2_util:json_body(ReqData),
+ Persist = wrq:get_req_header("X-Couch-Persist", ReqData) /= "false",
+ OldValue = config:get(Section, Key, ""),
+ ok = config:set(Section, Key, binary_to_list(Value), Persist),
+ couch_log:error("Setting value(~p): ~p [~p]", [Persist, Value, OldValue]),
+ Resp = wrq:set_resp_body(?JSON_ENCODE(list_to_binary(OldValue)), ReqData),
+ Resp1 = wrq:set_resp_header("Location", "/_config/foo/baroob", Resp),
+ {true, Resp1, State}.
+
+
+delete_resource(ReqData, State) ->
+ %% how to handle intentional pattern matching fail on malformed requests?
+ [Section, Key] = wrq:path_tokens(ReqData),
+ Persist = wrq:get_req_header("X-Couch-Persist", ReqData) /= "false",
+ case config:get(Section, Key, null) of
+ %% why does this clause throw a 500?
+ null ->
+ {false, ReqData, State};
+ OldValue ->
+ config:delete(Section, Key, Persist),
+ Resp = wrq:set_resp_body(
+ ?JSON_ENCODE(list_to_binary(OldValue)),
+ ReqData
+ ),
+ {true, Resp, State}
+ end.
+
+
+get_config([]) ->
+ {config:all_list()};
+get_config([Section]) ->
+ {config:section_list(Section)};
+get_config([Section, Key]) ->
+ case config:get(Section, Key, null) of
+ null ->
+ %% move this to resource_exists/2?
+ throw({not_found, unknown_config_value});
+ Value ->
+ %% Should we turn this into a proper json value?
+ list_to_binary(Value)
+ end.
+
+
+
+