echo_h.erl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. %% This module echoes back the value the test is interested in.
  2. -module(echo_h).
  3. -export([init/2]).
  4. init(Req, Opts) ->
  5. case cowboy_req:binding(arg, Req) of
  6. undefined ->
  7. echo(cowboy_req:binding(key, Req), Req, Opts);
  8. Arg ->
  9. echo_arg(Arg, Req, Opts)
  10. end.
  11. echo(<<"read_body">>, Req0, Opts) ->
  12. case Opts of
  13. #{crash := true} -> ct_helper:ignore(cowboy_req, read_body, 2);
  14. _ -> ok
  15. end,
  16. {_, Body, Req} = case cowboy_req:path(Req0) of
  17. <<"/100-continue", _/bits>> ->
  18. cowboy_req:inform(100, Req0),
  19. cowboy_req:read_body(Req0);
  20. <<"/delay", _/bits>> ->
  21. timer:sleep(500),
  22. cowboy_req:read_body(Req0);
  23. <<"/full", _/bits>> -> read_body(Req0, <<>>);
  24. <<"/length", _/bits>> ->
  25. {_, _, Req1} = read_body(Req0, <<>>),
  26. Length = cowboy_req:body_length(Req1),
  27. {ok, integer_to_binary(Length), Req1};
  28. <<"/opts", _/bits>> -> cowboy_req:read_body(Req0, Opts);
  29. <<"/spawn", _/bits>> ->
  30. Parent = self(),
  31. Pid = spawn_link(fun() ->
  32. Parent ! {self(), cowboy_req:read_body(Req0)}
  33. end),
  34. receive
  35. {Pid, Msg} -> Msg
  36. after 5000 ->
  37. error(timeout)
  38. end;
  39. _ -> cowboy_req:read_body(Req0)
  40. end,
  41. {ok, cowboy_req:reply(200, #{}, Body, Req), Opts};
  42. echo(<<"read_urlencoded_body">>, Req0, Opts) ->
  43. Path = cowboy_req:path(Req0),
  44. case {Path, Opts} of
  45. {<<"/opts", _/bits>>, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_body, 2);
  46. {_, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_urlencoded_body, 2);
  47. _ -> ok
  48. end,
  49. {ok, Body, Req} = case Path of
  50. <<"/opts", _/bits>> -> cowboy_req:read_urlencoded_body(Req0, Opts);
  51. <<"/crash", _/bits>> -> cowboy_req:read_urlencoded_body(Req0, Opts);
  52. _ -> cowboy_req:read_urlencoded_body(Req0)
  53. end,
  54. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Body), Req), Opts};
  55. echo(<<"read_and_match_urlencoded_body">>, Req0, Opts) ->
  56. Path = cowboy_req:path(Req0),
  57. case {Path, Opts} of
  58. {<<"/opts", _/bits>>, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_body, 2);
  59. {_, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_urlencoded_body, 2);
  60. _ -> ok
  61. end,
  62. {ok, Body, Req} = case Path of
  63. <<"/opts", _/bits>> -> cowboy_req:read_and_match_urlencoded_body([], Req0, Opts);
  64. <<"/crash", _/bits>> -> cowboy_req:read_and_match_urlencoded_body([], Req0, Opts);
  65. _ -> cowboy_req:read_and_match_urlencoded_body([], Req0)
  66. end,
  67. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Body), Req), Opts};
  68. echo(<<"uri">>, Req, Opts) ->
  69. Value = case cowboy_req:path_info(Req) of
  70. [<<"origin">>] -> cowboy_req:uri(Req, #{host => undefined});
  71. [<<"protocol-relative">>] -> cowboy_req:uri(Req, #{scheme => undefined});
  72. [<<"no-qs">>] -> cowboy_req:uri(Req, #{qs => undefined});
  73. [<<"no-path">>] -> cowboy_req:uri(Req, #{path => undefined, qs => undefined});
  74. [<<"set-port">>] -> cowboy_req:uri(Req, #{port => 123});
  75. _ -> cowboy_req:uri(Req)
  76. end,
  77. {ok, cowboy_req:reply(200, #{}, Value, Req), Opts};
  78. echo(<<"match">>, Req, Opts) ->
  79. [Type|Fields0] = cowboy_req:path_info(Req),
  80. Fields = [binary_to_atom(F, latin1) || F <- Fields0],
  81. Value = case Type of
  82. <<"qs">> -> cowboy_req:match_qs(Fields, Req);
  83. <<"cookies">> -> cowboy_req:match_cookies(Fields, Req);
  84. <<"body_qs">> ->
  85. %% Note that the Req should not be discarded but for the
  86. %% purpose of this test this has no ill impacts.
  87. {ok, Match, _} = cowboy_req:read_and_match_urlencoded_body(Fields, Req),
  88. Match
  89. end,
  90. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts};
  91. echo(<<"filter_then_parse_cookies">>, Req0, Opts) ->
  92. Req = cowboy_req:filter_cookies([cake, color], Req0),
  93. Value = cowboy_req:parse_cookies(Req),
  94. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts};
  95. echo(What, Req, Opts) ->
  96. Key = binary_to_atom(What, latin1),
  97. Value = case cowboy_req:path(Req) of
  98. <<"/direct/",_/bits>> -> maps:get(Key, Req);
  99. _ -> cowboy_req:Key(Req)
  100. end,
  101. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts}.
  102. echo_arg(Arg0, Req, Opts) ->
  103. F = binary_to_atom(cowboy_req:binding(key, Req), latin1),
  104. Arg = case F of
  105. binding -> binary_to_atom(Arg0, latin1);
  106. _ -> Arg0
  107. end,
  108. Value = case cowboy_req:binding(default, Req) of
  109. undefined -> cowboy_req:F(Arg, Req);
  110. Default -> cowboy_req:F(Arg, Req, Default)
  111. end,
  112. {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts}.
  113. read_body(Req0, Acc) ->
  114. case cowboy_req:read_body(Req0) of
  115. {ok, Data, Req} -> {ok, << Acc/binary, Data/binary >>, Req};
  116. {more, Data, Req} -> read_body(Req, << Acc/binary, Data/binary >>)
  117. end.
  118. value_to_iodata(V) when is_integer(V) -> integer_to_binary(V);
  119. value_to_iodata(V) when is_atom(V) -> atom_to_binary(V, latin1);
  120. value_to_iodata(V) when is_list(V); is_tuple(V); is_map(V) -> io_lib:format("~999999p", [V]);
  121. value_to_iodata(V) -> V.