src/nine_cowboy_util.erl

-module(nine_cowboy_util).

-export([get_path/1, not_found/1, redirect/2, json_response/3, bearer/1, serve_priv_file/3, join_path/1]).

get_path(Req) ->
    Path = cowboy_req:path(Req),
    split_path(Path).

split_path(Path) ->
    string:split(Path, <<"/">>, all).

not_found(#{req := Req} = Context) ->
    Resp = cowboy_req:reply(
        404,
        #{<<"Content-Type">> => <<"text/plain">>},
        <<"Not Found">>,
        Req
    ),
    Context#{resp => Resp}.

redirect(#{req := Req} = Context, RedirectPath) ->
    Resp = cowboy_req:reply(
        302,
        #{<<"Location">> => RedirectPath},
        <<>>,
        Req
    ),
    Context#{resp => Resp}.

bearer(Req) ->
    case cowboy_req:header(<<"authorization">>, Req, undefined) of
        undefined -> undefined;
        Bearer ->
            case string:prefix(Bearer, <<"Bearer ">>) of
                nomatch ->
                    undefined;
                Token ->
                    Token
            end
    end.

json_response(Status, Body, Req) ->
    cowboy_req:reply(
        Status,
        #{<<"Content-Type">> => <<"application/json">>},
        thoas:encode(Body),
        Req
    ).

serve_priv_file(App, Req, Path) ->
    StrippedPath = strip_dots(Path),
    PrivPath = filename:join(code:priv_dir(App), StrippedPath),
    Mimetype = mimerl:filename(PrivPath),
    case file:read_file(PrivPath) of
        {ok, Bin} ->
            cowboy_req:reply(
                200,
                #{<<"Content-Type">> => Mimetype},
                Bin,
                Req
            );
        {error, _Error} ->
            cowboy_req:reply(404, #{}, <<>>, Req)
    end.

strip_dots(Path) ->
    list_to_binary(string:trim(string:replace(Path, <<"..">>, <<>>, all), leading, "/")).

join_path(L) ->
    join_path(L, []).

join_path([], Acc) ->
    list_to_binary(lists:reverse(Acc));
join_path([Part], Acc) ->
    join_path([], [Part | Acc]);
join_path([<<>> | T], Acc) ->
    join_path(T, Acc);
join_path([H | T], Acc) ->
    join_path(T, [[H, <<"/">>] | Acc]).