diff --git a/lib/mint/http.ex b/lib/mint/http.ex index 2021fc7e..d0009662 100644 --- a/lib/mint/http.ex +++ b/lib/mint/http.ex @@ -900,6 +900,11 @@ defmodule Mint.HTTP do Contrary to `recv/3`, this function does not return partial responses on errors. Use `recv/3` for full control. + > #### Error {: .error} + > + > This function can only be used for one-off requests. If there is another concurrent request, + > started by `request/5`, it will crash. + ## Options * `:timeout` - the maximum amount of time in milliseconds waiting to receive the response. @@ -979,8 +984,9 @@ defmodule Mint.HTTP do end # Ignore entries from other requests. - defp recv_response([_entry | rest], acc, conn, ref, timeout) do - recv_response(rest, acc, conn, ref, timeout) + defp recv_response([entry | _rest], _acc, _conn, _ref, _timeout) when is_tuple(entry) do + ref = elem(entry, 1) + raise "received unexpected response from request #{inspect(ref)}" end defp recv_response([], acc, conn, ref, timeout) do diff --git a/test/mint/http1/conn_test.exs b/test/mint/http1/conn_test.exs index 0c7ec945..0f765010 100644 --- a/test/mint/http1/conn_test.exs +++ b/test/mint/http1/conn_test.exs @@ -528,6 +528,28 @@ defmodule Mint.HTTP1Test do refute HTTP1.open?(conn) end + + test "raises on multiple requests " do + {:ok, port, server_ref} = + TestServer.start(fn %{socket: socket} -> + :ok = :gen_tcp.send(socket, "HTTP/1.1 200 OK\r\n") + :ok = :gen_tcp.send(socket, "content-type: text/plain\r\n") + :ok = :gen_tcp.send(socket, "content-length: 10\r\n\r\n") + :ok = :gen_tcp.send(socket, "hello") + :ok = :gen_tcp.send(socket, "world") + end) + + assert {:ok, conn} = HTTP1.connect(:http, "localhost", port, mode: :passive) + assert_receive {^server_ref, _server_socket} + + {:ok, conn, ref} = Mint.HTTP.request(conn, "GET", "/", [], nil) + + assert_raise RuntimeError, + "received unexpected response from request #{inspect(ref)}", + fn -> + Mint.HTTP.request_and_response(conn, "GET", "/", [], nil) + end + end end test "changing the connection mode with set_mode/2", diff --git a/test/support/mint/http1/test_server.ex b/test/support/mint/http1/test_server.ex index 79632fa0..1a1e2533 100644 --- a/test/support/mint/http1/test_server.ex +++ b/test/support/mint/http1/test_server.ex @@ -1,17 +1,17 @@ defmodule Mint.HTTP1.TestServer do - def start do + def start(fun \\ nil) do {:ok, listen_socket} = :gen_tcp.listen(0, mode: :binary, packet: :raw) server_ref = make_ref() parent = self() - spawn_link(fn -> loop(listen_socket, parent, server_ref) end) + spawn_link(fn -> loop(listen_socket, parent, server_ref, fun) end) with {:ok, port} <- :inet.port(listen_socket) do {:ok, port, server_ref} end end - defp loop(listen_socket, parent, server_ref) do + defp loop(listen_socket, parent, server_ref, fun) do case :gen_tcp.accept(listen_socket) do {:ok, socket} -> send(parent, {server_ref, socket}) @@ -22,7 +22,11 @@ defmodule Mint.HTTP1.TestServer do {:error, :einval} -> :ok end - loop(listen_socket, parent, server_ref) + if fun do + fun.(%{socket: socket, parent: parent}) + end + + loop(listen_socket, parent, server_ref, fun) {:error, :closed} -> :ok