diff options
Diffstat (limited to 'deps/mochiweb/examples/https/https_store.erl')
-rw-r--r-- | deps/mochiweb/examples/https/https_store.erl | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/deps/mochiweb/examples/https/https_store.erl b/deps/mochiweb/examples/https/https_store.erl new file mode 100644 index 00000000..959cc00c --- /dev/null +++ b/deps/mochiweb/examples/https/https_store.erl @@ -0,0 +1,146 @@ + +%% Trivial web storage app. It's available over both HTTP (port 8442) +%% and HTTPS (port 8443). You use a PUT to store items, a GET to +%% retrieve them and DELETE to delete them. The HTTP POST method is +%% invalid for this application. Example (using HTTPS transport): +%% +%% $ curl -k --verbose https://localhost:8443/flintstones +%% ... +%% 404 Not Found +%% ... +%% $ echo -e "Fred\nWilma\nBarney" | +%% curl -k --verbose https://localhost:8443/flintstones \ +%% -X PUT -H "Content-Type: text/plain" --data-binary @- +%% ... +%% 201 Created +%% ... +%% $ curl -k --verbose https://localhost:8443/flintstones +%% ... +%% Fred +%% Wilma +%% Barney +%% ... +%% $ curl -k --verbose https://localhost:8443/flintstones -X DELETE +%% ... +%% 200 OK +%% ... +%% $ curl -k --verbose https://localhost:8443/flintstones +%% ... +%% 404 Not Found +%% ... +%% +%% All submitted data is stored in memory (in an ets table). Could be +%% useful for ad-hoc testing. + +-module(https_store). + +-export([start/0, + stop/0, + dispatch/1, + loop/1 + ]). + +-define(HTTP_OPTS, [ + {loop, {?MODULE, dispatch}}, + {port, 8442}, + {name, http_8442} + ]). + +-define(HTTPS_OPTS, [ + {loop, {?MODULE, dispatch}}, + {port, 8443}, + {name, https_8443}, + {ssl, true}, + {ssl_opts, [ + {certfile, "server_cert.pem"}, + {keyfile, "server_key.pem"}]} + ]). + +-record(sd, {http, https}). +-record(resource, {type, data}). + +start() -> + {ok, Http} = mochiweb_http:start(?HTTP_OPTS), + {ok, Https} = mochiweb_http:start(?HTTPS_OPTS), + SD = #sd{http=Http, https=Https}, + Pid = spawn_link(fun() -> + ets:new(?MODULE, [named_table]), + loop(SD) + end), + register(http_store, Pid), + ok. + +stop() -> + http_store ! stop, + ok. + +dispatch(Req) -> + case Req:get(method) of + 'GET' -> + get_resource(Req); + 'PUT' -> + put_resource(Req); + 'DELETE' -> + delete_resource(Req); + _ -> + Headers = [{"Allow", "GET,PUT,DELETE"}], + Req:respond({405, Headers, "405 Method Not Allowed\r\n"}) + end. + +get_resource(Req) -> + Path = Req:get(path), + case ets:lookup(?MODULE, Path) of + [{Path, #resource{type=Type, data=Data}}] -> + Req:ok({Type, Data}); + [] -> + Req:respond({404, [], "404 Not Found\r\n"}) + end. + +put_resource(Req) -> + ContentType = case Req:get_header_value("Content-Type") of + undefined -> + "application/octet-stream"; + S -> + S + end, + Resource = #resource{type=ContentType, data=Req:recv_body()}, + http_store ! {self(), {put, Req:get(path), Resource}}, + Pid = whereis(http_store), + receive + {Pid, created} -> + Req:respond({201, [], "201 Created\r\n"}); + {Pid, updated} -> + Req:respond({200, [], "200 OK\r\n"}) + end. + +delete_resource(Req) -> + http_store ! {self(), {delete, Req:get(path)}}, + Pid = whereis(http_store), + receive + {Pid, ok} -> + Req:respond({200, [], "200 OK\r\n"}) + end. + +loop(#sd{http=Http, https=Https} = SD) -> + receive + stop -> + ok = mochiweb_http:stop(Http), + ok = mochiweb_http:stop(Https), + exit(normal); + {From, {put, Key, Val}} -> + Exists = ets:member(?MODULE, Key), + ets:insert(?MODULE, {Key, Val}), + case Exists of + true -> + From ! {self(), updated}; + false -> + From ! {self(), created} + end; + {From, {delete, Key}} -> + ets:delete(?MODULE, Key), + From ! {self(), ok}; + _ -> + ignore + end, + ?MODULE:loop(SD). + |