provide_range_callback_h.erl 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. %% This module defines many callbacks relevant to range requests
  2. %% and return something different depending on query string.
  3. -module(provide_range_callback_h).
  4. -export([init/2]).
  5. -export([content_types_provided/2]).
  6. -export([ranges_provided/2]).
  7. -export([expires/2]).
  8. -export([generate_etag/2]).
  9. -export([last_modified/2]).
  10. -export([get_text_plain/2]).
  11. -export([get_text_plain_bytes/2]).
  12. init(Req, State) ->
  13. {cowboy_rest, Req, State}.
  14. content_types_provided(Req, State) ->
  15. {[
  16. {{<<"text">>, <<"plain">>, []}, get_text_plain},
  17. %% This one only exists so we generate a vary header.
  18. {{<<"text">>, <<"html">>, []}, get_text_html}
  19. ], Req, State}.
  20. ranges_provided(Req, State) ->
  21. {[{<<"bytes">>, get_text_plain_bytes}], Req, State}.
  22. generate_etag(Req=#{qs := <<"weak-etag">>}, State) ->
  23. {{weak, <<"weak-no-match">>}, Req, State};
  24. generate_etag(Req, State) ->
  25. {{strong, <<"strong-and-match">>}, Req, State}.
  26. last_modified(Req, State) ->
  27. {{{2222, 2, 22}, {11, 11, 11}}, Req, State}.
  28. expires(Req, State) ->
  29. {{{3333, 3, 3}, {11, 11, 11}}, Req, State}.
  30. get_text_plain(Req, State) ->
  31. {<<"This is REST!">>, Req, State}.
  32. %% Simulate the callback being missing, otherwise expect true/false.
  33. get_text_plain_bytes(#{qs := <<"missing">>}, _) ->
  34. ct_helper_error_h:ignore(cowboy_rest, set_ranged_body_callback, 3),
  35. no_call;
  36. get_text_plain_bytes(Req=#{qs := <<"sendfile">>, range := {_, [{From=0, infinity}]}}, State) ->
  37. Path = code:lib_dir(cowboy) ++ "/ebin/cowboy.app",
  38. Size = filelib:file_size(Path),
  39. {[{{From, Size - 1, Size}, {sendfile, From, Size, Path}}], Req, State};
  40. get_text_plain_bytes(Req=#{range := {_, [{From=0, infinity}]}}, State) ->
  41. %% We send everything in one part.
  42. Body = <<"This is ranged REST!">>,
  43. Total = byte_size(Body),
  44. {[{{From, Total - 1, Total}, Body}], Req, State};
  45. get_text_plain_bytes(Req=#{qs := <<"sendfile">>, range := {_, Range}}, State) ->
  46. %% We check the range header we get and send everything hardcoded.
  47. [
  48. {50, 99},
  49. {150, 199},
  50. {250, 299},
  51. -99
  52. ] = Range,
  53. Path = code:lib_dir(cowboy) ++ "/ebin/cowboy.app",
  54. Size = filelib:file_size(Path),
  55. {[
  56. {{50, 99, Size}, {sendfile, 50, 50, Path}},
  57. {{150, 199, Size}, {sendfile, 150, 50, Path}},
  58. {{250, 299, Size}, {sendfile, 250, 50, Path}},
  59. {{Size - 99, Size - 1, Size}, {sendfile, Size - 99, 99, Path}}
  60. ], Req, State};
  61. get_text_plain_bytes(Req=#{range := {_, Range}}, State) ->
  62. %% We check the range header we get and send everything hardcoded.
  63. [
  64. {0, 3},
  65. {5, 6},
  66. {8, 13},
  67. {15, infinity}
  68. ] = Range,
  69. Body = <<"This is ranged REST!">>,
  70. Total = byte_size(Body),
  71. {[
  72. {{0, 3, Total}, <<"This">>},
  73. {{5, 6, Total}, <<"is">>},
  74. {{8, 13, Total}, <<"ranged">>},
  75. {{15, 19, Total}, <<"REST!">>}
  76. ], Req, State}.