<commit_before>-module(elli_example_callback).
-export([handle/2, request_complete/6]).
-export([request_throw/4, request_exit/4, request_error/4,
         request_parse_error/2]).
-export([client_closed/2, client_timeout/2]).
-export([chunk_loop/1]).

-include("elli.hrl").
-behaviour(elli_handler).


handle(Req, _Args) ->
    handle(Req#req.method, elli_request:path(Req), Req).

handle('GET',[<<"hello">>, <<"world">>], _Req) ->
    {ok, [], <<"Hello World!">>};

handle('GET',[<<"headers.html">>], _Req) ->
    {ok, [{<<"X-Custom">>, <<"foobar">>}], <<"see headers">>};

handle('GET', [<<"hello">>], Req) ->
    Name = elli_request:get_arg(<<"name">>, Req),
    {ok, [], <<"Hello ", Name/binary>>};

handle('GET',[<<"close">>], _Req) ->
    {ok, [{<<"Connection">>, <<"close">>}], <<"closing">>};

handle('GET', [<<"crash">>], _Req) ->
    throw(foobar);

handle('GET', [<<"compressed">>], _Req) ->
    {ok, [], binary:copy(<<"Hello World!">>, 86)};

handle('GET', [<<"chunked">>], Req) ->
    Ref = elli_request:chunk_ref(Req),
    spawn(fun() -> ?MODULE:chunk_loop(Ref) end),
    {chunk, []};

handle('GET', [<<"304">>], _Req) ->
    {304, [], <<>>};

handle('GET', [<<"403">>], _Req) ->
    throw({403, [], <<"Forbidden">>});

handle(_, _, _Req) ->
    {404, [], <<"body">>}.




chunk_loop(Ref) ->
    chunk_loop(Ref, 10).

chunk_loop(Ref, 0) ->
    elli_request:send_chunk(Ref, <<>>);
chunk_loop(Ref, N) ->
    timer:sleep(1000),

    case elli_request:send_chunk(Ref, [<<"chunk">>, integer_to_list(N)]) of
        ok -> ok;
        {error, Reason} ->
            io:format("error in sending chunk: ~p~n", [Reason])
    end,

    chunk_loop(Ref, N-1).




request_complete(_Req, _ResponseCode, _ResponseHeaders, _ResponseBody, _Timings, _Args) ->
    %% io:format(
    %%   "REQUEST: ~s~n"
    %%   "    headers  : ~w us~n"
    %%   "    body     : ~w us~n"
    %%   "    user     : ~w us~n"
    %%   "    response : ~w us~n"
    %%   "    total    : ~w us~n",
    %%   [Req#req.path,
    %%    timer:now_diff(HeadersEnd, RequestStart),
    %%    timer:now_diff(BodyEnd, HeadersEnd),
    %%    timer:now_diff(UserEnd, BodyEnd),
    %%    timer:now_diff(RequestEnd, UserEnd),
    %%    timer:now_diff(RequestEnd, RequestStart)]),

    ok.

request_throw(_Req, _Exception, _Stack, _Args) -> ok.
request_exit(_Req, _Exit, _Stack, _Args)       -> ok.
request_error(_Req, _Error, _Stack, _Args)     -> ok.
request_parse_error(_Data, _Args)              -> ok.
client_closed(_When, _Args)                    -> ok.
client_timeout(_When, _Args)                   -> ok.<commit_msg>Added documentation to the example callback.<commit_after>-module(elli_example_callback).
-export([handle/2, request_complete/6]).
-export([request_throw/4, request_exit/4, request_error/4,
         request_parse_error/2]).
-export([client_closed/2, client_timeout/2]).
-export([chunk_loop/1]).

-include("elli.hrl").
-behaviour(elli_handler).


%%
%% ELLI REQUEST CALLBACK
%%

handle(Req, _Args) ->
    %% Delegate to our handler function
    handle(Req#req.method, elli_request:path(Req), Req).



%% Route METHOD & PATH to the appropriate clause
handle('GET',[<<"hello">>, <<"world">>], _Req) ->
    %% Reply with a normal response. 'ok' can be used instead of '200'
    %% to signal success.
    {ok, [], <<"Hello World!">>};

handle('GET', [<<"hello">>], Req) ->
    %% Fetch a get argument from the URL.
    Name = elli_request:get_arg(<<"name">>, Req),
    {ok, [], <<"Hello ", Name/binary>>};

handle('GET',[<<"headers.html">>], _Req) ->
    %% Set custom headers, for example 'Content-Type'
    {ok, [{<<"X-Custom">>, <<"foobar">>}], <<"see headers">>};

handle('GET',[<<"close">>], _Req) ->
    %% Set a custom connection header. Elli will by default use
    %% keep-alive if the browser supports it, this will override that
    %% behaviour.
    {ok, [{<<"Connection">>, <<"close">>}], <<"closing">>};

handle('GET', [<<"crash">>], _Req) ->
    %% Throwing an exception results in a 500 response and
    %% request_throw being called
    throw(foobar);

handle('GET', [<<"compressed">>], _Req) ->
    %% Body with a byte size over 1024 are automatically gzipped
    {ok, [], binary:copy(<<"Hello World!">>, 86)};

handle('GET', [<<"chunked">>], Req) ->
    %% Start a chunked response for streaming real-time events to the
    %% browser.
    %%
    %% Calling elli_request:send_chunk(ChunkRef, Body) will send that
    %% chunk to the client. An empty body will close the
    %% connection. See chunk_loop/1 below.
    %%
    %% Return immediately {chunk, Headers} to signal we want to chunk.
    Ref = elli_request:chunk_ref(Req),
    spawn(fun() -> ?MODULE:chunk_loop(Ref) end),
    {chunk, []};

handle('GET', [<<"304">>], _Req) ->
    {304, [], <<>>};

handle('GET', [<<"403">>], _Req) ->
    %% Exceptions formatted as return codes can be used to
    %% short-circuit a response, for example in case of
    %% authentication/authorization
    throw({403, [], <<"Forbidden">>});

handle(_, _, _Req) ->
    {404, [], <<"body">>}.



%% Send 10 separate chunks to the client.
chunk_loop(Ref) ->
    chunk_loop(Ref, 10).

chunk_loop(Ref, 0) ->
    %% Send empty chunk to make elli close the connection
    elli_request:send_chunk(Ref, <<>>);
chunk_loop(Ref, N) ->
    timer:sleep(1000),

    %% Send a chunk to the client, check for errors as the user might
    %% have disconnected
    case elli_request:send_chunk(Ref, [<<"chunk">>, integer_to_list(N)]) of
        ok -> ok;
        {error, Reason} ->
            io:format("error in sending chunk: ~p~n", [Reason])
    end,

    chunk_loop(Ref, N-1).


%%
%% ELLI EVENT CALLBACKS
%%


request_complete(_Req, _ResponseCode, _ResponseHeaders, _ResponseBody, _Timings, _Args) -> ok.
request_throw(_Req, _Exception, _Stack, _Args) -> ok.
request_exit(_Req, _Exit, _Stack, _Args)       -> ok.
request_error(_Req, _Error, _Stack, _Args)     -> ok.
request_parse_error(_Data, _Args)              -> ok.
client_closed(_When, _Args)                    -> ok.
client_timeout(_When, _Args)                   -> ok.
{'fraction_non_alphanumeric': 0.20750041301833802, 'fraction_numerical': 0.013381794151660334, 'mean_word_length': 3.3869565217391306, 'pattern_counts': {'":': 0, '<': 103, '<?xml version=': 0, '>': 151, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '98389', 'n_tokens_mistral': 2251, 'n_tokens_neox': 2124, 'n_words': 484}