+{
+ my $conn = conn_for($sock, 'streaming callback');
+ $conn->write("GET /callback HTTP/1.0\r\n\r\n");
+ ok($conn->read(my $buf, 8192), 'read response');
+ my ($head, $body) = split(/\r\n\r\n/, $buf);
+ is($body, "hello world\n", 'callback body matches expected');
+}
+
+{
+ my $conn = conn_for($sock, 'getline-die');
+ $conn->write("GET /getline-die HTTP/1.1\r\nHost: example.com\r\n\r\n");
+ ok($conn->read(my $buf, 8192), 'read some response');
+ like($buf, qr!HTTP/1\.1 200\b[^\r]*\r\n!, 'got some sort of header');
+ is($conn->read(my $nil, 8192), 0, 'read EOF');
+ $conn = undef;
+ my $after = capture($err);
+ is(scalar(grep(/GETLINE FAIL/, @$after)), 1, 'failure logged');
+ is(scalar(grep(/CLOSE FAIL/, @$after)), 1, 'body->close not called');
+}
+
+{
+ my $conn = conn_for($sock, 'close-die');
+ $conn->write("GET /close-die HTTP/1.1\r\nHost: example.com\r\n\r\n");
+ ok($conn->read(my $buf, 8192), 'read some response');
+ like($buf, qr!HTTP/1\.1 200\b[^\r]*\r\n!, 'got some sort of header');
+ is($conn->read(my $nil, 8192), 0, 'read EOF');
+ $conn = undef;
+ my $after = capture($err);
+ is(scalar(grep(/GETLINE FAIL/, @$after)), 0, 'getline not failed');
+ is(scalar(grep(/CLOSE FAIL/, @$after)), 1, 'body->close not called');
+}
+
+{
+ my $conn = conn_for($sock, 'excessive header');
+ $SIG{PIPE} = 'IGNORE';
+ $conn->write("GET /callback HTTP/1.0\r\n");
+ foreach my $i (1..500000) {
+ last unless $conn->write("X-xxxxxJunk-$i: omg\r\n");
+ }
+ ok(!$conn->write("\r\n"), 'broken request');
+ ok($conn->read(my $buf, 8192), 'read response');
+ my ($head, $body) = split(/\r\n\r\n/, $buf);
+ like($head, qr/\b400\b/, 'got 400 response');
+}
+
+{
+ my $conn = conn_for($sock, 'excessive body Content-Length');
+ $SIG{PIPE} = 'IGNORE';
+ my $n = (10 * 1024 * 1024) + 1;
+ $conn->write("PUT /sha1 HTTP/1.0\r\nContent-Length: $n\r\n\r\n");
+ ok($conn->read(my $buf, 8192), 'read response');
+ my ($head, $body) = split(/\r\n\r\n/, $buf);
+ like($head, qr/\b413\b/, 'got 413 response');
+}
+
+{
+ my $conn = conn_for($sock, 'excessive body chunked');
+ $SIG{PIPE} = 'IGNORE';
+ my $n = (10 * 1024 * 1024) + 1;
+ $conn->write("PUT /sha1 HTTP/1.1\r\nTransfer-Encoding: chunked\r\n");
+ $conn->write("\r\n".sprintf("%x\r\n", $n));
+ ok($conn->read(my $buf, 8192), 'read response');
+ my ($head, $body) = split(/\r\n\r\n/, $buf);
+ like($head, qr/\b413\b/, 'got 413 response');
+}
+
+# Unix domain sockets
+{
+ my $u = IO::Socket::UNIX->new(Type => SOCK_STREAM, Peer => $upath);
+ ok($u, 'unix socket connected');
+ $u->write("GET /host-port HTTP/1.0\r\n\r\n");
+ $u->read(my $buf, 4096);
+ like($buf, qr!\r\n\r\n127\.0\.0\.1:0\z!,
+ 'set REMOTE_ADDR and REMOTE_PORT for Unix socket');
+}
+