Skip to content

Commit 1b3ef6b

Browse files
committed
Port protocol-level stale-conn test from #666
Covers a read_body whose returned conn is dropped, followed by a second request arriving mangled on the same connection, and a stale conn reused for a second read_body call. Ported per request on #649.
1 parent bf6a918 commit 1b3ef6b

1 file changed

Lines changed: 52 additions & 0 deletions

File tree

test/bandit/http1/protocol_test.exs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,58 @@ defmodule HTTP1ProtocolTest do
815815
send_resp(conn, 200, "#{first},#{second},#{third}")
816816
end
817817

818+
@tag :capture_log
819+
test "rejects a stale conn after an incremental body read", context do
820+
client = SimpleHTTP1Client.tcp_client(context)
821+
822+
Transport.send(
823+
client,
824+
"POST /respond_with_stale_conn HTTP/1.1\r\nhost: localhost\r\ncontent-length: 5\r\n\r\nAB"
825+
)
826+
827+
Process.sleep(10)
828+
829+
Transport.send(
830+
client,
831+
"CDEGET /echo_method HTTP/1.1\r\nhost: localhost\r\n\r\n"
832+
)
833+
834+
assert {:ok, "500 Internal Server Error", headers, ""} =
835+
SimpleHTTP1Client.recv_reply(client)
836+
837+
assert Bandit.Headers.get_header(headers, :connection) == "close"
838+
assert SimpleHTTP1Client.connection_closed_for_reading?(client)
839+
840+
assert_receive {:log, %{level: :error, msg: {:string, msg}}}, 500
841+
assert msg =~ "** (RuntimeError) Stale conn passed to a Plug.Conn function."
842+
end
843+
844+
def respond_with_stale_conn(conn) do
845+
{:more, "ABC", _conn} = Plug.Conn.read_body(conn, length: 3)
846+
send_resp(conn, 200, "should not be sent")
847+
end
848+
849+
@tag :capture_log
850+
test "rejects an earlier conn for another body read", context do
851+
client = SimpleHTTP1Client.tcp_client(context)
852+
853+
Transport.send(
854+
client,
855+
"POST /read_body_with_stale_conn HTTP/1.1\r\nhost: localhost\r\ncontent-length: 2\r\n\r\nAB"
856+
)
857+
858+
assert {:ok, "500 Internal Server Error", _, ""} = SimpleHTTP1Client.recv_reply(client)
859+
assert SimpleHTTP1Client.connection_closed_for_reading?(client)
860+
861+
assert_receive {:log, %{level: :error, msg: {:string, msg}}}, 500
862+
assert msg =~ "** (RuntimeError) Stale conn passed to a Plug.Conn function."
863+
end
864+
865+
def read_body_with_stale_conn(conn) do
866+
{:more, "A", _conn} = Plug.Conn.read_body(conn, length: 1)
867+
Plug.Conn.read_body(conn)
868+
end
869+
818870
test "handles the case where we read from the network in smaller chunks than we return",
819871
context do
820872
client = SimpleHTTP1Client.tcp_client(context)

0 commit comments

Comments
 (0)