summaryrefslogtreecommitdiff
path: root/src/catlfish_web.erl
blob: d49aaa1fddb8ea1b91cf17aac673b6b8849912b9 (plain)
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
%%% Copyright (c) 2014-2015, NORDUnet A/S.
%%% See LICENSE for licensing information.

-module(catlfish_web).
-export([start/3, loop/2]).

start(Options, Module, Name) ->
    lager:debug("Starting catlfish web server: ~p", [Module]),
    Loop = fun (Req) ->
                   ?MODULE:loop(Req, Module)
           end,
    mochiweb_http:start([{name, Name}, {loop, Loop} | Options]).


add_auth(Path, {Code, Headers, Data}) ->
    AuthHeader = http_auth:create_auth("REPLY", Path, Data),
    lager:debug("sent auth header: ~p", [AuthHeader]),
    {Code, [{"X-Catlfish-Auth", AuthHeader} | Headers], Data}.

loop(Req, Module) ->
    "/" ++ Path = Req:get(path),
    try
        Starttime = os:timestamp(),
        AuthHeader = Req:get_header_value("X-Catlfish-Auth"),
        case Req:get(method) of
            'GET' ->
                Query = Req:parse_qs(),
                {_, RawQuery, _} = mochiweb_util:urlsplit_path(Req:get(raw_path)),
                Result = case http_auth:verify_auth(AuthHeader, "GET", "/" ++ Path, RawQuery) of
                             failure ->
                                 {403, [{"Content-Type", "text/plain"}], "Invalid credentials"};
                             success ->
                                 lager:debug("GET ~p ~p", [Path, Query]),
                                 add_auth("/" ++ Path, Module:request(get, Path, Query));
                             noauth ->
                                 lager:debug("GET ~p ~p", [Path, Query]),
                                 Module:request(get, Path, Query)
                         end,
                lager:debug("GET finished: ~p us", [timer:now_diff(os:timestamp(), Starttime)]),
                case Result of
                    none ->
                        Req:respond({404, [{"Content-Type", "text/plain"}], "Page not found"});
                    _ ->
                        Req:respond(Result)
                end;
            'POST' ->
                Body = Req:recv_body(),
                Result = case http_auth:verify_auth(AuthHeader, "POST", "/" ++ Path, Body) of
                             failure ->
                                 {403, [{"Content-Type", "text/plain"}], "Invalid credentials"};
                             success ->
                                 lager:debug("POST ~p ~p", [Path, Body]),
                                 add_auth("/" ++ Path, Module:request(post, Path, Body));
                             noauth ->
                                 lager:debug("POST ~p ~p", [Path, Body]),
                                 Module:request(post, Path, Body)
                         end,
                lager:debug("POST finished: ~p us", [timer:now_diff(os:timestamp(), Starttime)]),
                case Result of
                    none ->
                        Req:respond({404, [{"Content-Type", "text/plain"}], "Page not found"});
                    _ ->
                        Req:respond(Result)
                end;
            _ ->
                Req:respond({501, [], []})
        end
    catch
        Type:What ->
            [CrashFunction | Stack] = erlang:get_stacktrace(),
            lager:error("Crash in ~p for path ~p: ~p ~p~n~p~n~p~n", [Module, Path, Type, What, CrashFunction, Stack]),
            Req:respond({500, [{"Content-Type", "text/plain"}],
                         "Internal Server Error\n"})
    end.