Advertisement
Guest User

Untitled

a guest
Jan 13th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 10.63 KB | None | 0 0
  1. %% @doc REST database update handler.
  2. -module(db_update_handler).
  3.  
  4. %% Webmachine API
  5. -export([
  6.          init/3,
  7.          rest_init/2,
  8.          allowed_methods/2,
  9.          content_types_provided/2,
  10.          content_types_accepted/2,
  11.          resource_exists/2,
  12.          delete_resource/2
  13.         ]).
  14.  
  15. -export([
  16.          db_to_json/2,
  17.          db_to_text/2,
  18.          text_to_db/2
  19.         ]).
  20.  
  21. -record(state, {op}).
  22.  
  23. init(_, _Req, _Opts) ->
  24.     {upgrade, protocol, cowboy_rest}.
  25.  
  26. rest_init(Req, Opts) ->
  27.     [Op | _] = Opts,
  28.     State = #state{op=Op},
  29.     {ok, Req, State}.
  30.  
  31. allowed_methods(Req, State) ->
  32.     Methods = [<<"GET">>, <<"POST">>, <<"DELETE">>],
  33.     {Methods, Req, State}.
  34.  
  35. content_types_provided(Req, State) ->
  36.     {[
  37.       {<<"application/json">>, db_to_json},
  38.       {<<"text/plain">>, db_to_text}
  39.      ], Req, State}.
  40.  
  41. content_types_accepted(Req, State) ->
  42.     {[
  43.       {<<"text/plain">>, text_to_db},
  44.  %     {<<"application/json">>, text_to_db},
  45.       {<<"application/x-www-form-urlencoded">>, text_to_db}
  46.      ], Req, State}.
  47.  
  48. db_to_json(Req, #state{op=Op} = State) ->
  49.     {Body, Req1, State1} = case Op of
  50.         list ->
  51.             get_record_list(Req, State);
  52.         get ->
  53.             get_one_record(Req, State);
  54.         help ->
  55.             get_help(Req, State)
  56.     end,
  57.     {Body, Req1, State1}.
  58.  
  59. db_to_text(Req, #state{op=Op} = State) ->
  60.     {Body, Req1, State1} = case Op of
  61.         list ->
  62.             get_record_list_text(Req, State);
  63.         get ->
  64.             get_one_record_text(Req, State);
  65.         help ->
  66.             get_help_text(Req, State)
  67.     end,
  68.     {Body, Req1, State1}.
  69.  
  70. text_to_db(Req, #state{op=Op} = State) ->
  71.     {Body, Req1, State1} = case Op of
  72.         create ->
  73.             create_record_to_json(Req, State);
  74.         delete ->
  75.             delete_record_to_json(Req, State);
  76.         update ->
  77.             update_record_to_json(Req, State)
  78.     end,
  79.     {Body, Req1, State1}.
  80.  
  81. resource_exists(Req, State) ->
  82.     {Method, Req0} = cowboy_req:method(Req),
  83.     case Method of
  84.         <<"DELETE">> ->
  85.             {RecordId, _} = cowboy_req:binding(record_id, Req0),           
  86.             RecordId1 = binary_to_list(RecordId),
  87.             {ok, Recordfilename} = application:get_env(
  88.                  rest_update, records_file_name),
  89.             {ok, _} = dets:open_file(
  90.                 records_db, [{file, Recordfilename}, {type, set}]),
  91.             Records = dets:lookup(records_db, RecordId1),
  92.             ok = dets:close(records_db),
  93.             Response = case Records of
  94.                 [_] ->
  95.                     {true, Req, State};
  96.                 _ ->
  97.                     {false, Req, State}
  98.             end,
  99.             Response;
  100.         _ ->
  101.             {true, Req, State}
  102.     end.
  103.  
  104. delete_resource(Req, State) ->
  105.     {RecordId, _} = cowboy_req:binding(record_id, Req),
  106.     RecordId1 = binary_to_list(RecordId),
  107.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  108.     {ok, _} = dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  109.     Result = dets:delete(records_db, RecordId1),
  110.     ok = dets:close(records_db),
  111.     Response = case Result of
  112.         ok ->
  113.             true;
  114.         {error, _Reason} ->
  115.             false
  116.     end,
  117.     {Response, Req, State}.
  118.  
  119. get_record_list(Req, State) ->
  120.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  121.     dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  122.     F = fun (Item, Acc) -> Acc1 = [Item | Acc], Acc1 end,
  123.     Items = dets:foldl(F, [], records_db),
  124.     dets:close(records_db),
  125.     Items1 = lists:sort(Items),
  126.     Body = "
  127. {
  128.    \"list\": \"~p\",
  129. }",
  130.     Body1 = io_lib:format(Body, [Items1]),
  131.     {Body1, Req, State}.
  132.  
  133. get_record_list_text(Req, State) ->
  134.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  135.     dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  136.     F1 = fun (Item, Acc) -> Acc1 = [Item | Acc], Acc1 end,
  137.     Items = dets:foldl(F1, [], records_db),
  138.     dets:close(records_db),
  139.     F2 = fun ({Id, Rec}, Acc) ->
  140.                  Val = io_lib:format("- ~s: ~s~n", [Id, Rec]),
  141.                  [Val | Acc]
  142.          end,
  143.     Items1 = lists:foldl(F2, [], Items),
  144.     Items2 = lists:sort(Items1),
  145.     Items3 = lists:flatten(lists:concat(Items2)),
  146.     Body = "
  147. list: ~p,
  148. ",
  149.     Body1 = io_lib:format(Body, [Items3]),
  150.     {Body1, Req, State}.
  151.  
  152. get_one_record(Req, State) ->
  153.     {RecordId, _} = cowboy_req:binding(record_id, Req),
  154.     RecordId1 = binary_to_list(RecordId),
  155.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  156.     {ok, _} = dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  157.     Records = dets:lookup(records_db, RecordId1),
  158.     ok = dets:close(records_db),
  159.     Body = case Records of
  160.         [{RecordId2, Data}] ->
  161.             io_lib:format("{\"id\": \"~s\", \"record\": \"~s\"}",
  162.                           [RecordId2, binary_to_list(Data)]);
  163.         [] ->
  164.             io_lib:format("{\"not_found\": \"record ~p not found\"}",
  165.                           [RecordId1]);
  166.         _ ->
  167.             io_lib:format("{\"extra_records\": \"extra records for ~p\"}",
  168.                           [RecordId1])
  169.     end,
  170.     {list_to_binary(Body), Req, State}.
  171.  
  172. get_one_record_text(Req, State) ->
  173.     {RecordId, _} = cowboy_req:binding(record_id, Req),
  174.     RecordId1 = binary_to_list(RecordId),
  175.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  176.     {ok, _} = dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  177.     Records = dets:lookup(records_db, RecordId1),
  178.     ok = dets:close(records_db),
  179.     Body = case Records of
  180.         [{RecordId2, Data}] ->
  181.             io_lib:format("id: \"~s\", record: \"~s\"",
  182.                           [RecordId2, binary_to_list(Data)]);
  183.         [] ->
  184.             io_lib:format("{not_found: record ~p not found",
  185.                           [RecordId1]);
  186.         _ ->
  187.             io_lib:format("{extra_records: extra records for ~p",
  188.                           [RecordId1])
  189.     end,
  190.     {list_to_binary(Body), Req, State}.
  191.  
  192. create_record_to_json(Req, State) ->
  193.     {ok, [{<<"content">>, Content}], Req1} = cowboy_req:body_qs(Req,[]),
  194.     RecordId = generate_id(),
  195.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  196.     {ok, _} = dets:open_file(records_db, [{file, Recordfilename}, {type, set}]),
  197.     ok = dets:insert(records_db, {RecordId, Content}),
  198.     ok = dets:sync(records_db),
  199.     ok = dets:close(records_db),
  200.     {Method, Req2} = cowboy_req:method(Req1),
  201.     case Method of
  202.         <<"POST">> ->
  203.             Response = io_lib:format("/get/~s", [RecordId]),
  204.             {{true, list_to_binary(Response)}, Req2, State};
  205.         _ ->
  206.             {true, Req2, State}
  207.     end.
  208.  
  209. update_record_to_json(Req, State) ->
  210.     {Method, Req0} = cowboy_req:method(Req),
  211.     case Method of
  212.         <<"POST">> ->
  213.             {RecId, _} = cowboy_req:binding(record_id, Req0),          
  214.             RecId1 = binary_to_list(RecId),
  215.             {ok, [{<<"content">>, NewContent}], Req1} =
  216.                 cowboy_req:body_qs(Req,[]),
  217.             {ok, Recordfilename} = application:get_env(
  218.                 rest_update, records_file_name),
  219.             {ok, _} = dets:open_file(
  220.                 records_db, [{file, Recordfilename}, {type, set}]),
  221.             DBResponse = dets:lookup(records_db, RecId1),
  222.             Result = case DBResponse of
  223.                 [_] ->
  224.                     ok = dets:insert(records_db, {RecId1, NewContent}),
  225.                     ok = dets:sync(records_db),
  226.                     Response = io_lib:format("/get/~s", [RecId1]),
  227.                     Response1 = list_to_binary(Response),
  228.                     {{true, Response1}, Req1, State};
  229.                 [] ->
  230.                     {true, Req1, State}
  231.             end,
  232.             ok = dets:close(records_db),
  233.             Result;
  234.         _ ->
  235.             {true, Req, State}
  236.     end.
  237.  
  238. delete_record_to_json(Req, State) ->
  239.     {Method, Req0} = cowboy_req:method(Req),
  240.     case Method of
  241.         <<"POST">> ->
  242.             {RecId, _} = cowboy_req:binding(record_id, Req0),          
  243.             RecId1 = binary_to_list(RecId),
  244.             {ok, Recordfilename} = application:get_env(
  245.                 rest_update, records_file_name),
  246.             {ok, _} = dets:open_file(
  247.                 records_db, [{file, Recordfilename}, {type, set}]),
  248.             DBResponse = dets:lookup(records_db, RecId1),
  249.             Result = case DBResponse of
  250.                 [_] ->
  251.                     ok = dets:delete(records_db, RecId1),
  252.                     ok = dets:sync(records_db),
  253.                     Response = io_lib:format("/delete/~s", [RecId1]),
  254.                     Response1 = list_to_binary(Response),
  255.                     {{true, Response1}, Req, State};
  256.                 [] ->
  257.                     {true, Req, State}
  258.             end,
  259.             ok = dets:close(records_db),
  260.             Result;
  261.         _ ->
  262.             {true, Req, State}
  263.     end.
  264.  
  265. get_help(Req, State) ->
  266.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  267.     {ok, Statefilename} = application:get_env(rest_update, state_file_name),
  268.     Body = "{
  269.    \"/list\": \"return a list of record IDs\",
  270.    \"/get/ID\": \"retrieve a record by its ID\",
  271.    \"/create\": \"create a new record; return its ID\",
  272.    \"/update/ID\": \"update an existing record\",
  273.    \"/delete/ID\": \"udelete an existing record\",
  274.    \"records_file_name\": \"~s\",
  275.    \"state_file_name\": \"~s\",
  276. }",
  277.     Body1 = io_lib:format(Body, [Recordfilename, Statefilename]),
  278.     {Body1, Req, State}.
  279.  
  280. get_help_text(Req, State) ->
  281.     {ok, Recordfilename} = application:get_env(rest_update, records_file_name),
  282.     {ok, Statefilename} = application:get_env(rest_update, state_file_name),
  283.     Body = "
  284. - list: return a list of record IDs~n
  285. - get:  retrieve a record by its ID~n
  286. - create: create a new record; return its ID~n
  287. - update:  update an existing record~n
  288. - records_file_name: ~s~n
  289. - state_file_name: ~s~n
  290. ",
  291.     Body1 = io_lib:format(Body, [Recordfilename, Statefilename]),
  292.     {Body1, Req, State}.
  293.  
  294. generate_id() ->
  295.     {ok, Statefilename} = application:get_env(rest_update, state_file_name),
  296.     dets:open_file(state_db, [{file, Statefilename}, {type, set}]),
  297.     Records = dets:lookup(state_db, current_id),
  298.     Response = case Records of
  299.         [{current_id, CurrentId}] ->
  300.             NextId = CurrentId + 1,
  301.             %    CurrentId, NextId]),
  302.             dets:insert(state_db, {current_id, NextId}),
  303.             Id = lists:flatten(io_lib:format("id_~4..0B", [CurrentId])),
  304.             Id;
  305.         [] ->
  306.             error
  307.     end,
  308.     dets:close(state_db),
  309.     Response.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement