rfc7231_SUITE.erl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. %% Copyright (c) 2017, 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(rfc7231_SUITE).
  15. -compile(export_all).
  16. -compile(nowarn_export_all).
  17. -import(ct_helper, [config/2]).
  18. -import(ct_helper, [doc/1]).
  19. -import(cowboy_test, [gun_open/1]).
  20. -import(cowboy_test, [raw_open/1]).
  21. -import(cowboy_test, [raw_send/2]).
  22. -import(cowboy_test, [raw_recv_head/1]).
  23. -import(cowboy_test, [raw_recv/3]).
  24. all() ->
  25. cowboy_test:common_all().
  26. groups() ->
  27. cowboy_test:common_groups(ct_helper:all(?MODULE)).
  28. init_per_group(Name, Config) ->
  29. cowboy_test:init_common_groups(Name, Config, ?MODULE).
  30. end_per_group(Name, _) ->
  31. cowboy:stop_listener(Name).
  32. init_dispatch(_) ->
  33. cowboy_router:compile([{"[...]", [
  34. {"*", asterisk_h, []},
  35. {"/", hello_h, []},
  36. {"/echo/:key", echo_h, []},
  37. {"/resp/:key[/:arg]", resp_h, []}
  38. ]}]).
  39. %% @todo The documentation should list what methods, headers and status codes
  40. %% are handled automatically so users can know what befalls to them to implement.
  41. %% Methods.
  42. method_get(Config) ->
  43. doc("The GET method is accepted. (RFC7231 4.3.1)"),
  44. ConnPid = gun_open(Config),
  45. Ref = gun:get(ConnPid, "/", [
  46. {<<"accept-encoding">>, <<"gzip">>}
  47. ]),
  48. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  49. {ok, <<"Hello world!">>} = gun:await_body(ConnPid, Ref),
  50. ok.
  51. method_head(Config) ->
  52. doc("The HEAD method is accepted. (RFC7231 4.3.2)"),
  53. ConnPid = gun_open(Config),
  54. Ref = gun:head(ConnPid, "/", [
  55. {<<"accept-encoding">>, <<"gzip">>}
  56. ]),
  57. {response, fin, 200, _} = gun:await(ConnPid, Ref),
  58. ok.
  59. method_head_same_resp_headers_as_get(Config) ->
  60. doc("Responses to HEAD should return the same headers as GET. (RFC7231 4.3.2)"),
  61. ConnPid = gun_open(Config),
  62. Ref1 = gun:get(ConnPid, "/", [
  63. {<<"accept-encoding">>, <<"gzip">>}
  64. ]),
  65. {response, nofin, 200, Headers1} = gun:await(ConnPid, Ref1),
  66. {ok, <<"Hello world!">>} = gun:await_body(ConnPid, Ref1),
  67. Ref2 = gun:head(ConnPid, "/", [
  68. {<<"accept-encoding">>, <<"gzip">>}
  69. ]),
  70. {response, fin, 200, Headers2} = gun:await(ConnPid, Ref2),
  71. %% We remove the date header since the date might have changed between requests.
  72. Headers = lists:keydelete(<<"date">>, 1, Headers1),
  73. Headers = lists:keydelete(<<"date">>, 1, Headers2),
  74. ok.
  75. method_head_same_resp_headers_as_get_stream_reply(Config) ->
  76. doc("Responses to HEAD should return the same headers as GET. (RFC7231 4.3.2)"),
  77. ConnPid = gun_open(Config),
  78. Ref1 = gun:get(ConnPid, "/resp/stream_reply2/200", [
  79. {<<"accept-encoding">>, <<"gzip">>}
  80. ]),
  81. {response, nofin, 200, Headers1} = gun:await(ConnPid, Ref1),
  82. {ok, _} = gun:await_body(ConnPid, Ref1),
  83. Ref2 = gun:head(ConnPid, "/resp/stream_reply2/200", [
  84. {<<"accept-encoding">>, <<"gzip">>}
  85. ]),
  86. {response, fin, 200, Headers2} = gun:await(ConnPid, Ref2),
  87. %% We remove the date header since the date might have changed between requests.
  88. Headers = lists:keydelete(<<"date">>, 1, Headers1),
  89. Headers = lists:keydelete(<<"date">>, 1, Headers2),
  90. ok.
  91. method_post(Config) ->
  92. doc("The POST method is accepted. (RFC7231 4.3.3)"),
  93. ConnPid = gun_open(Config),
  94. Ref = gun:post(ConnPid, "/echo/read_body", [
  95. {<<"accept-encoding">>, <<"gzip">>},
  96. {<<"content-type">>, <<"application/x-www-form-urlencoded">>}
  97. ], <<"hello=world">>),
  98. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  99. {ok, <<"hello=world">>} = gun:await_body(ConnPid, Ref),
  100. ok.
  101. method_put(Config) ->
  102. doc("The PUT method is accepted. (RFC7231 4.3.4)"),
  103. ConnPid = gun_open(Config),
  104. Ref = gun:put(ConnPid, "/echo/read_body", [
  105. {<<"accept-encoding">>, <<"gzip">>},
  106. {<<"content-type">>, <<"application/x-www-form-urlencoded">>}
  107. ], <<"hello=world">>),
  108. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  109. {ok, <<"hello=world">>} = gun:await_body(ConnPid, Ref),
  110. ok.
  111. method_delete(Config) ->
  112. doc("The DELETE method is accepted. (RFC7231 4.3.5)"),
  113. ConnPid = gun_open(Config),
  114. Ref = gun:delete(ConnPid, "/echo/method", [
  115. {<<"accept-encoding">>, <<"gzip">>}
  116. ]),
  117. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  118. {ok, <<"DELETE">>} = gun:await_body(ConnPid, Ref),
  119. ok.
  120. method_connect(Config) ->
  121. doc("The CONNECT method is currently not implemented. (RFC7231 4.3.6)"),
  122. ConnPid = gun_open(Config),
  123. Ref = gun:request(ConnPid, <<"CONNECT">>, "localhost:8080", [
  124. {<<"accept-encoding">>, <<"gzip">>}
  125. ]),
  126. {response, fin, 501, _} = gun:await(ConnPid, Ref),
  127. ok.
  128. % A client sending a CONNECT request MUST send the authority form of
  129. % request-target (Section 5.3 of [RFC7230]); i.e., the request-target
  130. % consists of only the host name and port number of the tunnel
  131. % destination, separated by a colon.
  132. %
  133. % A server MUST NOT send any Transfer-Encoding or Content-Length header
  134. % fields in a 2xx (Successful) response to CONNECT. A client MUST
  135. % ignore any Content-Length or Transfer-Encoding header fields received
  136. % in a successful response to CONNECT.
  137. %
  138. % A payload within a CONNECT request message has no defined semantics;
  139. % sending a payload body on a CONNECT request might cause some existing
  140. % implementations to reject the request.
  141. method_options(Config) ->
  142. doc("The OPTIONS method is accepted. (RFC7231 4.3.7)"),
  143. ConnPid = gun_open(Config),
  144. Ref = gun:options(ConnPid, "/echo/method", [
  145. {<<"accept-encoding">>, <<"gzip">>}
  146. ]),
  147. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  148. {ok, <<"OPTIONS">>} = gun:await_body(ConnPid, Ref),
  149. ok.
  150. method_options_asterisk(Config) ->
  151. doc("The OPTIONS method is accepted with an asterisk. (RFC7231 4.3.7)"),
  152. ConnPid = gun_open(Config),
  153. Ref = gun:options(ConnPid, "*", [
  154. {<<"accept-encoding">>, <<"gzip">>},
  155. {<<"x-echo">>, <<"method">>}
  156. ]),
  157. {response, nofin, 200, _} = gun:await(ConnPid, Ref),
  158. {ok, <<"OPTIONS">>} = gun:await_body(ConnPid, Ref),
  159. ok.
  160. method_options_content_length_0(Config) ->
  161. doc("The OPTIONS method must set the content-length header "
  162. "to 0 when no body is returned. (RFC7231 4.3.7)"),
  163. ConnPid = gun_open(Config),
  164. Ref = gun:options(ConnPid, "*", [
  165. {<<"accept-encoding">>, <<"gzip">>}
  166. ]),
  167. {response, fin, 200, Headers} = gun:await(ConnPid, Ref),
  168. {_, <<"0">>} = lists:keyfind(<<"content-length">>, 1, Headers),
  169. ok.
  170. method_trace(Config) ->
  171. doc("The TRACE method is currently not implemented. (RFC7231 4.3.8)"),
  172. ConnPid = gun_open(Config),
  173. Ref = gun:request(ConnPid, <<"TRACE">>, "/", [
  174. {<<"accept-encoding">>, <<"gzip">>}
  175. ]),
  176. {response, fin, 501, _} = gun:await(ConnPid, Ref),
  177. ok.
  178. %% Request headers.
  179. %% @todo
  180. %% Status codes.
  181. http10_status_code_100(Config) ->
  182. case config(protocol, Config) of
  183. http ->
  184. doc("The 100 Continue status code must not "
  185. "be sent to HTTP/1.0 endpoints. (RFC7231 6.2)"),
  186. do_http10_status_code_1xx(100, Config);
  187. http2 ->
  188. status_code_100(Config)
  189. end.
  190. http10_status_code_101(Config) ->
  191. case config(protocol, Config) of
  192. http ->
  193. doc("The 101 Switching Protocols status code must not "
  194. "be sent to HTTP/1.0 endpoints. (RFC7231 6.2)"),
  195. do_http10_status_code_1xx(101, Config);
  196. http2 ->
  197. status_code_101(Config)
  198. end.
  199. do_http10_status_code_1xx(StatusCode, Config) ->
  200. ConnPid = gun_open([{http_opts, #{version => 'HTTP/1.0'}}|Config]),
  201. Ref = gun:get(ConnPid, "/resp/inform2/" ++ integer_to_list(StatusCode), [
  202. {<<"accept-encoding">>, <<"gzip">>}
  203. ]),
  204. {response, _, 200, _} = gun:await(ConnPid, Ref),
  205. ok.
  206. status_code_100(Config) ->
  207. doc("The 100 Continue status code can be sent. (RFC7231 6.2.1)"),
  208. ConnPid = gun_open(Config),
  209. Ref = gun:get(ConnPid, "/resp/inform2/100", [
  210. {<<"accept-encoding">>, <<"gzip">>}
  211. ]),
  212. {inform, 100, []} = gun:await(ConnPid, Ref),
  213. ok.
  214. status_code_101(Config) ->
  215. doc("The 101 Switching Protocols status code can be sent. (RFC7231 6.2.2)"),
  216. ConnPid = gun_open(Config),
  217. Ref = gun:get(ConnPid, "/resp/inform2/101", [
  218. {<<"accept-encoding">>, <<"gzip">>}
  219. ]),
  220. {inform, 101, []} = gun:await(ConnPid, Ref),
  221. ok.
  222. status_code_200(Config) ->
  223. doc("The 200 OK status code can be sent. (RFC7231 6.3.1)"),
  224. ConnPid = gun_open(Config),
  225. Ref = gun:get(ConnPid, "/resp/reply2/200", [
  226. {<<"accept-encoding">>, <<"gzip">>}
  227. ]),
  228. {response, _, 200, _} = gun:await(ConnPid, Ref),
  229. ok.
  230. status_code_201(Config) ->
  231. doc("The 201 Created status code can be sent. (RFC7231 6.3.2)"),
  232. ConnPid = gun_open(Config),
  233. Ref = gun:get(ConnPid, "/resp/reply2/201", [
  234. {<<"accept-encoding">>, <<"gzip">>}
  235. ]),
  236. {response, _, 201, _} = gun:await(ConnPid, Ref),
  237. ok.
  238. status_code_202(Config) ->
  239. doc("The 202 Accepted status code can be sent. (RFC7231 6.3.3)"),
  240. ConnPid = gun_open(Config),
  241. Ref = gun:get(ConnPid, "/resp/reply2/202", [
  242. {<<"accept-encoding">>, <<"gzip">>}
  243. ]),
  244. {response, _, 202, _} = gun:await(ConnPid, Ref),
  245. ok.
  246. status_code_203(Config) ->
  247. doc("The 203 Non-Authoritative Information status code can be sent. (RFC7231 6.3.4)"),
  248. ConnPid = gun_open(Config),
  249. Ref = gun:get(ConnPid, "/resp/reply2/203", [
  250. {<<"accept-encoding">>, <<"gzip">>}
  251. ]),
  252. {response, _, 203, _} = gun:await(ConnPid, Ref),
  253. ok.
  254. status_code_204(Config) ->
  255. doc("The 204 No Content status code can be sent. (RFC7231 6.3.5)"),
  256. ConnPid = gun_open(Config),
  257. Ref = gun:get(ConnPid, "/resp/reply2/204", [
  258. {<<"accept-encoding">>, <<"gzip">>}
  259. ]),
  260. {response, _, 204, _} = gun:await(ConnPid, Ref),
  261. ok.
  262. status_code_205(Config) ->
  263. doc("The 205 Reset Content status code can be sent. (RFC7231 6.3.6)"),
  264. ConnPid = gun_open(Config),
  265. Ref = gun:get(ConnPid, "/resp/reply2/205", [
  266. {<<"accept-encoding">>, <<"gzip">>}
  267. ]),
  268. {response, _, 205, _} = gun:await(ConnPid, Ref),
  269. ok.
  270. status_code_300(Config) ->
  271. doc("The 300 Multiple Choices status code can be sent. (RFC7231 6.4.1)"),
  272. ConnPid = gun_open(Config),
  273. Ref = gun:get(ConnPid, "/resp/reply2/300", [
  274. {<<"accept-encoding">>, <<"gzip">>}
  275. ]),
  276. {response, _, 300, _} = gun:await(ConnPid, Ref),
  277. ok.
  278. status_code_301(Config) ->
  279. doc("The 301 Moved Permanently status code can be sent. (RFC7231 6.4.2)"),
  280. ConnPid = gun_open(Config),
  281. Ref = gun:get(ConnPid, "/resp/reply2/301", [
  282. {<<"accept-encoding">>, <<"gzip">>}
  283. ]),
  284. {response, _, 301, _} = gun:await(ConnPid, Ref),
  285. ok.
  286. status_code_302(Config) ->
  287. doc("The 302 Found status code can be sent. (RFC7231 6.4.3)"),
  288. ConnPid = gun_open(Config),
  289. Ref = gun:get(ConnPid, "/resp/reply2/302", [
  290. {<<"accept-encoding">>, <<"gzip">>}
  291. ]),
  292. {response, _, 302, _} = gun:await(ConnPid, Ref),
  293. ok.
  294. status_code_303(Config) ->
  295. doc("The 303 See Other status code can be sent. (RFC7231 6.4.4)"),
  296. ConnPid = gun_open(Config),
  297. Ref = gun:get(ConnPid, "/resp/reply2/303", [
  298. {<<"accept-encoding">>, <<"gzip">>}
  299. ]),
  300. {response, _, 303, _} = gun:await(ConnPid, Ref),
  301. ok.
  302. status_code_305(Config) ->
  303. doc("The 305 Use Proxy status code can be sent. (RFC7231 6.4.5)"),
  304. ConnPid = gun_open(Config),
  305. Ref = gun:get(ConnPid, "/resp/reply2/305", [
  306. {<<"accept-encoding">>, <<"gzip">>}
  307. ]),
  308. {response, _, 305, _} = gun:await(ConnPid, Ref),
  309. ok.
  310. %% The status code 306 is no longer used. (RFC7231 6.4.6)
  311. status_code_307(Config) ->
  312. doc("The 307 Temporary Redirect status code can be sent. (RFC7231 6.4.7)"),
  313. ConnPid = gun_open(Config),
  314. Ref = gun:get(ConnPid, "/resp/reply2/307", [
  315. {<<"accept-encoding">>, <<"gzip">>}
  316. ]),
  317. {response, _, 307, _} = gun:await(ConnPid, Ref),
  318. ok.
  319. status_code_400(Config) ->
  320. doc("The 400 Bad Request status code can be sent. (RFC7231 6.5.1)"),
  321. ConnPid = gun_open(Config),
  322. Ref = gun:get(ConnPid, "/resp/reply2/400", [
  323. {<<"accept-encoding">>, <<"gzip">>}
  324. ]),
  325. {response, _, 400, _} = gun:await(ConnPid, Ref),
  326. ok.
  327. status_code_402(Config) ->
  328. doc("The 402 Payment Required status code can be sent. (RFC7231 6.5.2)"),
  329. ConnPid = gun_open(Config),
  330. Ref = gun:get(ConnPid, "/resp/reply2/402", [
  331. {<<"accept-encoding">>, <<"gzip">>}
  332. ]),
  333. {response, _, 402, _} = gun:await(ConnPid, Ref),
  334. ok.
  335. status_code_403(Config) ->
  336. doc("The 403 Forbidden status code can be sent. (RFC7231 6.5.3)"),
  337. ConnPid = gun_open(Config),
  338. Ref = gun:get(ConnPid, "/resp/reply2/403", [
  339. {<<"accept-encoding">>, <<"gzip">>}
  340. ]),
  341. {response, _, 403, _} = gun:await(ConnPid, Ref),
  342. ok.
  343. status_code_404(Config) ->
  344. doc("The 404 Not Found status code can be sent. (RFC7231 6.5.4)"),
  345. ConnPid = gun_open(Config),
  346. Ref = gun:get(ConnPid, "/resp/reply2/404", [
  347. {<<"accept-encoding">>, <<"gzip">>}
  348. ]),
  349. {response, _, 404, _} = gun:await(ConnPid, Ref),
  350. ok.
  351. status_code_405(Config) ->
  352. doc("The 405 Method Not Allowed status code can be sent. (RFC7231 6.5.5)"),
  353. ConnPid = gun_open(Config),
  354. Ref = gun:get(ConnPid, "/resp/reply2/405", [
  355. {<<"accept-encoding">>, <<"gzip">>}
  356. ]),
  357. {response, _, 405, _} = gun:await(ConnPid, Ref),
  358. ok.
  359. status_code_406(Config) ->
  360. doc("The 406 Not Acceptable status code can be sent. (RFC7231 6.5.6)"),
  361. ConnPid = gun_open(Config),
  362. Ref = gun:get(ConnPid, "/resp/reply2/406", [
  363. {<<"accept-encoding">>, <<"gzip">>}
  364. ]),
  365. {response, _, 406, _} = gun:await(ConnPid, Ref),
  366. ok.
  367. status_code_408(Config) ->
  368. doc("The 408 Request Timeout status code can be sent. (RFC7231 6.5.7)"),
  369. ConnPid = gun_open(Config),
  370. Ref = gun:get(ConnPid, "/resp/reply2/408", [
  371. {<<"accept-encoding">>, <<"gzip">>}
  372. ]),
  373. {response, _, 408, _} = gun:await(ConnPid, Ref),
  374. ok.
  375. status_code_408_connection_close(Config) ->
  376. case config(protocol, Config) of
  377. http ->
  378. do_http11_status_code_408_connection_close(Config);
  379. http2 ->
  380. doc("HTTP/2 connections are not closed on 408 responses.")
  381. end.
  382. do_http11_status_code_408_connection_close(Config) ->
  383. doc("A 408 response should result in a connection close "
  384. "for HTTP/1.1 connections. (RFC7231 6.5.7)"),
  385. Client = raw_open(Config),
  386. ok = raw_send(Client, "GET / HTTP/1.1\r\n"),
  387. {_, 408, _, Rest} = cow_http:parse_status_line(raw_recv_head(Client)),
  388. {Headers, <<>>} = cow_http:parse_headers(Rest),
  389. {_, <<"close">>} = lists:keyfind(<<"connection">>, 1, Headers),
  390. {error, closed} = raw_recv(Client, 0, 1000),
  391. ok.
  392. status_code_409(Config) ->
  393. doc("The 409 Conflict status code can be sent. (RFC7231 6.5.8)"),
  394. ConnPid = gun_open(Config),
  395. Ref = gun:get(ConnPid, "/resp/reply2/409", [
  396. {<<"accept-encoding">>, <<"gzip">>}
  397. ]),
  398. {response, _, 409, _} = gun:await(ConnPid, Ref),
  399. ok.
  400. status_code_410(Config) ->
  401. doc("The 410 Gone status code can be sent. (RFC7231 6.5.9)"),
  402. ConnPid = gun_open(Config),
  403. Ref = gun:get(ConnPid, "/resp/reply2/410", [
  404. {<<"accept-encoding">>, <<"gzip">>}
  405. ]),
  406. {response, _, 410, _} = gun:await(ConnPid, Ref),
  407. ok.
  408. status_code_411(Config) ->
  409. doc("The 411 Length Required status code can be sent. (RFC7231 6.5.10)"),
  410. ConnPid = gun_open(Config),
  411. Ref = gun:get(ConnPid, "/resp/reply2/411", [
  412. {<<"accept-encoding">>, <<"gzip">>}
  413. ]),
  414. {response, _, 411, _} = gun:await(ConnPid, Ref),
  415. ok.
  416. status_code_413(Config) ->
  417. doc("The 413 Payload Too Large status code can be sent. (RFC7231 6.5.11)"),
  418. ConnPid = gun_open(Config),
  419. Ref = gun:get(ConnPid, "/resp/reply2/413", [
  420. {<<"accept-encoding">>, <<"gzip">>}
  421. ]),
  422. {response, _, 413, _} = gun:await(ConnPid, Ref),
  423. ok.
  424. status_code_414(Config) ->
  425. doc("The 414 URI Too Long status code can be sent. (RFC7231 6.5.12)"),
  426. ConnPid = gun_open(Config),
  427. Ref = gun:get(ConnPid, "/resp/reply2/414", [
  428. {<<"accept-encoding">>, <<"gzip">>}
  429. ]),
  430. {response, _, 414, _} = gun:await(ConnPid, Ref),
  431. ok.
  432. status_code_415(Config) ->
  433. doc("The 415 Unsupported Media Type status code can be sent. (RFC7231 6.5.13)"),
  434. ConnPid = gun_open(Config),
  435. Ref = gun:get(ConnPid, "/resp/reply2/415", [
  436. {<<"accept-encoding">>, <<"gzip">>}
  437. ]),
  438. {response, _, 415, _} = gun:await(ConnPid, Ref),
  439. ok.
  440. status_code_417(Config) ->
  441. doc("The 417 Expectation Failed status code can be sent. (RFC7231 6.5.14)"),
  442. ConnPid = gun_open(Config),
  443. Ref = gun:get(ConnPid, "/resp/reply2/417", [
  444. {<<"accept-encoding">>, <<"gzip">>}
  445. ]),
  446. {response, _, 417, _} = gun:await(ConnPid, Ref),
  447. ok.
  448. status_code_426(Config) ->
  449. doc("The 426 Upgrade Required status code can be sent. (RFC7231 6.5.15)"),
  450. ConnPid = gun_open(Config),
  451. Ref = gun:get(ConnPid, "/resp/reply2/426", [
  452. {<<"accept-encoding">>, <<"gzip">>}
  453. ]),
  454. {response, _, 426, _} = gun:await(ConnPid, Ref),
  455. ok.
  456. status_code_500(Config) ->
  457. doc("The 500 Internal Server Error status code can be sent. (RFC7231 6.6.1)"),
  458. ConnPid = gun_open(Config),
  459. Ref = gun:get(ConnPid, "/resp/reply2/500", [
  460. {<<"accept-encoding">>, <<"gzip">>}
  461. ]),
  462. {response, _, 500, _} = gun:await(ConnPid, Ref),
  463. ok.
  464. status_code_501(Config) ->
  465. doc("The 501 Not Implemented status code can be sent. (RFC7231 6.6.2)"),
  466. ConnPid = gun_open(Config),
  467. Ref = gun:get(ConnPid, "/resp/reply2/501", [
  468. {<<"accept-encoding">>, <<"gzip">>}
  469. ]),
  470. {response, _, 501, _} = gun:await(ConnPid, Ref),
  471. ok.
  472. status_code_502(Config) ->
  473. doc("The 502 Bad Gateway status code can be sent. (RFC7231 6.6.3)"),
  474. ConnPid = gun_open(Config),
  475. Ref = gun:get(ConnPid, "/resp/reply2/502", [
  476. {<<"accept-encoding">>, <<"gzip">>}
  477. ]),
  478. {response, _, 502, _} = gun:await(ConnPid, Ref),
  479. ok.
  480. status_code_503(Config) ->
  481. doc("The 503 Service Unavailable status code can be sent. (RFC7231 6.6.4)"),
  482. ConnPid = gun_open(Config),
  483. Ref = gun:get(ConnPid, "/resp/reply2/503", [
  484. {<<"accept-encoding">>, <<"gzip">>}
  485. ]),
  486. {response, _, 503, _} = gun:await(ConnPid, Ref),
  487. ok.
  488. status_code_504(Config) ->
  489. doc("The 504 Gateway Timeout status code can be sent. (RFC7231 6.6.5)"),
  490. ConnPid = gun_open(Config),
  491. Ref = gun:get(ConnPid, "/resp/reply2/504", [
  492. {<<"accept-encoding">>, <<"gzip">>}
  493. ]),
  494. {response, _, 504, _} = gun:await(ConnPid, Ref),
  495. ok.
  496. status_code_505(Config) ->
  497. doc("The 505 HTTP Version Not Supported status code can be sent. (RFC7231 6.6.6)"),
  498. ConnPid = gun_open(Config),
  499. Ref = gun:get(ConnPid, "/resp/reply2/505", [
  500. {<<"accept-encoding">>, <<"gzip">>}
  501. ]),
  502. {response, _, 505, _} = gun:await(ConnPid, Ref),
  503. ok.