1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Shared test-only helpers for the SM provider mock servers.
//!
//! Why: the Anthropic and OpenRouter provider tests both drive `complete`
//! against a raw `TcpListener` HTTP mock. A naive mock that does a single
//! `read` may reply before the client has finished writing the request
//! (headers + body), which surfaces as intermittent connection-reset flakiness.
//! Centralising a robust "read the whole request first" helper keeps both mocks
//! deterministic without pulling in an external mock-server crate.
//! What: [`read_full_request`] loops reading from the socket until the HTTP
//! header terminator (`\r\n\r\n`) is seen, then drains any declared
//! `Content-Length` body bytes, so the server only replies once the full
//! request has arrived.
//! Test: exercised transitively by every `complete_*` provider round-trip test.
use AsyncReadExt;
use TcpStream;
/// Read an entire HTTP/1.1 request (headers + any `Content-Length` body) from
/// `sock` before the caller writes a response.
///
/// Why: a single `sock.read()` can return before the client has flushed the
/// full request, letting the mock reply early and reset the connection — the
/// source of the flaky-mock finding. Reading to the header terminator (and then
/// the declared body) makes the mock wait for the complete request.
/// What: appends reads into a buffer until `\r\n\r\n` appears, parses an
/// optional case-insensitive `Content-Length`, then keeps reading until the
/// buffer holds the full header + body (or the peer closes / errors). All I/O
/// errors are swallowed: this is a best-effort test mock, and the assertions
/// live in the response path.
/// Test: used by the Anthropic + OpenRouter `complete_*` tests.
pub async
/// Return the byte offset just past the `\r\n\r\n` header terminator, if present.
///
/// Why: marks where headers end and the body begins.
/// What: scans for the 4-byte CRLFCRLF sequence; returns `Some(end)` past it.
/// Test: exercised via [`read_full_request`].
/// Parse a case-insensitive `Content-Length` header value from header bytes.
///
/// Why: lets the mock drain the full request body before replying.
/// What: scans CRLF-delimited header lines for `content-length:` and parses the
/// decimal value; returns `0` when absent or unparseable.
/// Test: exercised via [`read_full_request`].