PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/https/https_store.erl

http://github.com/basho/mochiweb
Erlang | 146 lines | 100 code | 14 blank | 32 comment | 0 complexity | 521193db19fe9785003a035b1505f91e MD5 | raw file
Possible License(s): MIT
  1. %% Trivial web storage app. It's available over both HTTP (port 8442)
  2. %% and HTTPS (port 8443). You use a PUT to store items, a GET to
  3. %% retrieve them and DELETE to delete them. The HTTP POST method is
  4. %% invalid for this application. Example (using HTTPS transport):
  5. %%
  6. %% $ curl -k --verbose https://localhost:8443/flintstones
  7. %% ...
  8. %% 404 Not Found
  9. %% ...
  10. %% $ echo -e "Fred\nWilma\nBarney" |
  11. %% curl -k --verbose https://localhost:8443/flintstones \
  12. %% -X PUT -H "Content-Type: text/plain" --data-binary @-
  13. %% ...
  14. %% 201 Created
  15. %% ...
  16. %% $ curl -k --verbose https://localhost:8443/flintstones
  17. %% ...
  18. %% Fred
  19. %% Wilma
  20. %% Barney
  21. %% ...
  22. %% $ curl -k --verbose https://localhost:8443/flintstones -X DELETE
  23. %% ...
  24. %% 200 OK
  25. %% ...
  26. %% $ curl -k --verbose https://localhost:8443/flintstones
  27. %% ...
  28. %% 404 Not Found
  29. %% ...
  30. %%
  31. %% All submitted data is stored in memory (in an ets table). Could be
  32. %% useful for ad-hoc testing.
  33. -module(https_store).
  34. -export([start/0,
  35. stop/0,
  36. dispatch/1,
  37. loop/1
  38. ]).
  39. -define(HTTP_OPTS, [
  40. {loop, {?MODULE, dispatch}},
  41. {port, 8442},
  42. {name, http_8442}
  43. ]).
  44. -define(HTTPS_OPTS, [
  45. {loop, {?MODULE, dispatch}},
  46. {port, 8443},
  47. {name, https_8443},
  48. {ssl, true},
  49. {ssl_opts, [
  50. {certfile, "server_cert.pem"},
  51. {keyfile, "server_key.pem"}]}
  52. ]).
  53. -record(sd, {http, https}).
  54. -record(resource, {type, data}).
  55. start() ->
  56. {ok, Http} = mochiweb_http:start(?HTTP_OPTS),
  57. {ok, Https} = mochiweb_http:start(?HTTPS_OPTS),
  58. SD = #sd{http=Http, https=Https},
  59. Pid = spawn_link(fun() ->
  60. ets:new(?MODULE, [named_table]),
  61. loop(SD)
  62. end),
  63. register(http_store, Pid),
  64. ok.
  65. stop() ->
  66. http_store ! stop,
  67. ok.
  68. dispatch(Req) ->
  69. case Req:get(method) of
  70. 'GET' ->
  71. get_resource(Req);
  72. 'PUT' ->
  73. put_resource(Req);
  74. 'DELETE' ->
  75. delete_resource(Req);
  76. _ ->
  77. Headers = [{"Allow", "GET,PUT,DELETE"}],
  78. Req:respond({405, Headers, "405 Method Not Allowed\r\n"})
  79. end.
  80. get_resource(Req) ->
  81. Path = Req:get(path),
  82. case ets:lookup(?MODULE, Path) of
  83. [{Path, #resource{type=Type, data=Data}}] ->
  84. Req:ok({Type, Data});
  85. [] ->
  86. Req:respond({404, [], "404 Not Found\r\n"})
  87. end.
  88. put_resource(Req) ->
  89. ContentType = case Req:get_header_value("Content-Type") of
  90. undefined ->
  91. "application/octet-stream";
  92. S ->
  93. S
  94. end,
  95. Resource = #resource{type=ContentType, data=Req:recv_body()},
  96. http_store ! {self(), {put, Req:get(path), Resource}},
  97. Pid = whereis(http_store),
  98. receive
  99. {Pid, created} ->
  100. Req:respond({201, [], "201 Created\r\n"});
  101. {Pid, updated} ->
  102. Req:respond({200, [], "200 OK\r\n"})
  103. end.
  104. delete_resource(Req) ->
  105. http_store ! {self(), {delete, Req:get(path)}},
  106. Pid = whereis(http_store),
  107. receive
  108. {Pid, ok} ->
  109. Req:respond({200, [], "200 OK\r\n"})
  110. end.
  111. loop(#sd{http=Http, https=Https} = SD) ->
  112. receive
  113. stop ->
  114. ok = mochiweb_http:stop(Http),
  115. ok = mochiweb_http:stop(Https),
  116. exit(normal);
  117. {From, {put, Key, Val}} ->
  118. Exists = ets:member(?MODULE, Key),
  119. ets:insert(?MODULE, {Key, Val}),
  120. case Exists of
  121. true ->
  122. From ! {self(), updated};
  123. false ->
  124. From ! {self(), created}
  125. end;
  126. {From, {delete, Key}} ->
  127. ets:delete(?MODULE, Key),
  128. From ! {self(), ok};
  129. _ ->
  130. ignore
  131. end,
  132. ?MODULE:loop(SD).