Skip to content

Commit 90142af

Browse files
committed
Rename to Mint.HTTP.request_and_response/6
1 parent 2c10fca commit 90142af

File tree

4 files changed

+152
-105
lines changed

4 files changed

+152
-105
lines changed

lib/mint/http.ex

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -876,14 +876,11 @@ defmodule Mint.HTTP do
876876
@version Mix.Project.config()[:version]
877877

878878
@doc """
879-
Receives response from the socket in a blocking way.
879+
Sends a request and receives a response from the socket in a blocking way.
880880
881-
This function receives a response for the request identified by `request_ref` on the connection
882-
`conn`.
881+
This function is a convenience for sending a request with `request/5` and repeatedly calling `recv/3`.
883882
884-
`timeout` is the maximum time to wait before returning an error.
885-
886-
This function is a convenience for repeatedly calling `Mint.HTTP.recv/3`. The result is either:
883+
The result is either:
887884
888885
* `{:ok, conn, response}` where `conn` is the updated connection and `response` is a map
889886
with the following keys:
@@ -903,30 +900,48 @@ defmodule Mint.HTTP do
903900
Contrary to `recv/3`, this function does not return partial responses on errors. Use
904901
`recv/3` for full control.
905902
906-
This function only handles responses for the given `request_ref`. Do not use it when making
907-
concurrent requests as responses other than for `request_ref` are ignored.
903+
## Options
904+
905+
* `:timeout` - the maximum amount of time in milliseconds waiting to receive the response.
906+
Setting to `:infinity`, disables the timeout. Defaults to `:infinity`.
908907
909908
## Examples
910909
911910
iex> {:ok, conn} = Mint.HTTP.connect(:https, "httpbin.org", 443, mode: :passive)
912-
iex> {:ok, conn, request_ref} = Mint.HTTP.request(conn, "GET", "/user-agent", [], nil)
913-
iex> {:ok, _conn, response} = Mint.HTTP.recv_response(conn, request_ref, 5000)
911+
iex> {:ok, conn, response} = Mint.HTTP.request_and_response(conn, "GET", "/user-agent", [], nil)
914912
iex> response
915913
%{
916914
status: 200,
917915
headers: [{"date", ...}, ...],
918916
body: "{\\n \\"user-agent\\": \\"#{@version}\\"\\n}\\n"
919917
}
918+
iex> Mint.HTTP.open?(conn)
919+
true
920920
"""
921-
@spec recv_response(t(), Types.request_ref(), timeout()) ::
922-
{:ok, t(), response} | {:error, Types.error()}
921+
@spec request_and_response(
922+
t(),
923+
method :: String.t(),
924+
path :: String.t(),
925+
Types.headers(),
926+
body :: iodata() | nil | :stream,
927+
options :: [{:timeout, timeout()}]
928+
) ::
929+
{:ok, t(), response}
930+
| {:error, t(), Types.error()}
923931
when response: %{
924932
status: non_neg_integer(),
925933
headers: [{binary(), binary()}],
926934
body: binary()
927935
}
928-
def recv_response(conn, request_ref, timeout)
929-
when is_reference(request_ref) and Util.is_timeout(timeout) do
936+
def request_and_response(conn, method, path, headers, body, options \\ []) do
937+
options = Keyword.validate!(options, timeout: :infinity)
938+
939+
with {:ok, conn, ref} <- request(conn, method, path, headers, body) do
940+
recv_response(conn, ref, options[:timeout])
941+
end
942+
end
943+
944+
defp recv_response(conn, request_ref, timeout) when Util.is_timeout(timeout) do
930945
recv_response([], {nil, [], ""}, conn, request_ref, timeout)
931946
end
932947

test/http_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
defmodule Mint.HTTPTest do
22
use ExUnit.Case, async: true
3-
doctest Mint.HTTP, except: [recv_response: 3]
3+
doctest Mint.HTTP, except: [request_and_response: 6]
44
end

test/mint/http1/conn_test.exs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -460,42 +460,40 @@ defmodule Mint.HTTP1Test do
460460
assert responses == [{:status, ref, 200}]
461461
end
462462

463-
describe "Mint.HTTP.recv_response/3" do
463+
describe "Mint.HTTP.request_and_response/6" do
464464
test "receives response", %{port: port, server_ref: server_ref} do
465465
assert {:ok, conn} = HTTP1.connect(:http, "localhost", port, mode: :passive)
466466
assert_receive {^server_ref, server_socket}
467467

468-
{:ok, conn, ref} = HTTP1.request(conn, "GET", "/", [], nil)
469-
470468
:ok = :gen_tcp.send(server_socket, "HTTP/1.1 200 OK\r\n")
471469
:ok = :gen_tcp.send(server_socket, "content-type: text/plain\r\n")
472470
:ok = :gen_tcp.send(server_socket, "content-length: 10\r\n\r\n")
473471
:ok = :gen_tcp.send(server_socket, "hello")
474472
:ok = :gen_tcp.send(server_socket, "world")
475473

476-
assert {:ok, _conn, response} = Mint.HTTP.recv_response(conn, ref, 100)
474+
{:ok, conn, response} = Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
477475

478476
assert response == %{
479477
body: "helloworld",
480478
headers: [{"content-type", "text/plain"}, {"content-length", "10"}],
481479
status: 200
482480
}
481+
482+
assert HTTP1.open?(conn)
483483
end
484484

485485
test "handles trailers", %{port: port, server_ref: server_ref} do
486486
assert {:ok, conn} = HTTP1.connect(:http, "localhost", port, mode: :passive)
487487
assert_receive {^server_ref, server_socket}
488488

489-
{:ok, conn, ref} = HTTP1.request(conn, "GET", "/", [], nil)
490-
491489
:ok = :gen_tcp.send(server_socket, "HTTP/1.1 200 OK\r\n")
492490
:ok = :gen_tcp.send(server_socket, "transfer-encoding: chunked\r\n")
493491
:ok = :gen_tcp.send(server_socket, "trailer: x-trailer\r\n\r\n")
494492
:ok = :gen_tcp.send(server_socket, "5\r\nhello\r\n")
495493
:ok = :gen_tcp.send(server_socket, "5\r\nworld\r\n0\r\n")
496494
:ok = :gen_tcp.send(server_socket, "x-trailer: foo\r\n\r\n")
497495

498-
assert {:ok, _conn, response} = Mint.HTTP.recv_response(conn, ref, 100)
496+
{:ok, conn, response} = Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
499497

500498
assert response == %{
501499
body: "helloworld",
@@ -506,29 +504,29 @@ defmodule Mint.HTTP1Test do
506504
],
507505
status: 200
508506
}
507+
508+
assert HTTP1.open?(conn)
509509
end
510510

511511
test "handles errors", %{port: port, server_ref: server_ref} do
512512
assert {:ok, conn} = HTTP1.connect(:http, "localhost", port, mode: :passive)
513513
assert_receive {^server_ref, server_socket}
514514

515-
{:ok, conn, ref} = HTTP1.request(conn, "GET", "/", [], nil)
516-
517515
:ok = :gen_tcp.send(server_socket, "HTTP/1.1 200 OK\r\n")
518516
:ok = :gen_tcp.close(server_socket)
519517

520518
assert {:error, _conn, %Mint.TransportError{reason: :closed}} =
521-
Mint.HTTP.recv_response(conn, ref, 100)
519+
Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
522520
end
523521

524522
test "handles timeout", %{port: port, server_ref: server_ref} do
525523
assert {:ok, conn} = HTTP1.connect(:http, "localhost", port, mode: :passive)
526524
assert_receive {^server_ref, _server_socket}
527525

528-
{:ok, conn, ref} = HTTP1.request(conn, "GET", "/", [], nil)
526+
assert {:error, conn, %Mint.TransportError{reason: :timeout}} =
527+
Mint.HTTP.request_and_response(conn, "GET", "/", [], nil, timeout: 0)
529528

530-
assert {:error, _conn, %Mint.TransportError{reason: :timeout}} =
531-
Mint.HTTP.recv_response(conn, ref, 1)
529+
refute HTTP1.open?(conn)
532530
end
533531
end
534532

test/mint/http2/conn_test.exs

Lines changed: 111 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,35 +2167,44 @@ defmodule Mint.HTTP2Test do
21672167
end
21682168
end
21692169

2170-
describe "Mint.HTTP.recv_response/3" do
2170+
describe "Mint.HTTP.request_and_response/6" do
21712171
@describetag connect_options: [mode: :passive]
21722172

2173-
test "receives response", %{conn: conn} do
2174-
{conn, ref} = open_request(conn)
2175-
2176-
assert_recv_frames [headers(stream_id: stream_id)]
2177-
2178-
data =
2179-
server_encode_frames([
2180-
headers(
2181-
stream_id: stream_id,
2182-
hbf:
2183-
server_encode_headers([
2184-
{":status", "200"},
2185-
{"content-type", "text/plain"},
2186-
{"content-length", "10"}
2187-
]),
2188-
flags: set_flags(:headers, [:end_headers])
2189-
),
2190-
data(
2191-
stream_id: stream_id,
2192-
data: "helloworld",
2193-
flags: set_flags(:data, [:end_stream])
2194-
)
2195-
])
2173+
test "receives response", context do
2174+
pid = self()
2175+
2176+
Task.start_link(fn ->
2177+
context = Map.merge(context, start_server_async(context))
2178+
[conn: conn] = start_connection(context)
2179+
send(pid, {:conn, conn})
2180+
2181+
assert_recv_frames [headers(stream_id: stream_id)]
2182+
2183+
data =
2184+
server_encode_frames([
2185+
headers(
2186+
stream_id: stream_id,
2187+
hbf:
2188+
server_encode_headers([
2189+
{":status", "200"},
2190+
{"content-type", "text/plain"},
2191+
{"content-length", "10"}
2192+
]),
2193+
flags: set_flags(:headers, [:end_headers])
2194+
),
2195+
data(
2196+
stream_id: stream_id,
2197+
data: "helloworld",
2198+
flags: set_flags(:data, [:end_stream])
2199+
)
2200+
])
2201+
2202+
:ok = :ssl.send(server_get_socket(), data)
2203+
Process.sleep(:infinity)
2204+
end)
21962205

2197-
:ok = :ssl.send(server_get_socket(), data)
2198-
assert {:ok, _conn, response} = Mint.HTTP.recv_response(conn, ref, 100)
2206+
assert_receive {:conn, conn}
2207+
assert {:ok, conn, response} = Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
21992208

