Namdak Tonpa 3 лет назад
Родитель
Сommit
1116a4184f
6 измененных файлов с 687 добавлено и 301 удалено
  1. 4 4
      mix.exs
  2. 17 0
      rebar.config
  3. 1 1
      src/rest.app.src
  4. 243 115
      src/rest.erl
  5. 199 88
      src/rest_cowboy.erl
  6. 223 93
      src/rest_kvs.erl

+ 4 - 4
mix.exs

@@ -3,7 +3,7 @@ defmodule REST.Mixfile do
 
 
   def project do
   def project do
     [app: :rest,
     [app: :rest,
-     version: "6.1.1",
+     version: "6.11.1",
      description: "REST erlang interface generator",
      description: "REST erlang interface generator",
      deps: deps(),
      deps: deps(),
      package: package()]
      package: package()]
@@ -17,9 +17,9 @@ defmodule REST.Mixfile do
   end
   end
 
 
   def deps, do: [ {:ex_doc, "~> 0.11", only: :dev},
   def deps, do: [ {:ex_doc, "~> 0.11", only: :dev},
-                  {:rocksdb, "~> 1.3.2"},
-                  {:bpe, "~> 5.1.1"},
-                  {:erp, "~> 1.1.1"},
+                  {:rocksdb, "~> 1.6.0"},
+                  {:bpe, "~> 6.11.0"},
+                  {:erp, "~> 1.11.0"},
                   {:jsone, "~> 1.5.0"},
                   {:jsone, "~> 1.5.0"},
                   {:cowboy, "~> 2.5.0"} ]
                   {:cowboy, "~> 2.5.0"} ]
 
 

+ 17 - 0
rebar.config

@@ -9,3 +9,20 @@
         {jsone, ".*", {git, "git://github.com/sile/jsone", {tag,"master"}}},
         {jsone, ".*", {git, "git://github.com/sile/jsone", {tag,"master"}}},
         {syn, ".*", {git, "git://github.com/ostinelli/syn", {tag,"master"}}},
         {syn, ".*", {git, "git://github.com/ostinelli/syn", {tag,"master"}}},
         {cowboy, ".*", {git, "git://github.com/voxoz/cowboy2", {tag,"master"}}}]}.
         {cowboy, ".*", {git, "git://github.com/voxoz/cowboy2", {tag,"master"}}}]}.
+
+{project_plugins, [rebar3_format]}.
+{format, [
+    {files, ["src/*.erl", "test/*.erl"]},
+    {formatter, otp_formatter},
+    {options, #{ line_length => 108,
+                 paper => 250,
+                 spaces_around_fields => false,
+                 inlining => all,
+                 inline_clause_bodies => true,
+                 inline_expressions => true,
+                 inline_qualified_function_composition => true,
+                 inline_simple_funs => true,
+                 inline_items => all,
+                 inline_fields => true,
+                 inline_attributes => true
+                 }}]}.

+ 1 - 1
src/rest.app.src

