-
Notifications
You must be signed in to change notification settings - Fork 0
/
tinyerl_handler.erl
77 lines (63 loc) · 2.02 KB
/
tinyerl_handler.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
-module(tinyerl_handler).
-export([
init/3,
handle/2,
terminate/3]
).
init(_Type, Req, _Opts) ->
{ok, Req, #{}}.
handle(Req, State) ->
try
case cowboy_req:method(Req) of
{<<"POST">>, Req1} ->
handle_post(Req1, State);
{<<"GET">>, Req1} ->
handle_get(Req1, State);
_ ->
throw(unallowed_method)
end
catch
throw:Reason ->
handle_exception(Reason, Req, State)
end.
terminate(_Reason, _Req, _State) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Private functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
handle_post(Req, State) ->
{Path, Req1} = cowboy_req:path(Req),
throw_when(not_found, Path /= <<"/shorten">>),
{ok, Params, Req2} = cowboy_req:body_qs(Req1),
Url = proplists:get_value(<<"url">>, Params),
throw_when(bad_request, Url == undefined),
Random = ktn_random:generate(),
RandomBinary = erlang:list_to_binary(Random),
dets:insert(urls, {RandomBinary, Url}),
ShortUrl = <<"http://localhost:8080/", RandomBinary/binary>>,
Headers = [{<<"Location">>, ShortUrl}],
{ok, Req3} = cowboy_req:reply(201, Headers, Req2),
{ok, Req3, State}.
handle_get(Req, State) ->
{<<"/", RandomUrl/binary>>, Req1} = cowboy_req:path(Req),
case dets:lookup(urls, RandomUrl) of
[{_, Url}] ->
Headers = [{<<"Location">>, Url}],
{ok, Req2} = cowboy_req:reply(302, Headers, Req1),
{ok, Req2, State};
_ ->
throw(not_found)
end.
%%% Error handling
handle_exception(Reason, Req, State) ->
Code = status_code(Reason),
{ok, Req1} = cowboy_req:reply(Code, Req),
{ok, Req1, State}.
status_code(unallowed_method) -> 405;
status_code(bad_request) -> 400;
status_code(not_found) -> 404.
throw_when(Reason, IsThrown) ->
case IsThrown of
true -> throw(Reason);
_ -> ok
end.