22002209
assert response == %{
22012210
body: "helloworld",
@@ -2206,45 +2215,53 @@ defmodule Mint.HTTP2Test do
22062215
assert HTTP2.open?(conn)
22072216
end
22082217

2209-
test "handles trailers", %{conn: conn} do
2210-
{conn, ref} = open_request(conn)
2211-
2212-
assert_recv_frames [headers(stream_id: stream_id)]
2213-
2214-
<<trailer_hbf1::1-bytes, trailer_hbf2::binary>> =
2215-
server_encode_headers([{"x-trailer", "foo"}])
2216-
2217-
data =
2218-
server_encode_frames([
2219-
headers(
2220-
stream_id: stream_id,
2221-
hbf:
2222-
server_encode_headers([
2223-
{":status", "200"},
2224-
{"content-type", "text/plain"}
2225-
]),
2226-
flags: set_flags(:headers, [:end_headers])
2227-
),
2228-
data(
2229-
stream_id: stream_id,
2230-
data: "helloworld",
2231-
flags: set_flags(:data, [])
2232-
),
2233-
headers(
2234-
stream_id: stream_id,
2235-
hbf: trailer_hbf1,
2236-
flags: set_flags(:headers, [:end_stream])
2237-
),
2238-
continuation(
2239-
stream_id: stream_id,
2240-
hbf: trailer_hbf2,
2241-
flags: set_flags(:continuation, [:end_headers])
2242-
)
2243-
])
2244-
2245-
:ok = :ssl.send(server_get_socket(), data)
2218+
test "handles trailers", context do
2219+
pid = self()
2220+
2221+
Task.start_link(fn ->
2222+
context = Map.merge(context, start_server_async(context))
2223+
[conn: conn] = start_connection(context)
2224+
send(pid, {:conn, conn})
2225+
2226+
assert_recv_frames [headers(stream_id: stream_id)]
2227+
2228+
<<trailer_hbf1::1-bytes, trailer_hbf2::binary>> =
2229+
server_encode_headers([{"x-trailer", "foo"}])
2230+
2231+
data =
2232+
server_encode_frames([
2233+
headers(
2234+
stream_id: stream_id,
2235+
hbf:
2236+
server_encode_headers([
2237+
{":status", "200"},
2238+
{"content-type", "text/plain"}
2239+
]),
2240+
flags: set_flags(:headers, [:end_headers])
2241+
),
2242+
data(
2243+
stream_id: stream_id,
2244+
data: "helloworld",
2245+
flags: set_flags(:data, [])
2246+
),
2247+
headers(
2248+
stream_id: stream_id,
2249+
hbf: trailer_hbf1,
2250+
flags: set_flags(:headers, [:end_stream])
2251+
),
2252+
continuation(
2253+
stream_id: stream_id,
2254+
hbf: trailer_hbf2,
2255+
flags: set_flags(:continuation, [:end_headers])
2256+
)
2257+
])
2258+
2259+
:ok = :ssl.send(server_get_socket(), data)
2260+
Process.sleep(:infinity)
2261+
end)
22462262

2247-
assert {:ok, _conn, response} = Mint.HTTP.recv_response(conn, ref, 100)
2263+
assert_receive {:conn, conn}
2264+
assert {:ok, conn, response} = Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
22482265

22492266
assert response == %{
22502267
body: "helloworld",
@@ -2255,25 +2272,42 @@ defmodule Mint.HTTP2Test do
22552272
assert HTTP2.open?(conn)
22562273
end
22572274

2258-
test "handles errors", %{conn: conn} do
2259-
{conn, ref} = open_request(conn)
2260-
assert_recv_frames [headers(stream_id: _stream_id)]
2261-
:ok = :ssl.close(server_get_socket())
2275+
test "handles errors", context do
2276+
pid = self()
22622277

2263-
assert {:error, _conn, %Mint.TransportError{reason: :closed}} =
2264-
Mint.HTTP.recv_response(conn, ref, 100)
2278+
Task.start_link(fn ->
2279+
context = Map.merge(context, start_server_async(context))
2280+
[conn: conn] = start_connection(context)
2281+
send(pid, {:conn, conn})
22652282

2266-
assert HTTP2.open?(conn)
2283+
assert_recv_frames [headers(stream_id: _stream_id)]
2284+
:ok = :ssl.close(server_get_socket())
2285+
end)
2286+
2287+
assert_receive {:conn, conn}
2288+
2289+
assert {:error, conn, %Mint.TransportError{reason: :closed}} =
2290+
Mint.HTTP.request_and_response(conn, "GET", "/", [], nil)
2291+
2292+
refute HTTP2.open?(conn)
22672293
end
22682294

2269-
test "handles timeout", %{conn: conn} do
2270-
{conn, ref} = open_request(conn)
2271-
assert_recv_frames [headers(stream_id: _stream_id)]
2295+
test "handles timeout", context do
2296+
pid = self()
22722297

2273-
assert {:error, _conn, %Mint.TransportError{reason: :timeout}} =
2274-
Mint.HTTP.recv_response(conn, ref, 1)
2298+
Task.start_link(fn ->
2299+
context = Map.merge(context, start_server_async(context))
2300+
[conn: conn] = start_connection(context)
2301+
send(pid, {:conn, conn})
2302+
Process.sleep(:infinity)
2303+
end)
22752304

2276-
assert HTTP2.open?(conn)
2305+
assert_receive {:conn, conn}
2306+
2307+
assert {:error, conn, %Mint.TransportError{reason: :timeout}} =
2308+
Mint.HTTP.request_and_response(conn, "GET", "/", [], nil, timeout: 0)
2309+
2310+
refute HTTP2.open?(conn)
22772311
end
22782312
end
22792313

0 commit comments

Comments
 (0)