0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00
cowboy/test/handlers/provide_range_callback_h.erl
Loïc Hoguin dd0fbab6b7
Add automatic ranged request handling for bytes units
Returning the atom auto instead of a callback informs Cowboy
that it needs to handle range requests automatically. This
changes the behavior so that the ProvideCallback function
is called and then Cowboy splits the data on its own and
sends the response without any other user involvement other
than defining the ranges_provided/2 callback.

This is a quick and dirty way to add range request support
to resources, and will be good enough for many cases including
for cowboy_static as it also works when the normal response
body is a sendfile tuple.
2018-11-11 13:57:26 +01:00

66 lines
1.9 KiB
Erlang

%% This module defines many callbacks relevant to range requests
%% and return something different depending on query string.
-module(provide_range_callback_h).
-export([init/2]).
-export([content_types_provided/2]).
-export([ranges_provided/2]).
-export([expires/2]).
-export([generate_etag/2]).
-export([last_modified/2]).
-export([get_text_plain/2]).
-export([get_text_plain_bytes/2]).
init(Req, State) ->
{cowboy_rest, Req, State}.
content_types_provided(Req, State) ->
{[
{{<<"text">>, <<"plain">>, []}, get_text_plain},
%% This one only exists so we generate a vary header.
{{<<"text">>, <<"html">>, []}, get_text_html}
], Req, State}.
ranges_provided(Req, State) ->
{[{<<"bytes">>, get_text_plain_bytes}], Req, State}.
generate_etag(Req=#{qs := <<"weak-etag">>}, State) ->
{{weak, <<"weak-no-match">>}, Req, State};
generate_etag(Req, State) ->
{{strong, <<"strong-and-match">>}, Req, State}.
last_modified(Req, State) ->
{{{2222, 2, 22}, {11, 11, 11}}, Req, State}.
expires(Req, State) ->
{{{3333, 3, 3}, {11, 11, 11}}, Req, State}.
get_text_plain(Req, State) ->
{<<"This is REST!">>, Req, State}.
%% Simulate the callback being missing, otherwise expect true/false.
get_text_plain_bytes(#{qs := <<"missing">>}, _) ->
ct_helper_error_h:ignore(cowboy_rest, set_ranged_body_callback, 3),
no_call;
get_text_plain_bytes(Req=#{range := {_, [{From=0, infinity}]}}, State) ->
%% We send everything in one part.
Body = <<"This is ranged REST!">>,
Total = byte_size(Body),
{[{{From, Total - 1, Total}, Body}], Req, State};
get_text_plain_bytes(Req=#{range := {_, Range}}, State) ->
%% We check the range header we get and send everything hardcoded.
[
{0, 3},
{5, 6},
{8, 13},
{15, infinity}
] = Range,
Body = <<"This is ranged REST!">>,
Total = byte_size(Body),
{[
{{0, 3, Total}, <<"This">>},
{{5, 6, Total}, <<"is">>},
{{8, 13, Total}, <<"ranged">>},
{{15, 19, Total}, <<"REST!">>}
], Req, State}.