diff options
author | Loïc Hoguin <[email protected]> | 2013-02-07 18:34:49 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2013-02-07 18:37:15 +0100 |
commit | efbd9133261e1aabf473f2f6f5ab4cbb36062481 (patch) | |
tree | 1b2855534b20c59208edd82be61ae3aa738a0141 /examples/rest_pastebin/src | |
parent | cb15243d8b91458f1c5e2a7e0c664f7b76f593ad (diff) | |
parent | d7b83db92ea6b6a0022c7d19c252037197fc28c4 (diff) | |
download | cowboy-efbd9133261e1aabf473f2f6f5ab4cbb36062481.tar.gz cowboy-efbd9133261e1aabf473f2f6f5ab4cbb36062481.tar.bz2 cowboy-efbd9133261e1aabf473f2f6f5ab4cbb36062481.zip |
Merge branch 'add_rest_example' of git://github.com/acammack/cowboy
Diffstat (limited to 'examples/rest_pastebin/src')
-rw-r--r-- | examples/rest_pastebin/src/rest_pastebin.app.src | 15 | ||||
-rw-r--r-- | examples/rest_pastebin/src/rest_pastebin.erl | 14 | ||||
-rw-r--r-- | examples/rest_pastebin/src/rest_pastebin_app.erl | 25 | ||||
-rw-r--r-- | examples/rest_pastebin/src/rest_pastebin_sup.erl | 23 | ||||
-rw-r--r-- | examples/rest_pastebin/src/toppage_handler.erl | 132 |
5 files changed, 209 insertions, 0 deletions
diff --git a/examples/rest_pastebin/src/rest_pastebin.app.src b/examples/rest_pastebin/src/rest_pastebin.app.src new file mode 100644 index 0000000..7701ebe --- /dev/null +++ b/examples/rest_pastebin/src/rest_pastebin.app.src @@ -0,0 +1,15 @@ +%% Feel free to use, reuse and abuse the code in this file. + +{application, rest_pastebin, [ + {description, "Cowboy REST Pastebin example inspired by sprunge."}, + {vsn, "1"}, + {modules, []}, + {registered, []}, + {applications, [ + kernel, + stdlib, + cowboy + ]}, + {mod, {rest_pastebin_app, []}}, + {env, []} +]}. diff --git a/examples/rest_pastebin/src/rest_pastebin.erl b/examples/rest_pastebin/src/rest_pastebin.erl new file mode 100644 index 0000000..cf03a71 --- /dev/null +++ b/examples/rest_pastebin/src/rest_pastebin.erl @@ -0,0 +1,14 @@ +%% Feel free to use, reuse and abuse the code in this file. + +-module(rest_pastebin). + +%% API. +-export([start/0]). + +%% API. + +start() -> + ok = application:start(crypto), + ok = application:start(ranch), + ok = application:start(cowboy), + ok = application:start(rest_pastebin). diff --git a/examples/rest_pastebin/src/rest_pastebin_app.erl b/examples/rest_pastebin/src/rest_pastebin_app.erl new file mode 100644 index 0000000..10ba4c5 --- /dev/null +++ b/examples/rest_pastebin/src/rest_pastebin_app.erl @@ -0,0 +1,25 @@ +%% Feel free to use, reuse and abuse the code in this file. + +%% @private +-module(rest_pastebin_app). +-behaviour(application). + +%% API. +-export([start/2]). +-export([stop/1]). + +%% API. + +start(_Type, _Args) -> + Dispatch = cowboy_router:compile([ + {'_', [ + {"/[:paste_id]", toppage_handler, []} + ]} + ]), + {ok, _} = cowboy:start_http(http, 100, [{port, 8080}], [ + {env, [{dispatch, Dispatch}]} + ]), + rest_pastebin_sup:start_link(). + +stop(_State) -> + ok. diff --git a/examples/rest_pastebin/src/rest_pastebin_sup.erl b/examples/rest_pastebin/src/rest_pastebin_sup.erl new file mode 100644 index 0000000..b5f08d7 --- /dev/null +++ b/examples/rest_pastebin/src/rest_pastebin_sup.erl @@ -0,0 +1,23 @@ +%% Feel free to use, reuse and abuse the code in this file. + +%% @private +-module(rest_pastebin_sup). +-behaviour(supervisor). + +%% API. +-export([start_link/0]). + +%% supervisor. +-export([init/1]). + +%% API. + +-spec start_link() -> {ok, pid()}. +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%% supervisor. + +init([]) -> + Procs = [], + {ok, {{one_for_one, 10, 10}, Procs}}. diff --git a/examples/rest_pastebin/src/toppage_handler.erl b/examples/rest_pastebin/src/toppage_handler.erl new file mode 100644 index 0000000..758e11d --- /dev/null +++ b/examples/rest_pastebin/src/toppage_handler.erl @@ -0,0 +1,132 @@ +%% Feel free to use, reuse and abuse the code in this file. + +%% @doc Pastebin handler. +-module(toppage_handler). + +%% REST Callbacks +-export([init/3]). +-export([allowed_methods/2]). +-export([content_types_provided/2]). +-export([content_types_accepted/2]). +-export([resource_exists/2]). +-export([post_is_create/2]). +-export([create_path/2]). + +%% Callback Callbacks +-export([create_paste/2]). +-export([paste_html/2]). +-export([paste_text/2]). + +init(_Transport, _Req, []) -> + % For the random number generator: + {X, Y, Z} = now(), + random:seed(X, Y, Z), + {upgrade, protocol, cowboy_rest}. + +allowed_methods(Req, State) -> + {[<<"GET">>, <<"POST">>], Req, State}. + +content_types_provided(Req, State) -> + {[ + {{<<"text">>, <<"plain">>, []}, paste_text}, + {{<<"text">>, <<"html">>, []}, paste_html} + ], Req, State}. + +content_types_accepted(Req, State) -> + {[{{<<"application">>, <<"x-www-form-urlencoded">>, []}, create_paste}], + Req, State}. + +resource_exists(Req, _State) -> + case cowboy_req:binding(paste_id, Req) of + {undefined, Req2} -> + {true, Req2, index}; + {PasteID, Req2} -> + case valid_path(PasteID) and file_exists(PasteID) of + true -> {true, Req2, PasteID}; + false -> {false, Req2, PasteID} + end + end. + +post_is_create(Req, State) -> + {true, Req, State}. + +create_path(Req, State) -> + {<<$/, (new_paste_id())/binary>>, Req, State}. + +create_paste(Req, State) -> + {<<$/, PasteID/binary>>, Req2} = cowboy_req:meta(put_path, Req), + {ok, [{<<"paste">>, Paste}], Req3} = cowboy_req:body_qs(Req2), + ok = file:write_file(full_path(PasteID), Paste), + {true, Req3, State}. + +paste_html(Req, index) -> + {read_file("index.html"), Req, index}; +paste_html(Req, Paste) -> + {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain), + {format_html(Paste, Style), Req2, Paste}. + +paste_text(Req, index) -> + {read_file("index.txt"), Req, index}; +paste_text(Req, Paste) -> + {Style, Req2} = cowboy_req:qs_val(<<"lang">>, Req, plain), + {format_text(Paste, Style), Req2, Paste}. + +% Private + +read_file(Name) -> + {ok, Binary} = file:read_file(full_path(Name)), + Binary. + +full_path(Name) -> + {ok, Cwd} = file:get_cwd(), + filename:join([Cwd, "priv", Name]). + +file_exists(Name) -> + case file:read_file_info(full_path(Name)) of + {ok, _Info} -> true; + {error, _Reason} -> false + end. + +valid_path(<<>>) -> true; +valid_path(<<$., _T/binary>>) -> false; +valid_path(<<_Char, T/binary>>) -> valid_path(T). + +new_paste_id() -> + Initial = random:uniform(62) - 1, + new_paste_id(<<Initial>>, 7). +new_paste_id(Bin, 0) -> + Chars = <<"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890">>, + << <<(binary_part(Chars, B, 1))/binary>> || <<B>> <= Bin >>; +new_paste_id(Bin, Rem) -> + Next = random:uniform(62) - 1, + new_paste_id(<<Bin/binary, Next>>, Rem - 1). + +format_html(Paste, plain) -> + Text = escape_html_chars(read_file(Paste)), + <<"<!DOCTYPE html><html>", + "<head><title>paste</title></head>", + "<body><pre><code>", Text/binary, "</code></pre></body></html>\n">>; +format_html(Paste, Lang) -> + highlight(full_path(Paste), Lang, "html"). + +format_text(Paste, plain) -> + read_file(Paste); +format_text(Paste, Lang) -> + highlight(full_path(Paste), Lang, "ansi"). + +highlight(Path, Lang, Type) -> + Path1 = binary_to_list(Path), + Lang1 = binary_to_list(Lang), + os:cmd(["highlight --syntax=", Lang1, + " --doc-title=paste ", + " --out-format=", Type, + " --include-style ", Path1]). + +% Escape some HTML characters that might make a fuss +escape_html_chars(Bin) -> + << <<(escape_html_char(B))/binary>> || <<B>> <= Bin >>. + +escape_html_char($<) -> <<"<">>; +escape_html_char($>) -> <<">">>; +escape_html_char($&) -> <<"&">>; +escape_html_char(C) -> <<C>>. |