@@ -1,6 +1,6 @@
 {application, rest, [
 {application, rest, [
     {description,  "REST Yoctoframework"},
     {description,  "REST Yoctoframework"},
-    {vsn, "6.1.1"},
+    {vsn, "6.11.1"},
     {applications, [public_key,asn1,kernel,stdlib,ranch,cowboy,syntax_tools,compiler,n2o]},
     {applications, [public_key,asn1,kernel,stdlib,ranch,cowboy,syntax_tools,compiler,n2o]},
     {modules, []},
     {modules, []},
     {registered, []},
     {registered, []},

+ 243 - 115
src/rest.erl

@@ -1,209 +1,337 @@
 -module(rest).
 -module(rest).
+
 -author('Dmitry Bushmelev').
 -author('Dmitry Bushmelev').
+
 -behaviour(application).
 -behaviour(application).
+
 -behaviour(supervisor).
 -behaviour(supervisor).
--export([init/1,start/2, stop/1]).
--export([behaviour_info/1, parse_transform/2, generate_to_json/3, binarize/1,
-         generate_from_json/3, from_json/2, to_json/1, to_binary/1, parse/1, atomize/1]).
+
+-export([init/1, start/2, stop/1]).
+
+-export([behaviour_info/1,
+         parse_transform/2,
+         generate_to_json/3,
+         binarize/1,
+         generate_from_json/3,
+         from_json/2,
+         to_json/1,
+         to_binary/1,
+         parse/1,
+         atomize/1]).
 
 
 stop(_State) -> ok.
 stop(_State) -> ok.
-start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+start(_StartType, _StartArgs) ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
 init([]) ->
 init([]) ->
-   users:init(),
-   kvs:join(),
-   cowboy:start_clear(http, [{port,application:get_env(n2o,port,8005)}],
-                            #{env=>#{dispatch=> points() }}),
-   {ok, {{one_for_one, 5, 10}, []}}.
-
-points() -> cowboy_router:compile([{'_', [
-             {"/rest/kvs/0/[...]",     rest_kvs,    []},
-             {"/rest/kvs/1/:id/[...]", rest_kvs,    []},
-             {"/rest/:resource",     rest_cowboy, []},
-             {"/rest/:resource/:id", rest_cowboy, []}
-            ]}]).
-
-behaviour_info(callbacks) -> [{exists, 1}, {get, 0}, {get, 1}, {post, 1}, {delete, 1}, {from_json, 2}, {to_json, 1}];
+    users:init(),
+    kvs:join(),
+    cowboy:start_clear(http,
+                       [{port, application:get_env(n2o, port, 8005)}],
+                       #{env => #{dispatch => points()}}),
+    {ok, {{one_for_one, 5, 10}, []}}.
+
+points() ->
+    cowboy_router:compile([{'_',
+                            [{"/rest/kvs/0/[...]", rest_kvs, []},
+                             {"/rest/kvs/1/:id/[...]", rest_kvs, []},
+                             {"/rest/:resource", rest_cowboy, []},
+                             {"/rest/:resource/:id", rest_cowboy, []}]}]).
+
+behaviour_info(callbacks) ->
+    [{exists, 1},
+     {get, 0},
+     {get, 1},
+     {post, 1},
+     {delete, 1},
+     {from_json, 2},
+     {to_json, 1}];
 behaviour_info(_) -> undefined.
 behaviour_info(_) -> undefined.
 
 
 parse_transform(Forms, _Options) ->
 parse_transform(Forms, _Options) ->
     RecordName = rest_record(Forms),
     RecordName = rest_record(Forms),
     RecordFields = record_fields(RecordName, Forms),
     RecordFields = record_fields(RecordName, Forms),
-    Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
-    Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
+    Forms1 = generate({from_json, 2},
+                      RecordName,
+                      RecordFields,
+                      Forms),
+    Forms2 = generate({to_json, 1},
+                      RecordName,
+                      RecordFields,
+                      Forms1),
     Forms2.
     Forms2.
 
 
 rest_record([]) -> [];
 rest_record([]) -> [];
-rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
+rest_record([{attribute, _, rest_record, RecordName}
+             | _Forms]) ->
+    RecordName;
 rest_record([_ | Forms]) -> rest_record(Forms).
 rest_record([_ | Forms]) -> rest_record(Forms).
 
 
-record_field({record_field, _, {atom, _, Field}   },_cordName) ->
-%  io:format("Case 1: ~p~n",[Field]),
-  Field;
-record_field({record_field, _, {atom, _, Field}, Type},_cordName) ->
-%  io:format("Case 2: ~p~n",[Field]),
-  Field;
-record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, Type},RecordName) ->
-  Rec = allow(Type),
-  put({RecordName,Field},Rec),
-%  case Rec of
-%    undefined -> io:format("Case 3: ~p~n",[Field]);
-%            _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
-  Field.
-
-allow({type,_,union,Components}) -> findType(Components);
+record_field({record_field, _, {atom, _, Field}},
+             _cordName) ->
+    %  io:format("Case 1: ~p~n",[Field]),
+    Field;
+record_field({record_field, _, {atom, _, Field}, Type},
+             _cordName) ->
+    %  io:format("Case 2: ~p~n",[Field]),
+    Field;
+record_field({typed_record_field,
+              {record_field, _, {atom, _, Field}, _},
+              Type},
+             RecordName) ->
+    Rec = allow(Type),
+    put({RecordName, Field}, Rec),
+    %  case Rec of
+    %    undefined -> io:format("Case 3: ~p~n",[Field]);
+    %            _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
+    Field.
+
+allow({type, _, union, Components}) ->
+    findType(Components);
 allow(Type) -> findType([Type]).
 allow(Type) -> findType([Type]).
 
 
 findType([]) -> undefined;
 findType([]) -> undefined;
-findType([{type,_,record,[{atom,_,X}]}|T]) -> X;
-findType([{remote_type,_,[{atom,_,_},{atom,_,X},_]}|T]) -> X;
-findType([H|T]) ->
-%  io:format("Unknown Type: ~p~n",[H]),
-  findType(T).
-
-record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
-    [record_field(Field,RecordName) || Field <- Fields];
-record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
+findType([{type, _, record, [{atom, _, X}]} | T]) -> X;
+findType([{remote_type,
+           _,
+           [{atom, _, _}, {atom, _, X}, _]}
+          | T]) ->
+    X;
+findType([H | T]) ->
+    %  io:format("Unknown Type: ~p~n",[H]),
+    findType(T).
+
+record_fields(RecordName,
+              [{attribute, _, record, {RecordName, Fields}}
+               | _Forms]) ->
+    [record_field(Field, RecordName) || Field <- Fields];
+record_fields(RecordName, [_ | Forms]) ->
+    record_fields(RecordName, Forms);
 record_fields(__cordName, []) -> [].
 record_fields(__cordName, []) -> [].
 
 
 last_export_line(Exports) ->
 last_export_line(Exports) ->
     case lists:reverse(Exports) of
     case lists:reverse(Exports) of
-         [{_, Line, _, _} | _] -> Line;
-         _ -> 0 end.
+        [{_, Line, _, _} | _] -> Line;
+        _ -> 0
+    end.
 
 
-generate({FunName, _Arity} = Fun, Record, Fields, Forms) ->
-    Exports = lists:filter(fun({attribute, _, export, _}) -> true; (_) -> false end, Forms),
+generate({FunName, _Arity} = Fun, Record, Fields,
+         Forms) ->
+    Exports = lists:filter(fun ({attribute,
+                                 _,
+                                 export,
+                                 _}) ->
+                                   true;
+                               (_) -> false
+                           end,
+                           Forms),
     case exported(Fun, Exports) of
     case exported(Fun, Exports) of
-        true  -> Forms;
+        true -> Forms;
         false ->
         false ->
             Line = last_export_line(Exports),
             Line = last_export_line(Exports),
-            Gen = list_to_atom("generate_" ++ atom_to_list(FunName)),
-            lists:flatten([?MODULE:Gen(export(Form, Fun, Line), Record, Fields) || Form <- Forms])
+            Gen = list_to_atom("generate_" ++
+                                   atom_to_list(FunName)),
+            lists:flatten([(?MODULE):Gen(export(Form, Fun, Line),
+                                         Record,
+                                         Fields)
+                           || Form <- Forms])
     end.
     end.
 
 
-exported(Fun, Exports) -> lists:member(Fun, lists:flatten([E || {attribute, _, export, E} <- Exports])).
+exported(Fun, Exports) ->
+    lists:member(Fun,
+                 lists:flatten([E
+                                || {attribute, _, export, E} <- Exports])).
 
 
-field_var(Field) -> list_to_atom("V_" ++ atom_to_list(Field)).
+field_var(Field) ->
+    list_to_atom("V_" ++ atom_to_list(Field)).
 
 
 from_json_prelude(Line) ->
 from_json_prelude(Line) ->
-    {clause, Line,
+    {clause,
+     Line,
      [{nil, Line}, {var, Line, 'Acc'}],
      [{nil, Line}, {var, Line, 'Acc'}],
      [],
      [],
      [{var, Line, 'Acc'}]}.
      [{var, Line, 'Acc'}]}.
 
 
 from_json_coda(Line) ->
 from_json_coda(Line) ->
-    {clause, Line,
-     [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
+    {clause,
+     Line,
+     [{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}},
+      {var, Line, 'Acc'}],
      [],
      [],
-     [{call, Line, {atom, Line, from_json}, [
-%     {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
-     {call,Line,{remote,Line,{atom,Line,?MODULE},{atom,Line,binarize}},[{var, Line, 'Json'}]}
-     , {var, Line, 'Acc'}]}]}.
+     [{call,
+       Line,
+       {atom, Line, from_json},
+       [%     {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
+        {call,
+         Line,
+         {remote,
+          Line,
+          {atom, Line, ?MODULE},
+          {atom, Line, binarize}},
+         [{var, Line, 'Json'}]},
+        {var, Line, 'Acc'}]}]}.
 
 
 from_json_clauses(_, _, []) -> [];
 from_json_clauses(_, _, []) -> [];
 from_json_clauses(Line, Record, [Field | Fields]) ->
 from_json_clauses(Line, Record, [Field | Fields]) ->
-    [{clause, Line,
-      [{cons, Line,
-        {tuple, Line,
-         [{bin, Line,
-           [{bin_element, Line, {string, Line, atom_to_list(Field)}, default, default}]},
+    [{clause,
+      Line,
+      [{cons,
+        Line,
+        {tuple,
+         Line,
+         [{bin,
+           Line,
+           [{bin_element,
+             Line,
+             {string, Line, atom_to_list(Field)},
+             default,
+             default}]},
           {var, Line, field_var(Field)}]},
           {var, Line, field_var(Field)}]},
         {var, Line, 'Json'}},
         {var, Line, 'Json'}},
        {var, Line, 'Acc'}],
        {var, Line, 'Acc'}],
       [],
       [],
-      [{call, Line,
+      [{call,
+        Line,
         {atom, Line, from_json},
         {atom, Line, from_json},
         [{var, Line, 'Json'},
         [{var, Line, 'Json'},
-         {record, Line,
+         {record,
+          Line,
           {var, Line, 'Acc'},
           {var, Line, 'Acc'},
           Record,
           Record,
-          [{record_field, Line,
+          [{record_field,
+            Line,
             {atom, Line, Field},
             {atom, Line, Field},
-             {call, Line,
-             {remote, Line, {atom, Line, ?MODULE }, {atom, Line, from_json}},
+            {call,
+             Line,
+             {remote,
+              Line,
+              {atom, Line, ?MODULE},
+              {atom, Line, from_json}},
              [{var, Line, field_var(Field)},
              [{var, Line, field_var(Field)},
-              {atom,Line, case get({Record,Field}) of undefined -> Record; FieldType -> FieldType end}]}
-            }]}]}]}
+              {atom,
+               Line,
+               case get({Record, Field}) of
+                   undefined -> Record;
+                   FieldType -> FieldType
+               end}]}}]}]}]}
      | from_json_clauses(Line, Record, Fields)].
      | from_json_clauses(Line, Record, Fields)].
 
 
 generate_from_json({eof, Line}, Record, Fields) ->
 generate_from_json({eof, Line}, Record, Fields) ->
-    [{function, Line, from_json, 2,
-      [from_json_prelude(Line)] ++ from_json_clauses(Line, Record, Fields) ++ [from_json_coda(Line)]},
+    [{function,
+      Line,
+      from_json,
+      2,
+      [from_json_prelude(Line)] ++
+          from_json_clauses(Line, Record, Fields) ++
+              [from_json_coda(Line)]},
      {eof, Line + 1}];
      {eof, Line + 1}];
 generate_from_json(Form, _, _) -> Form.
 generate_from_json(Form, _, _) -> Form.
 
 
-export({attribute, LastExportLine, export, Exports}, Fun, LastExportLine) ->
+export({attribute, LastExportLine, export, Exports},
+       Fun, LastExportLine) ->
     {attribute, LastExportLine, export, [Fun | Exports]};
     {attribute, LastExportLine, export, [Fun | Exports]};
 export(Form, _, _) -> Form.
 export(Form, _, _) -> Form.
 
 
 to_json_cons(Line, []) -> {nil, Line};
 to_json_cons(Line, []) -> {nil, Line};
 to_json_cons(Line, [Field | Fields]) ->
 to_json_cons(Line, [Field | Fields]) ->
-    {cons, Line,
-     {tuple, Line,
+    {cons,
+     Line,
+     {tuple,
+      Line,
       [{atom, Line, Field},
       [{atom, Line, Field},
-       {call, Line,
-        {remote, Line, {atom, Line, ?MODULE}, {atom, Line, to_json}},
+       {call,
+        Line,
+        {remote,
+         Line,
+         {atom, Line, ?MODULE},
+         {atom, Line, to_json}},
         [{var, Line, field_var(Field)}]}]},
         [{var, Line, field_var(Field)}]}]},
      to_json_cons(Line, Fields)}.
      to_json_cons(Line, Fields)}.
 
 
 generate_to_json({eof, Line}, Record, Fields) ->
 generate_to_json({eof, Line}, Record, Fields) ->
-    [{function, Line, to_json, 1,
-      [{clause, Line,
-        [{record, Line, Record,
-          [{record_field, Line, {atom, Line, F}, {var, Line, field_var(F)}} || F <- Fields]}],
+    [{function,
+      Line,
+      to_json,
+      1,
+      [{clause,
+        Line,
+        [{record,
+          Line,
+          Record,
+          [{record_field,
+            Line,
+            {atom, Line, F},
+            {var, Line, field_var(F)}}
+           || F <- Fields]}],
         [],
         [],
         [to_json_cons(Line, Fields)]}]},
         [to_json_cons(Line, Fields)]}]},
      {eof, Line + 1}];
      {eof, Line + 1}];
-
 generate_to_json(Form, _, _) -> Form.
 generate_to_json(Form, _, _) -> Form.
 
 
-from_json(<<Data/binary>>,_) ->
-  binary_to_list(Data);
-from_json({struct, Props},X) ->
-  from_json(Props,X);
-from_json([{Key,_}|_]=Props,X) when Key =/= struct ->
-  X:from_json(binarize(Props),X:new());
-from_json(Any,X) ->
-  Any.
-
-atomize([{Key,_}|_]=Props) when Key =/= struct ->
-  lists:map(fun ({K,V}) when is_atom(K) -> {K,V};
-                ({K,V}) when is_binary(K) -> {list_to_existing_atom(binary_to_list(K)),V} end, Props);
+from_json(<<Data/binary>>, _) -> binary_to_list(Data);
+from_json({struct, Props}, X) -> from_json(Props, X);
+from_json([{Key, _} | _] = Props, X)
+    when Key =/= struct ->
+    X:from_json(binarize(Props), X:new());
+from_json(Any, X) -> Any.
+
+atomize([{Key, _} | _] = Props) when Key =/= struct ->
+    lists:map(fun ({K, V}) when is_atom(K) -> {K, V};
+                  ({K, V}) when is_binary(K) ->
+                      {list_to_existing_atom(binary_to_list(K)), V}
+              end,
+              Props);
 atomize(X) -> X.
 atomize(X) -> X.
 
 
-binarize([{Key,_}|_]=Props) when Key =/= struct ->
-  lists:map(fun ({K,V}) when is_atom(K) -> {list_to_binary(atom_to_list(K)),allowed_value(V)};
-                ({K,V}) when is_binary(K) -> {K,allowed_value(V)} end, Props);
+binarize([{Key, _} | _] = Props) when Key =/= struct ->
+    lists:map(fun ({K, V}) when is_atom(K) ->
+                      {list_to_binary(atom_to_list(K)), allowed_value(V)};
+                  ({K, V}) when is_binary(K) -> {K, allowed_value(V)}
+              end,
+              Props);
 binarize(X) -> X.
 binarize(X) -> X.
 
 
 allowed_value(X) when is_reference(X) -> [];
 allowed_value(X) when is_reference(X) -> [];
 allowed_value(X) -> X.
 allowed_value(X) -> X.
 
 
-to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
+to_json(X) when is_tuple(X) ->
+    Module = hd(tuple_to_list(X)),
+    Module:to_json(X);
 to_json(Data) ->
 to_json(Data) ->
     case is_string(Data) of
     case is_string(Data) of
-        true  -> rest:to_binary(Data);
+        true -> rest:to_binary(Data);
         false -> json_match(Data)
         false -> json_match(Data)
     end.
     end.
 
 
 json_match([{_, _} | _] = Props) ->
 json_match([{_, _} | _] = Props) ->
-  [ {rest:to_binary(Key), to_json(Value)} || {Key, Value} <- Props];
-json_match([_ | _] = NonEmptyList) -> [to_json(X) || X <- NonEmptyList];
+    [{rest:to_binary(Key), to_json(Value)}
+     || {Key, Value} <- Props];
+json_match([_ | _] = NonEmptyList) ->
+    [to_json(X) || X <- NonEmptyList];
 json_match(Any) -> Any.
 json_match(Any) -> Any.
 
 
-is_char(C) -> is_integer(C) andalso C >= 0 andalso C =< 255.
+is_char(C) ->
+    is_integer(C) andalso C >= 0 andalso C =< 255.
 
 
-is_string([N | _] = PossibleString) when is_number(N) -> lists:all(fun is_char/1, PossibleString);
-is_string(_)                                          -> false.
+is_string([N | _] = PossibleString) when is_number(N) ->
+    lists:all(fun is_char/1, PossibleString);
+is_string(_) -> false.
 
 
-to_binary(A) when is_atom(A) -> atom_to_binary(A,latin1);
+to_binary(A) when is_atom(A) ->
+    atom_to_binary(A, latin1);
 to_binary(B) when is_binary(B) -> B;
 to_binary(B) when is_binary(B) -> B;
-to_binary(I) when is_integer(I) -> to_binary(integer_to_list(I));
-to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
-to_binary(L) when is_list(L) ->  iolist_to_binary(L).
+to_binary(I) when is_integer(I) ->
+    to_binary(integer_to_list(I));
+to_binary(F) when is_float(F) ->
+    float_to_binary(F, [{decimals, 9}, compact]);
+to_binary(L) when is_list(L) -> iolist_to_binary(L).
 
 
-parse(String) when is_binary(String) -> parse(binary_to_list(String));
+parse(String) when is_binary(String) ->
+    parse(binary_to_list(String));
 parse(String) ->
 parse(String) ->
-    {ok,Tokens,_EndLine} = erl_scan:string(String ++ "."),
-    {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
-    {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
+    {ok, Tokens, _EndLine} = erl_scan:string(String ++ "."),
+    {ok, AbsForm} = erl_parse:parse_exprs(Tokens),
+    {value, Value, _Bs} = erl_eval:exprs(AbsForm,
+                                         erl_eval:new_bindings()),
     Value.
     Value.

+ 199 - 88
src/rest_cowboy.erl

@@ -1,147 +1,258 @@
 -module(rest_cowboy).
 -module(rest_cowboy).
+
 -author('Dmitry Bushmelev').
 -author('Dmitry Bushmelev').
--record(st, {resource_module = undefined :: atom(), resource_id = undefined :: binary()}).
--export([init/2, rest_init/2, resource_exists/2, allowed_methods/2, content_types_provided/2,
-         to_html/2, to_json/2, content_types_accepted/2, delete_resource/2,
-         handle_urlencoded_data/2, handle_json_data/2]).
+
+-record(st,
+        {resource_module = undefined :: atom(),
+         resource_id = undefined :: binary()}).
+
+-export([init/2,
+         rest_init/2,
+         resource_exists/2,
+         allowed_methods/2,
+         content_types_provided/2,
+         to_html/2,
+         to_json/2,
+         content_types_accepted/2,
+         delete_resource/2,
+         handle_urlencoded_data/2,
+         handle_json_data/2]).
 
 
 init(Req, Opts) -> {cowboy_rest, Req, Opts}.
 init(Req, Opts) -> {cowboy_rest, Req, Opts}.
 
 
 -ifndef(REST_JSON).
 -ifndef(REST_JSON).
--define(REST_JSON, (application:get_env(rest,json,jsone))).
+
+-define(REST_JSON,
+        application:get_env(rest, json, jsone)).
+
 -endif.
 -endif.
 
 
 c(X) -> list_to_atom(binary_to_list(X)).
 c(X) -> list_to_atom(binary_to_list(X)).
 
 
 rest_init(Req, _Opts) ->
 rest_init(Req, _Opts) ->
     {Resource, Req1} = cowboy_req:binding(resource, Req),
     {Resource, Req1} = cowboy_req:binding(resource, Req),
-    Module = case rest_module(Resource) of {ok, M} -> M; _ -> undefined end,
+    Module = case rest_module(Resource) of
+                 {ok, M} -> M;
+                 _ -> undefined
+             end,
     {Id, Req2} = cowboy_req:binding(id, Req1),
     {Id, Req2} = cowboy_req:binding(id, Req1),
-    {Origin, Req3} = cowboy_req:header(<<"origin">>, Req2, <<"*">>),
-    Req4 = cowboy_req:set_resp_header(<<"Access-Control-Allow-Origin">>, Origin, Req3),
+    {Origin, Req3} = cowboy_req:header(<<"origin">>,
+                                       Req2,
+                                       <<"*">>),
+    Req4 =
+        cowboy_req:set_resp_header(<<"Access-Control-Allow-Origin">>,
+                                   Origin,
+                                   Req3),
     io:format("REST INIT~p"),
     io:format("REST INIT~p"),
-    {ok, Req4, #st{resource_module = Module, resource_id = Id}}.
+    {ok,
+     Req4,
+     #st{resource_module = Module, resource_id = Id}}.
 
 
-resource_exists(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+resource_exists(#{bindings :=
+                      #{resource := Module, id := Id}} =
+                    Req,
+                State) ->
     M = c(Module),
     M = c(Module),
-    io:format("EXISTS: ~p dymamic: ~p~n",[Id,M:exists(Id)]),
+    io:format("EXISTS: ~p dymamic: ~p~n",
+              [Id, M:exists(Id)]),
     {M:exists(Id), Req, State};
     {M:exists(Id), Req, State};
-resource_exists(#{bindings := #{resource := Module}} = Req, State) -> io:format("resource ~p: no-id~n",[Module]), {true, Req, State};
-resource_exists(#{bindings := #{id := _}} = Req, State) -> io:format("EXISTS id: true~n"), {true, Req, State}.
+resource_exists(#{bindings := #{resource := Module}} =
+                    Req,
+                State) ->
+    io:format("resource ~p: no-id~n", [Module]),
+    {true, Req, State};
+resource_exists(#{bindings := #{id := _}} = Req,
+                State) ->
+    io:format("EXISTS id: true~n"),
+    {true, Req, State}.
 
 
-allowed_methods(#{bindings := #{resource := _}} = Req, State) -> {[<<"GET">>, <<"POST">>], Req, State};
-allowed_methods(#{bindings := #{resource := _, id := _}} = Req, State) -> {[<<"GET">>, <<"PUT">>, <<"DELETE">>], Req, State}.
+allowed_methods(#{bindings := #{resource := _}} = Req,
+                State) ->
+    {[<<"GET">>, <<"POST">>], Req, State};
+allowed_methods(#{bindings :=
+                      #{resource := _, id := _}} =
+                    Req,
+                State) ->
+    {[<<"GET">>, <<"PUT">>, <<"DELETE">>], Req, State}.
 
 
-content_types_provided(#{bindings := #{resource := Module}} = Req, State) ->
+content_types_provided(#{bindings :=
+                             #{resource := Module}} =
+                           Req,
+                       State) ->
     {case erlang:function_exported(c(Module), to_html, 1) of
     {case erlang:function_exported(c(Module), to_html, 1) of
          false -> [{<<"application/json">>, to_json}];
          false -> [{<<"application/json">>, to_json}];
-         true  -> [{<<"text/html">>, to_html}, {<<"application/json">>, to_json}] end,
-     Req, State}.
+         true ->
+             [{<<"text/html">>, to_html},
+              {<<"application/json">>, to_json}]
+     end,
+     Req,
+     State}.
 
 
-to_html(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+to_html(#{bindings := #{resource := Module, id := Id}} =
+            Req,
+        State) ->
     M = c(Module),
     M = c(Module),
     Body = case Id of
     Body = case Id of
-               undefined -> [M:to_html(Resource) || Resource <- M:get()];
-               _ -> M:to_html(M:get(Id)) end,
-    Html = case erlang:function_exported(M, html_layout, 2) of
-               true  -> M:html_layout(Req, Body);
-               false -> default_html_layout(Body) end,
+               undefined ->
+                   [M:to_html(Resource) || Resource <- M:get()];
+               _ -> M:to_html(M:get(Id))
+           end,
+    Html = case erlang:function_exported(M, html_layout, 2)
+               of
+               true -> M:html_layout(Req, Body);
+               false -> default_html_layout(Body)
+           end,
     {Html, Req, State}.
     {Html, Req, State}.
 
 
-default_html_layout(Body) -> [<<"<html><body>">>, Body, <<"</body></html>">>].
+default_html_layout(Body) ->
+    [<<"<html><body>">>, Body, <<"</body></html>">>].
 
 
-to_json(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-    io:format("~p ~p ~p~n",[?FUNCTION_NAME,Module,Id]),
+to_json(#{bindings := #{resource := Module, id := Id}} =
+            Req,
+        State) ->
+    io:format("~p ~p ~p~n", [?FUNCTION_NAME, Module, Id]),
     M = c(Module),
     M = c(Module),
     Struct = case Id of
     Struct = case Id of
-                 undefined -> [{M, [ M:to_json(Resource) || Resource <- M:get() ] } ];
-                 _         -> M:to_json(M:get(Id)) end,
-    {iolist_to_binary(?REST_JSON:encode(Struct)), Req, State};
-
-to_json(#{bindings := #{resource := Module}} = Req, State) ->
-    io:format("~p ~p~n",[?FUNCTION_NAME,Module]),
+                 undefined ->
+                     [{M, [M:to_json(Resource) || Resource <- M:get()]}];
+                 _ -> M:to_json(M:get(Id))
+             end,
+    {iolist_to_binary((?REST_JSON):encode(Struct)),
+     Req,
+     State};
+to_json(#{bindings := #{resource := Module}} = Req,
+        State) ->
+    io:format("~p ~p~n", [?FUNCTION_NAME, Module]),
     M = c(Module),
     M = c(Module),
-    Struct = [{M, [ M:to_json(Resource) || Resource <- M:get() ] } ],
-    {iolist_to_binary(?REST_JSON:encode(Struct)), Req, State}.
-
+    Struct = [{M,
+               [M:to_json(Resource) || Resource <- M:get()]}],
+    {iolist_to_binary((?REST_JSON):encode(Struct)),
+     Req,
+     State}.
 
 
 content_types_accepted(Req, State) ->
 content_types_accepted(Req, State) ->
-  {[{<<"application/x-www-form-urlencoded">>, handle_urlencoded_data},
-    {<<"application/json">>, handle_json_data}], Req, State}.
-
-handle_urlencoded_data(#{bindings := #{resource := Module}} = Req0, State) ->
-    {ok, Data1, Req} = cowboy_req:read_urlencoded_body(Req0),
-    io:format("FORM: ~p, Data1: ~p~n",[Module,Data1]),
+    {[{<<"application/x-www-form-urlencoded">>,
+       handle_urlencoded_data},
+      {<<"application/json">>, handle_json_data}],
+     Req,
+     State}.
 
 
+handle_urlencoded_data(#{bindings :=
+                             #{resource := Module}} =
+                           Req0,
+                       State) ->
+    {ok, Data1, Req} =
+        cowboy_req:read_urlencoded_body(Req0),
+    io:format("FORM: ~p, Data1: ~p~n", [Module, Data1]),
     {handle_data(c(Module), [], Data1, Req), Req, State};
     {handle_data(c(Module), [], Data1, Req), Req, State};
-
-handle_urlencoded_data(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+handle_urlencoded_data(#{bindings :=
+                             #{resource := Module, id := Id}} =
+                           Req,
+                       State) ->
     {ok, Data, Req2} = cowboy_req:read_urlencoded_body(Req),
     {ok, Data, Req2} = cowboy_req:read_urlencoded_body(Req),
-    io:format("FORM: ~p~n",[Data]),
+    io:format("FORM: ~p~n", [Data]),
     {handle_data(c(Module), Id, Data, Req), Req2, State}.
     {handle_data(c(Module), Id, Data, Req), Req2, State}.
 
 
-handle_json_data(#{bindings := #{resource := Module}} = Req, State) ->
+handle_json_data(#{bindings := #{resource := Module}} =
+                     Req,
+                 State) ->
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
-    io:format("JSON: ~p~n",[Binary]),
-    Data = case ?REST_JSON:decode(Binary) of {struct, Struct} -> Struct; S -> S end,
+    io:format("JSON: ~p~n", [Binary]),
+    Data = case (?REST_JSON):decode(Binary) of
+               {struct, Struct} -> Struct;
+               S -> S
+           end,
     {handle_data(c(Module), [], Data, Req), Req2, State};
     {handle_data(c(Module), [], Data, Req), Req2, State};
-
-handle_json_data(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+handle_json_data(#{bindings :=
+                       #{resource := Module, id := Id}} =
+                     Req,
+                 State) ->
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
-    io:format("JSON: ~p~n",[Binary]),
-    Data = case ?REST_JSON:decode(Binary) of {struct, Struct} -> Struct; S -> S end,
+    io:format("JSON: ~p~n", [Binary]),
+    Data = case (?REST_JSON):decode(Binary) of
+               {struct, Struct} -> Struct;
+               S -> S
+           end,
     {handle_data(c(Module), Id, Data, Req), Req2, State}.
     {handle_data(c(Module), Id, Data, Req), Req2, State}.
 
 
 handle_data(Mod, Id, Data, Req) ->
 handle_data(Mod, Id, Data, Req) ->
-    io:format("handle_data(~p)~n",[{Mod,Id,Data,Req}]),
-    Valid = case erlang:function_exported(Mod, validate, 2) of
-                true  -> Mod:validate(Id, Data);
-                false -> default_validate(Mod, Id, Data, Req) end,
-    io:format("Valid ~p Id ~p~n",[Valid,Id]),
+    io:format("handle_data(~p)~n", [{Mod, Id, Data, Req}]),
+    Valid = case erlang:function_exported(Mod, validate, 2)
+                of
+                true -> Mod:validate(Id, Data);
+                false -> default_validate(Mod, Id, Data, Req)
+            end,
+    io:format("Valid ~p Id ~p~n", [Valid, Id]),
     case {Valid, Id} of
     case {Valid, Id} of
-        {false, _}         -> false;
-        {true,  []}              -> Mod:post(Data);
-        {true,  <<"undefined">>} -> Mod:post(Data);
-        {true,  _}         -> case erlang:function_exported(Mod, put, 2) of
-                                  true  -> Mod:put(Id, Data);
-                                  false -> default_put(Mod, Id, Data, Req) end
+        {false, _} -> false;
+        {true, []} -> Mod:post(Data);
+        {true, <<"undefined">>} -> Mod:post(Data);
+        {true, _} ->
+            case erlang:function_exported(Mod, put, 2) of
+                true -> Mod:put(Id, Data);
+                false -> default_put(Mod, Id, Data, Req)
+            end
     end.
     end.
 
 
-default_put(Mod, Id, Data, Req) when is_map(Data) -> default_put(Mod, Id, maps:to_list(Data), Req);
+default_put(Mod, Id, Data, Req) when is_map(Data) ->
+    default_put(Mod, Id, maps:to_list(Data), Req);
 default_put(Mod, Id, Data, Req) ->
 default_put(Mod, Id, Data, Req) ->
     NewRes = Mod:from_json(Data, Mod:get(Id)),
     NewRes = Mod:from_json(Data, Mod:get(Id)),
     NewId = proplists:get_value(id, Mod:to_json(NewRes)),
     NewId = proplists:get_value(id, Mod:to_json(NewRes)),
-    io:format("Id ~p NewId ~p~n",[Id,NewId]),
+    io:format("Id ~p NewId ~p~n", [Id, NewId]),
     case Id =/= NewId of
     case Id =/= NewId of
         true when Id =:= [] -> skip;
         true when Id =:= [] -> skip;
         true -> Mod:delete(Id);
         true -> Mod:delete(Id);
-        false -> true end,
+        false -> true
+    end,
     Mod:post(NewRes).
     Mod:post(NewRes).
 
 
-default_validate(Mod, Id, DataX, Req0) when is_map(DataX) -> default_validate(Mod, Id, maps:to_list(DataX), Req0);
+default_validate(Mod, Id, DataX, Req0)
+    when is_map(DataX) ->
+    default_validate(Mod, Id, maps:to_list(DataX), Req0);
 default_validate(Mod, Id, Data, Req0) ->
 default_validate(Mod, Id, Data, Req0) ->
-    Allowed = case erlang:function_exported(Mod, keys_allowed, 1) of
-      true  -> Mod:keys_allowed(proplists:get_keys(Data));
-      false -> true end,
-    validate_match(Mod, Id, Allowed, proplists:get_value(<<"id">>, Data)).
-
-validate_match(_Mod,  [], true, [])      -> false;
-validate_match( Mod,  [], true, NewId)   -> not Mod:exists(NewId);
-validate_match(_Mod, _Id, true, [])      -> true;
-validate_match(_Mod,  Id, true, Id)      -> true;
-validate_match( Mod, _Id, true, NewId)   -> not Mod:exists(NewId);
-validate_match(   _,         _,    _, _) -> false.
-
-delete_resource(#{bindings := #{resource := Module, id := []}} = Req, State) -> {[], Req, State};
-delete_resource(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-   M = c(Module),
-   io:format("DELETE: ~p ~p ~p~n",[M,Id,M:delete(Id)]),
-   {M:delete(Id), Req, State}.
-
-rest_module(Module) when is_binary(Module) -> rest_module(binary_to_list(Module));
+    Allowed = case erlang:function_exported(Mod,
+                                            keys_allowed,
+                                            1)
+                  of
+                  true -> Mod:keys_allowed(proplists:get_keys(Data));
+                  false -> true
+              end,
+    validate_match(Mod,
+                   Id,
+                   Allowed,
+                   proplists:get_value(<<"id">>, Data)).
+
+validate_match(_Mod, [], true, []) -> false;
+validate_match(Mod, [], true, NewId) ->
+    not Mod:exists(NewId);
+validate_match(_Mod, _Id, true, []) -> true;
+validate_match(_Mod, Id, true, Id) -> true;
+validate_match(Mod, _Id, true, NewId) ->
+    not Mod:exists(NewId);
+validate_match(_, _, _, _) -> false.
+
+delete_resource(#{bindings :=
+                      #{resource := Module, id := []}} =
+                    Req,
+                State) ->
+    {[], Req, State};
+delete_resource(#{bindings :=
+                      #{resource := Module, id := Id}} =
+                    Req,
+                State) ->
+    M = c(Module),
+    io:format("DELETE: ~p ~p ~p~n", [M, Id, M:delete(Id)]),
+    {M:delete(Id), Req, State}.
+
+rest_module(Module) when is_binary(Module) ->
+    rest_module(binary_to_list(Module));
 rest_module(Module) ->
 rest_module(Module) ->
     try M = list_to_existing_atom(Module),
     try M = list_to_existing_atom(Module),
         Info = proplists:get_value(attributes, M:module_info()),
         Info = proplists:get_value(attributes, M:module_info()),
-        true = lists:member(rest, proplists:get_value(behaviour, Info)),
+        true = lists:member(rest,
+                            proplists:get_value(behaviour, Info)),
         {ok, M}
         {ok, M}
-    catch error:Error -> {error, Error} end.
+    catch
+        error:Error -> {error, Error}
+    end.

+ 223 - 93
src/rest_kvs.erl

@@ -1,147 +1,277 @@
 -module(rest_kvs).
 -module(rest_kvs).
+
 -include_lib("kvs/include/kvs.hrl").
 -include_lib("kvs/include/kvs.hrl").
+
 -compile(export_all).
 -compile(export_all).
--export([exists/1, exists/2, new/1, get/1, delete/2, post/2, post/3]).
--export([init/2, resource_exists/2, allowed_methods/2, content_types_provided/2,
-         to_html/2, to_json/2, content_types_accepted/2, delete_resource/2,
-         handle_urlencoded_data/2, handle_json_data/2]).
+
+-export([exists/1,
+         exists/2,
+         new/1,
+         get/1,
+         delete/2,
+         post/2,
+         post/3]).
+
+-export([init/2,
+         resource_exists/2,
+         allowed_methods/2,
+         content_types_provided/2,
+         to_html/2,
+         to_json/2,
+         content_types_accepted/2,
+         delete_resource/2,
+         handle_urlencoded_data/2,
+         handle_json_data/2]).
 
 
 -ifndef(REST_JSON).
 -ifndef(REST_JSON).
--define(REST_JSON, (application:get_env(rest,json,jsone))).
+
+-define(REST_JSON,
+        application:get_env(rest, json, jsone)).
+
 -endif.
 -endif.
 
 
-c(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:uri(X);
+c(X) when is_tuple(X) ->
+    Module = hd(tuple_to_list(X)),
+    Module:uri(X);
 c(X) -> binary_to_list(X).
 c(X) -> binary_to_list(X).
 
 
 % kvs rest api
 % kvs rest api
 
 
-new(Type)          -> Type:new().
-exists(Mod)        -> {X,_} = kvs:get(writer,c(Mod)), X == ok.
-exists(Mod,Id)     -> {X,_} = kvs:get(c(Mod),c(Id)), X == ok.
-get(Mod)           -> kvs:all(Mod).
-get(Mod,Id)        -> {X,Y} = kvs:get(c(Mod),c(Id)), X == ok, Y.
-delete(Mod,Id)     -> kvs:delete(Mod,Id).
-post(Mod,Resource) when is_tuple(Resource) -> kvs:append(Mod,Resource).
-post(Type,Mod,Data)     when is_list(Data) -> post(Mod,Type:from_json(new(Type))).
+new(Type) -> Type:new().
+
+exists(Mod) ->
+    {X, _} = kvs:get(writer, c(Mod)),
+    X == ok.
+
+exists(Mod, Id) ->
+    {X, _} = kvs:get(c(Mod), c(Id)),
+    X == ok.
+
+get(Mod) -> kvs:all(Mod).
+
+get(Mod, Id) ->
+    {X, Y} = kvs:get(c(Mod), c(Id)),
+    X == ok,
+    Y.
+
+delete(Mod, Id) -> kvs:delete(Mod, Id).
+
+post(Mod, Resource) when is_tuple(Resource) ->
+    kvs:append(Mod, Resource).
+
+post(Type, Mod, Data) when is_list(Data) ->
+    post(Mod, Type:from_json(new(Type))).
 
 
 % cowboy rest api
 % cowboy rest api
 
 
-update_req(Req) -> #{ bindings := Bindings, path_info := List } = Req,
-   Req#{bindings => Bindings#{ resource => list_to_binary("/" ++
-      string:join(lists:map(fun (X) -> binary_to_list(X) end, List),"/")) }}.
+update_req(Req) ->
+    #{bindings := Bindings, path_info := List} = Req,
+    Req#{bindings =>
+             Bindings#{resource =>
+                           list_to_binary("/" ++
+                                              string:join(lists:map(fun (X) -> binary_to_list(X) end,
+                                                                    List),
+                                                          "/"))}}.
 
 
-init(#{bindings := #{id := Id}} = Req, State) -> {cowboy_rest, update_req(Req), State};
-init(Req, State) -> {cowboy_rest, update_req(Req), State}.
+init(#{bindings := #{id := Id}} = Req, State) ->
+    {cowboy_rest, update_req(Req), State};
+init(Req, State) ->
+    {cowboy_rest, update_req(Req), State}.
 
 
 parse_id(Id) ->
 parse_id(Id) ->
-  List = binary_to_list(Id),
-  Parsed = case string:tokens(List,",") of
-     [X] -> Id;
-       _ -> rest:parse(lists:concat(["{",List,"}"]))
-  end.
+    List = binary_to_list(Id),
+    Parsed = case string:tokens(List, ",") of
+                 [X] -> Id;
+                 _ -> rest:parse(lists:concat(["{", List, "}"]))
+             end.
 
 
-resource_exists(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-  {rest_kvs:exists(Module,parse_id(Id)), Req, State};
-resource_exists(#{bindings := #{resource := Module}} = Req, State) -> {rest_kvs:exists(Module), Req, State};
-resource_exists(#{bindings := #{id := _}} = Req, State) -> {true, Req, State}.
+resource_exists(#{bindings :=
+                      #{resource := Module, id := Id}} =
+                    Req,
+                State) ->
+    {rest_kvs:exists(Module, parse_id(Id)), Req, State};
+resource_exists(#{bindings := #{resource := Module}} =
+                    Req,
+                State) ->
+    {rest_kvs:exists(Module), Req, State};
+resource_exists(#{bindings := #{id := _}} = Req,
+                State) ->
+    {true, Req, State}.
 
 
-allowed_methods(#{bindings := #{resource := _}} = Req, State) -> {[<<"GET">>, <<"POST">>], Req, State};
-allowed_methods(#{bindings := #{resource := _, id := _}} = Req, State) -> {[<<"GET">>, <<"PUT">>, <<"DELETE">>], Req, State}.
+allowed_methods(#{bindings := #{resource := _}} = Req,
+                State) ->
+    {[<<"GET">>, <<"POST">>], Req, State};
+allowed_methods(#{bindings :=
+                      #{resource := _, id := _}} =
+                    Req,
+                State) ->
+    {[<<"GET">>, <<"PUT">>, <<"DELETE">>], Req, State}.
 
 
-delete_resource(#{bindings := #{resource := Module, id := []}} = Req, State) -> {[], Req, State};
-delete_resource(#{bindings := #{resource := Module, id := Id}} = Req, State) -> {rest_kvs:delete(Module,Id), Req, State}.
+delete_resource(#{bindings :=
+                      #{resource := Module, id := []}} =
+                    Req,
+                State) ->
+    {[], Req, State};
+delete_resource(#{bindings :=
+                      #{resource := Module, id := Id}} =
+                    Req,
+                State) ->
+    {rest_kvs:delete(Module, Id), Req, State}.
 
 
-content_types_provided(#{bindings := #{resource := Module}} = Req, State) ->
-    {case application:get_env(rest,html,false) of
+content_types_provided(#{bindings :=
+                             #{resource := Module}} =
+                           Req,
+                       State) ->
+    {case application:get_env(rest, html, false) of
          false -> [{<<"application/json">>, to_json}];
          false -> [{<<"application/json">>, to_json}];
-         true  -> [{<<"text/html">>, to_html},
-                   {<<"application/json">>, to_json}] end, Req, State}.
+         true ->
+             [{<<"text/html">>, to_html},
+              {<<"application/json">>, to_json}]
+     end,
+     Req,
+     State}.
 
 
 % TODO: HTML render broken!
 % TODO: HTML render broken!
 
 
-to_html(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-%    Body = case Id of
-%               Id when Id==[];Id==undefined -> [ rest_kvs:to_html(Module, Resource) || Resource <- rest_kvs:get(Module,Id) ];
-%               _ -> rest_kvs:to_html(rest_kvs:get(Module,Id)) end,
-%    Html = case application:get_env(rest,html_layout,false) of
-%               true  -> rest_kvs:html_layout(Module, Req, Body);
-%               false -> default_html_layout(Body) end,
+to_html(#{bindings := #{resource := Module, id := Id}} =
+            Req,
+        State) ->
+    %    Body = case Id of
+    %               Id when Id==[];Id==undefined -> [ rest_kvs:to_html(Module, Resource) || Resource <- rest_kvs:get(Module,Id) ];
+    %               _ -> rest_kvs:to_html(rest_kvs:get(Module,Id)) end,
+    %    Html = case application:get_env(rest,html_layout,false) of
+    %               true  -> rest_kvs:html_layout(Module, Req, Body);
+    %               false -> default_html_layout(Body) end,
     {<<>>, Req, State}.
     {<<>>, Req, State}.
 
 
-default_html_layout(Body) -> [<<"<html><body>">>, Body, <<"</body></html>">>].
+default_html_layout(Body) ->
+    [<<"<html><body>">>, Body, <<"</body></html>">>].
 
 
 % JSON seems fine
 % JSON seems fine
 
 
-to_json(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
-    {ok,Resource} = kvs:get(c(Module),c(parse_id(Id))),
-    Type = element(1,Resource),
-    {iolist_to_binary([?REST_JSON:encode(rest:binarize(Type:to_json(Resource))),"\n"]), Req, State};
-to_json(#{bindings := #{resource := Module}} = Req, State) ->
-    Fold = [ begin M = element(1,Resource), rest:binarize(M:to_json(Resource)) end || Resource <- kvs:all(c(Module))],
-    {iolist_to_binary([?REST_JSON:encode([{Module,Fold}]),"\n"]), Req, State}.
+to_json(#{bindings := #{resource := Module, id := Id}} =
+            Req,
+        State) ->
+    {ok, Resource} = kvs:get(c(Module), c(parse_id(Id))),
+    Type = element(1, Resource),
+    {iolist_to_binary([(?REST_JSON):encode(rest:binarize(Type:to_json(Resource))),
+                       "\n"]),
+     Req,
+     State};
+to_json(#{bindings := #{resource := Module}} = Req,
+        State) ->
+    Fold = [begin
+                M = element(1, Resource),
+                rest:binarize(M:to_json(Resource))
+            end
+            || Resource <- kvs:all(c(Module))],
+    {iolist_to_binary([(?REST_JSON):encode([{Module,
+                                             Fold}]),
+                       "\n"]),
+     Req,
+     State}.
 
 
 content_types_accepted(Req, State) ->
 content_types_accepted(Req, State) ->
-  {[{<<"application/x-www-form-urlencoded">>, handle_urlencoded_data},
-    {<<"application/json">>, handle_json_data}], Req, State}.
+    {[{<<"application/x-www-form-urlencoded">>,
+       handle_urlencoded_data},
+      {<<"application/json">>, handle_json_data}],
+     Req,
+     State}.
 
 
-handle_urlencoded_data(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+handle_urlencoded_data(#{bindings :=
+                             #{resource := Module, id := Id}} =
+                           Req,
+                       State) ->
     {ok, Data, Req2} = cowboy_req:read_urlencoded_body(Req),
     {ok, Data, Req2} = cowboy_req:read_urlencoded_body(Req),
-    io:format("FORM: ~p~n",[Data]),
+    io:format("FORM: ~p~n", [Data]),
     {handle_data(Module, Id, Data, Req), Req2, State};
     {handle_data(Module, Id, Data, Req), Req2, State};
-
-handle_urlencoded_data(#{bindings := #{resource := Module}} = Req0, State) ->
-    {ok, Data1, Req} = cowboy_req:read_urlencoded_body(Req0),
-    io:format("FORM: ~p, Data1: ~p~n",[Module,Data1]),
+handle_urlencoded_data(#{bindings :=
+                             #{resource := Module}} =
+                           Req0,
+                       State) ->
+    {ok, Data1, Req} =
+        cowboy_req:read_urlencoded_body(Req0),
+    io:format("FORM: ~p, Data1: ~p~n", [Module, Data1]),
     {handle_data(Module, [], Data1, Req), Req, State}.
     {handle_data(Module, [], Data1, Req), Req, State}.
 
 
-handle_json_data(#{bindings := #{resource := Module, id := Id}} = Req, State) ->
+handle_json_data(#{bindings :=
+                       #{resource := Module, id := Id}} =
+                     Req,
+                 State) ->
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
-    io:format("JSON: ~p~n",[Binary]),
-    Data = case ?REST_JSON:decode(Binary) of {struct, Struct} -> Struct; S -> S end,
+    io:format("JSON: ~p~n", [Binary]),
+    Data = case (?REST_JSON):decode(Binary) of
+               {struct, Struct} -> Struct;
+               S -> S
+           end,
     {handle_data(Module, Id, Data, Req), Req2, State};
     {handle_data(Module, Id, Data, Req), Req2, State};
-
-handle_json_data(#{bindings := #{resource := Module}} = Req, State) ->
+handle_json_data(#{bindings := #{resource := Module}} =
+                     Req,
+                 State) ->
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
     {ok, Binary, Req2} = cowboy_req:read_body(Req),
-    io:format("JSON: ~p~n",[Binary]),
-    Data = case ?REST_JSON:decode(Binary) of {struct, Struct} -> Struct; S -> S end,
+    io:format("JSON: ~p~n", [Binary]),
+    Data = case (?REST_JSON):decode(Binary) of
+               {struct, Struct} -> Struct;
+               S -> S
+           end,
     {handle_data(Module, [], Data, Req), Req2, State}.
     {handle_data(Module, [], Data, Req), Req2, State}.
 
 
 handle_data(Mod, Id, Data, Req) ->
 handle_data(Mod, Id, Data, Req) ->
     Type = proplists:get_value(<<"rec">>, Data),
     Type = proplists:get_value(<<"rec">>, Data),
-    Valid = case application:get_env(rest,validate,false) of
-                true  -> rest_kvs:validate(Mod,Id, Data);
-                false -> default_validate(Mod, Id, Data, Req) end,
+    Valid = case application:get_env(rest, validate, false)
+                of
+                true -> rest_kvs:validate(Mod, Id, Data);
+                false -> default_validate(Mod, Id, Data, Req)
+            end,
     case {Valid, Id} of
     case {Valid, Id} of
-         {false, _}         -> false;
-         {true,  <<"undefined">>} -> rest_kvs:post(Type,Mod,Data);
-         {true,  _}         -> case application:get_env(rest,custom_put,false) of
-                                   true  -> Type:put(Mod, Id, Data);
-                                   false -> default_put(Type, Mod, Id, Data, Req) end
+        {false, _} -> false;
+        {true, <<"undefined">>} ->
+            rest_kvs:post(Type, Mod, Data);
+        {true, _} ->
+            case application:get_env(rest, custom_put, false) of
+                true -> Type:put(Mod, Id, Data);
+                false -> default_put(Type, Mod, Id, Data, Req)
+            end
     end.
     end.
 
 
-validate(_,_,_) -> true.
-keys_allowed(_,_) -> true.
+validate(_, _, _) -> true.
+
+keys_allowed(_, _) -> true.
 
 
-default_put(Type, Mod, Id, Data, Req) when is_map(Data) -> default_put(Type, Mod, Id, maps:to_list(Data), Req);
+default_put(Type, Mod, Id, Data, Req)
+    when is_map(Data) ->
+    default_put(Type, Mod, Id, maps:to_list(Data), Req);
 default_put(Type, Mod, Id, Data, Req) ->
 default_put(Type, Mod, Id, Data, Req) ->
-    NewRes = Type:from_json(Data, rest_kvs:get(Mod,Id)),
+    NewRes = Type:from_json(Data, rest_kvs:get(Mod, Id)),
     NewId = proplists:get_value(id, Type:to_json(NewRes)),
     NewId = proplists:get_value(id, Type:to_json(NewRes)),
     case Id =/= NewId of
     case Id =/= NewId of
-        true -> rest_kvs:delete(Mod,Id);
-        false -> true end,
-    rest_kvs:post(Type,Mod,NewRes).
+        true -> rest_kvs:delete(Mod, Id);
+        false -> true
+    end,
+    rest_kvs:post(Type, Mod, NewRes).
 
 
-default_validate(Mod, Id, DataX, Req0) when is_map(DataX) -> default_validate(Mod, Id, maps:to_list(DataX), Req0);
+default_validate(Mod, Id, DataX, Req0)
+    when is_map(DataX) ->
+    default_validate(Mod, Id, maps:to_list(DataX), Req0);
 default_validate(Mod, Id, Data, Req0) ->
 default_validate(Mod, Id, Data, Req0) ->
-    Allowed = case application:get_env(rest, keys_allowed, false) of
-      true  -> rest_kvs:keys_allowed(c(Mod),proplists:get_keys(Data));
-      false -> true end,
-    validate_match(Mod, Id, Allowed, proplists:get_value(<<"id">>, Data)).
-
-validate_match(_Mod,  [], true, [])      -> false;
-validate_match( Mod,  [], true, NewId)   -> not rest_kvs:exists(Mod,NewId);
-validate_match(_Mod, _Id, true, [])      -> true;
-validate_match(_Mod,  Id, true, Id)      -> true;
-validate_match( Mod, _Id, true, NewId)   -> not rest_kvs:exists(Mod,NewId);
-validate_match(   _,         _,    _, _) -> false.
+    Allowed = case application:get_env(rest,
+                                       keys_allowed,
+                                       false)
+                  of
+                  true ->
+                      rest_kvs:keys_allowed(c(Mod), proplists:get_keys(Data));
+                  false -> true
+              end,
+    validate_match(Mod,
+                   Id,
+                   Allowed,
+                   proplists:get_value(<<"id">>, Data)).
 
 
+validate_match(_Mod, [], true, []) -> false;
+validate_match(Mod, [], true, NewId) ->
+    not rest_kvs:exists(Mod, NewId);
+validate_match(_Mod, _Id, true, []) -> true;
+validate_match(_Mod, Id, true, Id) -> true;
+validate_match(Mod, _Id, true, NewId) ->
+    not rest_kvs:exists(Mod, NewId);
+validate_match(_, _, _, _) -> false.