req_SUITE.erl 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. %% Copyright (c) 2016, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. -module(req_SUITE).
  15. -compile(export_all).
  16. -import(ct_helper, [config/2]).
  17. -import(ct_helper, [doc/1]).
  18. -import(cowboy_test, [gun_open/1]).
  19. %% ct.
  20. all() ->
  21. cowboy_test:common_all().
  22. groups() ->
  23. AllTests = ct_helper:all(?MODULE),
  24. [
  25. {http, [parallel], AllTests},
  26. {https, [parallel], AllTests},
  27. {h2, [parallel], AllTests},
  28. {h2c, [parallel], AllTests}
  29. %% @todo With compression enabled.
  30. ].
  31. init_per_group(Name, Config) ->
  32. cowboy_test:init_common_groups(Name, Config, ?MODULE).
  33. end_per_group(Name, _) ->
  34. cowboy:stop_listener(Name).
  35. %% Routes.
  36. init_dispatch(_) ->
  37. cowboy_router:compile([{"[...]", [
  38. {"/no/:key", echo_h, []},
  39. {"/args/:key/:arg[/:default]", echo_h, []},
  40. {"/:key/[...]", echo_h, []}
  41. ]}]).
  42. %% Internal.
  43. do_body(Method, Path, Config) ->
  44. do_body(Method, Path, [], Config).
  45. do_body(Method, Path, Headers, Config) ->
  46. ConnPid = gun_open(Config),
  47. Ref = gun:request(ConnPid, Method, Path, Headers),
  48. {response, IsFin, 200, _} = gun:await(ConnPid, Ref),
  49. {ok, Body} = case IsFin of
  50. nofin -> gun:await_body(ConnPid, Ref);
  51. fin -> {ok, <<>>}
  52. end,
  53. gun:close(ConnPid),
  54. Body.
  55. do_get_body(Path, Config) ->
  56. do_get_body(Path, [], Config).
  57. do_get_body(Path, Headers, Config) ->
  58. do_body("GET", Path, Headers, Config).
  59. %% Tests.
  60. host(Config) ->
  61. doc("Request URI host."),
  62. <<"localhost">> = do_get_body("/host", Config),
  63. ok.
  64. host_info(Config) ->
  65. doc("Request host_info."),
  66. <<"[<<\"localhost\">>]">> = do_get_body("/host_info", Config),
  67. ok.
  68. method(Config) ->
  69. doc("Request method."),
  70. <<"GET">> = do_body("GET", "/method", Config),
  71. <<"HEAD">> = do_body("HEAD", "/method", Config),
  72. <<"OPTIONS">> = do_body("OPTIONS", "/method", Config),
  73. <<"PATCH">> = do_body("PATCH", "/method", Config),
  74. <<"POST">> = do_body("POST", "/method", Config),
  75. <<"PUT">> = do_body("PUT", "/method", Config),
  76. <<"ZZZZZZZZ">> = do_body("ZZZZZZZZ", "/method", Config),
  77. ok.
  78. %% @todo Do we really want a key/value list here instead of a map?
  79. parse_qs(Config) ->
  80. doc("Parsed request URI query string."),
  81. <<"[]">> = do_get_body("/parse_qs", Config),
  82. <<"[{<<\"abc\">>,true}]">> = do_get_body("/parse_qs?abc", Config),
  83. <<"[{<<\"a\">>,<<\"b\">>},{<<\"c\">>,<<\"d e\">>}]">> = do_get_body("/parse_qs?a=b&c=d+e", Config),
  84. ok.
  85. path(Config) ->
  86. doc("Request URI path."),
  87. <<"/path/to/the/resource">> = do_get_body("/path/to/the/resource", Config),
  88. <<"/path/to/the/resource">> = do_get_body("/path/to/the/resource?query", Config),
  89. <<"/path/to/the/resource">> = do_get_body("/path/to/the/resource?query#fragment", Config),
  90. <<"/path/to/the/resource">> = do_get_body("/path/to/the/resource#fragment", Config),
  91. ok.
  92. path_info(Config) ->
  93. doc("Request path_info."),
  94. <<"undefined">> = do_get_body("/no/path_info", Config),
  95. <<"[]">> = do_get_body("/path_info", Config),
  96. <<"[]">> = do_get_body("/path_info/", Config),
  97. <<"[<<\"to\">>,<<\"the\">>,<<\"resource\">>]">> = do_get_body("/path_info/to/the/resource", Config),
  98. <<"[<<\"to\">>,<<\"the\">>,<<\"resource\">>]">> = do_get_body("/path_info/to/the/resource?query", Config),
  99. <<"[<<\"to\">>,<<\"the\">>,<<\"resource\">>]">> = do_get_body("/path_info/to/the/resource?query#fragment", Config),
  100. <<"[<<\"to\">>,<<\"the\">>,<<\"resource\">>]">> = do_get_body("/path_info/to/the/resource#fragment", Config),
  101. ok.
  102. peer(Config) ->
  103. doc("Request peer."),
  104. <<"{{127,0,0,1},", _/bits >> = do_get_body("/peer", Config),
  105. ok.
  106. port(Config) ->
  107. doc("Request URI port."),
  108. Port = integer_to_binary(config(port, Config)),
  109. Port = do_get_body("/port", Config),
  110. ok.
  111. qs(Config) ->
  112. doc("Request URI query string."),
  113. <<>> = do_get_body("/qs", Config),
  114. <<"abc">> = do_get_body("/qs?abc", Config),
  115. <<"a=b&c=d+e">> = do_get_body("/qs?a=b&c=d+e", Config),
  116. ok.
  117. scheme(Config) ->
  118. doc("Request URI scheme."),
  119. Transport = config(type, Config),
  120. case do_get_body("/scheme", Config) of
  121. <<"http">> when Transport =:= tcp -> ok;
  122. <<"https">> when Transport =:= ssl -> ok
  123. end.
  124. version(Config) ->
  125. doc("Request HTTP version."),
  126. Protocol = config(protocol, Config),
  127. case do_get_body("/version", Config) of
  128. <<"HTTP/1.1">> when Protocol =:= http -> ok;
  129. <<"HTTP/2">> when Protocol =:= http2 -> ok
  130. end.