Skip to main content

http_net/
client.rs

1//! The client side of an HTTP/1.1 connection, without I/O.
2
3use alloc::vec::Vec;
4
5use crate::{
6    body::{Decoder, Encoder, Step, push_framing},
7    buffer::Buffer,
8    error::HttpError,
9    head::{
10        Asked, HeadKind, HeadScanner, Headers, ResponseHead, ResponseInfo, Scan,
11        interpret_response, switches_to_offered,
12    },
13    limits::{Limits, MAX_PIPELINE_DEPTH},
14    message::{OutBody, Request, check_trailers, push_last_chunk_with_trailers},
15    method::Method,
16    scan::find_byte,
17    server::Progress,
18};
19
20/// The error for sending a body the server declined (a final status in
21/// answer to `Expect: 100-continue`).
22const REFUSED: HttpError = HttpError::InvalidState(
23    "the server answered with a final status instead of 100 Continue; \
24     the body must not be sent",
25);
26
27/// What a [`ClientConn`] has for the caller after [`poll`](ClientConn::poll).
28///
29/// # Examples
30///
31/// ```
32/// use http_net::{ClientConn, ClientEvent, Request};
33///
34/// let mut conn = ClientConn::new();
35/// let mut out = Vec::new();
36/// conn.send_request(&Request::get("/").header("host", "example.com"), &mut out).unwrap();
37/// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n3\r\nabc\r\n0\r\n\r\n");
38/// let mut body = Vec::new();
39/// loop {
40///     match conn.poll().unwrap() {
41///         ClientEvent::Response(resp) => assert_eq!(resp.status(), 200),
42///         ClientEvent::Body(chunk) => body.extend_from_slice(chunk),
43///         ClientEvent::ResponseEnd => break,
44///         other => panic!("{other:?}"),
45///     }
46/// }
47/// assert_eq!(body, b"abc");
48/// ```
49#[non_exhaustive]
50#[derive(Debug)]
51pub enum ClientEvent<'a> {
52    /// The final response head arrived. Its body follows as
53    /// [`Body`](ClientEvent::Body) events, then
54    /// [`ResponseEnd`](ClientEvent::ResponseEnd). Interim (1xx) responses
55    /// before it are skipped unless
56    /// [`set_report_informational`](ClientConn::set_report_informational)
57    /// asked for them; either way they count against
58    /// [`Limits::max_interim`](crate::Limits::max_interim) and, together,
59    /// [`Limits::max_header_bytes`](crate::Limits::max_header_bytes).
60    Response(ResponseHead<'a>),
61    /// An interim response other than `101` (for example `103 Early Hints`,
62    /// or `102 Processing`), only with
63    /// [`set_report_informational(true)`](ClientConn::set_report_informational).
64    /// The final response follows.
65    Informational(ResponseHead<'a>),
66    /// The server answered `100 Continue` to a request built with
67    /// [`Request::expect_continue`](crate::Request::expect_continue): send
68    /// the body now.
69    Continue,
70    /// A run of body bytes, after chunked decoding.
71    Body(&'a [u8]),
72    /// The response's trailer fields, just before
73    /// [`ResponseEnd`](ClientEvent::ResponseEnd): only with
74    /// [`set_report_trailers(true)`](ClientConn::set_report_trailers) and a
75    /// non-empty trailer section.
76    Trailers(Headers<'a>),
77    /// The response is complete.
78    ResponseEnd,
79    /// More input is needed (or, for a body that runs until close,
80    /// [`feed_eof`](ClientConn::feed_eof) once the server closes).
81    NeedInput,
82    /// No request is outstanding; send the next one.
83    Idle,
84    /// The server switched protocols (101 to an upgrade request, or 2xx to
85    /// `CONNECT`); the response head was reported just before. Bytes of the
86    /// new protocol that already arrived are in
87    /// [`remaining_input`](ClientConn::remaining_input).
88    Upgraded,
89    /// The connection cannot carry another request: close the socket.
90    Closed,
91}
92
93/// Opt-in tolerances for responses a strict client would refuse. All are
94/// off by default; requests are never parsed leniently.
95///
96/// - `obs_fold_in_responses`: replace each obsolete line fold in a response
97///   head (a field line continued on the next line, which begins with a
98///   space or tab) by overwriting the fold's CR and LF with spaces, as RFC
99///   9112 section 5.2 tells a user agent to do. The rewrite happens in
100///   place in the connection's buffer, so offsets do not move, views stay
101///   borrowed, and nothing is allocated. Whitespace before the first field
102///   is still refused.
103///
104/// Bare LF, bare CR, `Content-Length` with `Transfer-Encoding`, and
105/// whitespace before a colon are never tolerated: they are how messages
106/// get framed differently by different hops.
107///
108/// # Examples
109///
110/// ```
111/// use http_net::{ClientConn, ClientEvent, ClientLeniency, Request};
112///
113/// let mut conn = ClientConn::new();
114/// conn.set_leniency(ClientLeniency::new().with_obs_fold_in_responses(true));
115/// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
116/// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nX-Long: part one,\r\n part two\r\nContent-Length: 0\r\n\r\n");
117/// let ClientEvent::Response(resp) = conn.poll()? else { panic!() };
118/// assert_eq!(resp.header("x-long"), Some(&b"part one,   part two"[..]));
119/// # Ok::<(), http_net::HttpError>(())
120/// ```
121#[non_exhaustive]
122#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
123pub struct ClientLeniency {
124    /// Replace obs-folds in response fields with spaces instead of refusing
125    /// them with [`HttpError::ObsFold`].
126    pub obs_fold_in_responses: bool,
127}
128
129impl ClientLeniency {
130    /// Every tolerance off (the strict default).
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// assert!(!http_net::ClientLeniency::new().obs_fold_in_responses);
136    /// ```
137    #[must_use]
138    pub const fn new() -> Self {
139        Self {
140            obs_fold_in_responses: false,
141        }
142    }
143
144    /// Sets [`obs_fold_in_responses`](Self::obs_fold_in_responses).
145    ///
146    /// # Examples
147    ///
148    /// ```
149    /// let l = http_net::ClientLeniency::new().with_obs_fold_in_responses(true);
150    /// assert!(l.obs_fold_in_responses);
151    /// ```
152    #[must_use]
153    pub const fn with_obs_fold_in_responses(mut self, on: bool) -> Self {
154        self.obs_fold_in_responses = on;
155        self
156    }
157}
158
159/// The in-place obs-fold rewrite of one response head. It walks the head's
160/// line ends once, overall linear however the input is split, and tells the
161/// head scanner how much it may see: a line end whose next byte has not
162/// arrived is held back, because only that byte says whether the line is
163/// folded. The scanner therefore never completes a field line that is about
164/// to be continued.
165#[derive(Clone, Copy, Debug)]
166struct Unfold {
167    /// Where the search for the next LF resumes.
168    scan: usize,
169    /// Start of the line being examined.
170    line_start: usize,
171    /// The status line has ended (it is never folded).
172    past_status: bool,
173    /// The blank line that ends the head was seen.
174    done: bool,
175}
176
177impl Unfold {
178    const fn new() -> Self {
179        Self {
180            scan: 0,
181            line_start: 0,
182            past_status: false,
183            done: false,
184        }
185    }
186
187    /// Rewrites the folds found in `msg` (the head so far) and returns how
188    /// many of its bytes the head scanner may examine.
189    fn run(&mut self, msg: &mut [u8], eof: bool) -> usize {
190        if self.done {
191            return msg.len();
192        }
193        loop {
194            let Some(off) = msg.get(self.scan..).and_then(|rest| find_byte(b'\n', rest)) else {
195                self.scan = msg.len();
196                return msg.len();
197            };
198            let lf = self.scan + off;
199            if !self.past_status {
200                self.past_status = true;
201                self.line_start = lf + 1;
202                self.scan = lf + 1;
203                continue;
204            }
205            // line_start <= lf: it only ever moves to just past an LF.
206            let line = msg.get(self.line_start..lf).unwrap_or(&[]);
207            if line.is_empty() || line == b"\r" {
208                self.done = true;
209                return msg.len();
210            }
211            let crlf = lf > 0 && msg.get(lf - 1) == Some(&b'\r');
212            match msg.get(lf + 1) {
213                None if eof => {
214                    self.scan = msg.len();
215                    return msg.len();
216                }
217                None => {
218                    // Revisit this LF once its next byte arrives.
219                    self.scan = lf;
220                    return lf;
221                }
222                Some(&b) if crlf && (b == b' ' || b == b'\t') => {
223                    // RFC 9112 section 5.2: replace the fold with SP. The
224                    // line goes on, so its start stays where it was.
225                    msg[lf - 1] = b' ';
226                    msg[lf] = b' ';
227                    self.scan = lf + 1;
228                }
229                Some(_) => {
230                    self.line_start = lf + 1;
231                    self.scan = lf + 1;
232                }
233            }
234        }
235    }
236}
237
238#[derive(Clone, Copy, Debug, PartialEq, Eq)]
239enum State {
240    Idle,
241    Head,
242    /// An interim head was reported and is still pinned; the next poll
243    /// drops it and waits for the next head.
244    Interim,
245    Body,
246    Complete,
247    Upgraded,
248    Closed,
249}
250
251#[derive(Clone, Copy, Debug, PartialEq, Eq)]
252enum ReqWrite {
253    Streaming(Encoder),
254    Sent,
255}
256
257/// The client side of one HTTP/1.1 connection: a sans-IO state machine.
258///
259/// By default one request is outstanding at a time; with
260/// [`Limits::with_pipeline_depth`], idempotent requests may be pipelined
261/// behind it (see [`can_send`](Self::can_send)).
262/// [`send_request`](Self::send_request)
263/// serializes a [`Request`]; [`feed`](Self::feed) and [`poll`](Self::poll)
264/// parse the response. When the response allows it, the connection returns
265/// to [`ClientEvent::Idle`] and can send the next request (keep-alive).
266///
267/// The response is framed with the request in mind: a `HEAD` request's
268/// response has no body whatever its headers say, a `CONNECT` 2xx becomes a
269/// tunnel, and a response with neither `Content-Length` nor
270/// `Transfer-Encoding` runs until the server closes.
271///
272/// # Examples
273///
274/// ```
275/// use http_net::{ClientConn, ClientEvent, Request};
276///
277/// let mut conn = ClientConn::new();
278/// let mut out = Vec::new();
279/// conn.send_request(&Request::get("/a").header("host", "h"), &mut out).unwrap();
280/// assert_eq!(out, b"GET /a HTTP/1.1\r\nhost: h\r\n\r\n");
281/// let _ = conn.feed(b"HTTP/1.1 204 No Content\r\n\r\n");
282/// assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
283/// assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
284/// assert!(matches!(conn.poll().unwrap(), ClientEvent::Idle));
285/// ```
286pub struct ClientConn {
287    buf: Buffer,
288    limits: Limits,
289    scanner: HeadScanner,
290    trailers: HeadScanner,
291    decoder: Decoder,
292    info: ResponseInfo,
293    asked: Asked,
294    upgrade_asked: bool,
295    /// The protocols the outstanding upgrade request offered, comma
296    /// separated; a `101` may switch only to these.
297    upgrade_offer: Vec<u8>,
298    state: State,
299    req: ReqWrite,
300    keep_alive: bool,
301    /// Bytes of interim (1xx) heads seen for the current request. They
302    /// count against the header budget so that a server cannot keep the
303    /// client parsing forever without answering.
304    interim_bytes: usize,
305    /// Interim heads seen for the current request, against `max_interim`.
306    interim_count: u16,
307    report_interim: bool,
308    report_trailers: bool,
309    /// The request was sent with `Expect: 100-continue` and neither a `100`,
310    /// a final response, nor body bytes have happened since.
311    waiting_continue: bool,
312    /// A final response arrived while waiting for `100`: the promised body
313    /// must not be sent, and the connection closes after the response.
314    body_refused: bool,
315    /// The request body was declared chunked (trailers allowed).
316    req_chunked: bool,
317    /// The request being answered is idempotent (it may share the
318    /// connection with pipelined requests).
319    idempotent: bool,
320    /// Requests sent after the one being answered, in order: a fixed ring,
321    /// so pipelining allocates nothing after construction.
322    queue: [Queued; MAX_PIPELINE_DEPTH as usize],
323    queue_start: usize,
324    queued: usize,
325    leniency: ClientLeniency,
326    /// Where the obs-fold rewrite stopped in the current response head.
327    unfold: Unfold,
328}
329
330/// A pipelined request waiting for its response: what framing its response
331/// needs and whether it asked to close.
332#[derive(Clone, Copy, Debug)]
333struct Queued {
334    asked: Asked,
335    close: bool,
336}
337
338/// Writes the request line, fields, framing, and (for a full body) the body;
339/// returns how the rest of the body, if any, is to be written.
340fn write_request(request: &Request, out: &mut Vec<u8>) -> Result<ReqWrite, HttpError> {
341    let method = request.method_kind;
342    let expects_body = matches!(method, Method::Post | Method::Put | Method::Patch);
343    let (mut encoder, declared) = match &request.body {
344        OutBody::Full(b) if b.is_empty() && !expects_body => (Encoder::Discard, None),
345        OutBody::Full(b) => (
346            Encoder::Length {
347                remaining: b.len() as u64,
348            },
349            Some(b.len() as u64),
350        ),
351        OutBody::Length(n) => (Encoder::Length { remaining: *n }, Some(*n)),
352        OutBody::Chunked => (Encoder::Chunked, None),
353    };
354    out.extend_from_slice(request.method().as_bytes());
355    out.push(b' ');
356    out.extend_from_slice(request.target().as_bytes());
357    out.extend_from_slice(b" HTTP/1.1\r\n");
358    out.extend_from_slice(request.fields());
359    push_framing(out, encoder, declared);
360    if request.close {
361        out.extend_from_slice(b"connection: close\r\n");
362    }
363    out.extend_from_slice(b"\r\n");
364    match &request.body {
365        OutBody::Full(b) => {
366            encoder.write(b, out)?;
367            Ok(ReqWrite::Sent)
368        }
369        _ => Ok(ReqWrite::Streaming(encoder)),
370    }
371}
372
373const NO_QUEUED: Queued = Queued {
374    asked: Asked {
375        head: false,
376        connect: false,
377    },
378    close: false,
379};
380
381impl Default for ClientConn {
382    fn default() -> Self {
383        Self::new()
384    }
385}
386
387impl core::fmt::Debug for ClientConn {
388    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
389        f.debug_struct("ClientConn")
390            .field("state", &self.state)
391            .field("request", &self.req)
392            .field("buffered", &self.buf.unread().len())
393            .field("limits", &self.limits)
394            .finish()
395    }
396}
397
398impl ClientConn {
399    /// A connection with the default [`Limits`].
400    ///
401    /// # Examples
402    ///
403    /// ```
404    /// let mut conn = http_net::ClientConn::new();
405    /// assert!(matches!(conn.poll(), Ok(http_net::ClientEvent::Idle)));
406    /// ```
407    #[must_use]
408    pub fn new() -> Self {
409        Self::with_limits(Limits::new())
410    }
411
412    /// A connection enforcing `limits` on responses.
413    ///
414    /// # Examples
415    ///
416    /// ```
417    /// let conn = http_net::ClientConn::with_limits(http_net::Limits::new().with_max_body(1 << 24));
418    /// assert_eq!(conn.limits().max_body(), 1 << 24);
419    /// ```
420    #[must_use]
421    pub fn with_limits(limits: Limits) -> Self {
422        Self::from_buffer(Buffer::new(limits.buffer_capacity()), limits)
423    }
424
425    /// A connection enforcing `limits` that reads into `storage` (its
426    /// capacity is used up to [`Limits::buffer_capacity`], its contents are
427    /// ignored), for drivers that pool buffers. Give it back with
428    /// [`into_buffer`](Self::into_buffer).
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// let conn = http_net::ClientConn::with_buffer(Vec::with_capacity(4096), http_net::Limits::new());
434    /// assert!(conn.into_buffer().capacity() >= 4096);
435    /// ```
436    #[must_use]
437    pub fn with_buffer(storage: Vec<u8>, limits: Limits) -> Self {
438        Self::from_buffer(
439            Buffer::with_storage(storage, limits.buffer_capacity()),
440            limits,
441        )
442    }
443
444    fn from_buffer(buf: Buffer, limits: Limits) -> Self {
445        Self {
446            buf,
447            limits,
448            scanner: HeadScanner::new(),
449            trailers: HeadScanner::new(),
450            decoder: Decoder::new(),
451            info: ResponseInfo::EMPTY,
452            asked: Asked {
453                head: false,
454                connect: false,
455            },
456            upgrade_asked: false,
457            upgrade_offer: Vec::new(),
458            state: State::Idle,
459            req: ReqWrite::Sent,
460            keep_alive: true,
461            interim_bytes: 0,
462            interim_count: 0,
463            report_interim: false,
464            report_trailers: false,
465            waiting_continue: false,
466            body_refused: false,
467            req_chunked: false,
468            idempotent: true,
469            queue: [NO_QUEUED; MAX_PIPELINE_DEPTH as usize],
470            queue_start: 0,
471            queued: 0,
472            leniency: ClientLeniency::new(),
473            unfold: Unfold::new(),
474        }
475    }
476
477    /// The limits this connection enforces.
478    ///
479    /// # Examples
480    ///
481    /// ```
482    /// assert_eq!(http_net::ClientConn::new().limits().max_headers(), 100);
483    /// ```
484    #[must_use]
485    pub fn limits(&self) -> &Limits {
486        &self.limits
487    }
488
489    /// Copies as much of `bytes` into the input buffer as fits; returns how
490    /// many were taken (see [`ServerConn::feed`](crate::ServerConn::feed)).
491    ///
492    /// # Examples
493    ///
494    /// ```
495    /// let mut conn = http_net::ClientConn::new();
496    /// assert_eq!(conn.feed(b"HTTP/1.1"), 8);
497    /// ```
498    #[must_use = "bytes beyond the returned count were not taken"]
499    pub fn feed(&mut self, bytes: &[u8]) -> usize {
500        self.buf.feed(bytes)
501    }
502
503    /// Spare space at the end of the input buffer; follow with
504    /// [`commit`](Self::commit).
505    ///
506    /// # Examples
507    ///
508    /// ```
509    /// let mut conn = http_net::ClientConn::new();
510    /// assert!(!conn.read_buf().is_empty());
511    /// ```
512    pub fn read_buf(&mut self) -> &mut [u8] {
513        self.buf.spare()
514    }
515
516    /// Records that `n` bytes were written into [`read_buf`](Self::read_buf).
517    ///
518    /// # Examples
519    ///
520    /// ```
521    /// let mut conn = http_net::ClientConn::new();
522    /// conn.read_buf()[..4].copy_from_slice(b"HTTP");
523    /// conn.commit(4);
524    /// ```
525    pub fn commit(&mut self, n: usize) {
526        self.buf.commit(n);
527    }
528
529    /// Records that the server closed its sending side: ends a body that
530    /// runs until close, or reports [`HttpError::UnexpectedEof`] mid-message.
531    ///
532    /// # Examples
533    ///
534    /// ```
535    /// use http_net::{ClientConn, ClientEvent, Request};
536    ///
537    /// let mut conn = ClientConn::new();
538    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
539    /// let _ = conn.feed(b"HTTP/1.0 200 OK\r\n\r\nall of it");
540    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
541    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::Body(b"all of it")));
542    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::NeedInput));
543    /// conn.feed_eof();
544    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
545    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::Closed));
546    /// ```
547    pub fn feed_eof(&mut self) {
548        self.buf.set_eof();
549    }
550
551    /// Writes `request` into `out` and starts waiting for its response.
552    ///
553    /// A full body is sent with `content-length` (omitted for an empty body
554    /// on methods that do not expect one); a streamed body continues with
555    /// [`send_body`](Self::send_body) and [`end_body`](Self::end_body).
556    ///
557    /// A request built with [`Request::expect_continue`] is sent head first:
558    /// [`is_waiting_for_continue`](Self::is_waiting_for_continue) is true
559    /// until the server answers `100 Continue` (reported as
560    /// [`ClientEvent::Continue`]: then send the body), a final status (then
561    /// the body must not be sent and the connection closes after the
562    /// response), or the caller sends the body anyway (RFC 9110 section
563    /// 10.1.1 allows it after a wait of its choosing).
564    ///
565    /// # Errors
566    ///
567    /// - the first error recorded by the [`Request`] builder;
568    /// - [`HttpError::MissingHost`] when the request has no `host` header;
569    /// - [`HttpError::InvalidState`] when a request is outstanding and this
570    ///   one cannot be pipelined (depth 1, depth full, or not idempotent with
571    ///   a full body; see [`can_send`](Self::can_send)), when the connection
572    ///   is closed or upgraded, or when an `expect_continue` request has a
573    ///   full body (it needs `content_length` or `chunked`);
574    /// - [`HttpError::UnexpectedData`] when response bytes nobody asked for
575    ///   are buffered.
576    ///
577    /// # Examples
578    ///
579    /// ```
580    /// use http_net::{ClientConn, HttpError, Request};
581    ///
582    /// let mut conn = ClientConn::new();
583    /// let mut out = Vec::new();
584    /// assert_eq!(conn.send_request(&Request::get("/"), &mut out), Err(HttpError::MissingHost));
585    /// conn.send_request(&Request::post("/f").header("host", "a").body(&b"xyz"[..]), &mut out).unwrap();
586    /// assert_eq!(out, b"POST /f HTTP/1.1\r\nhost: a\r\ncontent-length: 3\r\n\r\nxyz");
587    /// ```
588    pub fn send_request(&mut self, request: &Request, out: &mut Vec<u8>) -> Result<(), HttpError> {
589        if let Some(e) = request.error() {
590            return Err(e);
591        }
592        match self.state {
593            State::Idle => {}
594            State::Closed | State::Upgraded => {
595                return Err(HttpError::InvalidState(
596                    "the connection is closed or upgraded",
597                ));
598            }
599            _ => return self.send_pipelined(request, out),
600        }
601        if !self.buf.unread().is_empty() {
602            return Err(HttpError::UnexpectedData);
603        }
604        if !request.has_host {
605            return Err(HttpError::MissingHost);
606        }
607        if request.expect_continue && matches!(request.body, OutBody::Full(_)) {
608            // The point of the expectation is to hold the body back until
609            // the server agrees; a full body would be written at once.
610            return Err(HttpError::InvalidState(
611                "expect_continue needs a streamed body (content_length or chunked), \
612                 sent after ClientEvent::Continue",
613            ));
614        }
615        let method = request.method_kind;
616        self.req = write_request(request, out)?;
617        self.asked = Asked {
618            head: method == Method::Head,
619            connect: method == Method::Connect,
620        };
621        self.upgrade_asked = request.upgrade;
622        if request.upgrade {
623            self.upgrade_offer.clear();
624            for offer in request.upgrade_offers() {
625                if !self.upgrade_offer.is_empty() {
626                    self.upgrade_offer.push(b',');
627                }
628                self.upgrade_offer.extend_from_slice(offer);
629            }
630        }
631        self.keep_alive = !request.close;
632        self.idempotent = method.is_idempotent();
633        self.req_chunked = matches!(request.body, OutBody::Chunked);
634        self.waiting_continue = request.expect_continue;
635        self.body_refused = false;
636        self.buf.unpin();
637        self.buf.pin_at_pos();
638        self.scanner.reset();
639        self.unfold = Unfold::new();
640        self.interim_bytes = 0;
641        self.interim_count = 0;
642        self.state = State::Head;
643        Ok(())
644    }
645
646    /// Sends `request` behind the ones already outstanding (pipelining).
647    fn send_pipelined(&mut self, request: &Request, out: &mut Vec<u8>) -> Result<(), HttpError> {
648        if !self.can_send() {
649            return Err(HttpError::InvalidState(
650                if self.limits.pipeline_depth() <= 1 {
651                    "a request is already outstanding (raise Limits::with_pipeline_depth to pipeline)"
652                } else {
653                    "pipelining needs room in the pipeline depth, idempotent requests, \
654                 every earlier body sent, and no close, upgrade, CONNECT, or expectation"
655                },
656            ));
657        }
658        if !request.has_host {
659            return Err(HttpError::MissingHost);
660        }
661        let method = request.method_kind;
662        if !method.is_idempotent()
663            || request.upgrade
664            || request.expect_continue
665            || !matches!(request.body, OutBody::Full(_))
666        {
667            return Err(HttpError::InvalidState(
668                "only idempotent requests with a full body and no upgrade or expectation \
669                 can be pipelined",
670            ));
671        }
672        let req = write_request(request, out)?;
673        debug_assert_eq!(req, ReqWrite::Sent);
674        let slot = (self.queue_start + self.queued) % self.queue.len();
675        self.queue[slot] = Queued {
676            asked: Asked {
677                head: method == Method::Head,
678                connect: false,
679            },
680            close: request.close,
681        };
682        self.queued += 1;
683        Ok(())
684    }
685
686    /// Starts on the response to the oldest queued request.
687    fn next_queued(&mut self) {
688        let next = self.queue[self.queue_start];
689        self.queue_start = (self.queue_start + 1) % self.queue.len();
690        self.queued -= 1;
691        self.asked = next.asked;
692        self.keep_alive = !next.close;
693        self.upgrade_asked = false;
694        self.idempotent = true;
695        self.req_chunked = false;
696        self.waiting_continue = false;
697        self.body_refused = false;
698        self.buf.unpin();
699        self.buf.pin_at_pos();
700        self.scanner.reset();
701        self.interim_bytes = 0;
702        self.interim_count = 0;
703        self.state = State::Head;
704    }
705
706    /// Whether any outstanding request asked to close the connection.
707    fn closing(&self) -> bool {
708        !self.keep_alive
709            || (0..self.queued).any(|i| self.queue[(self.queue_start + i) % self.queue.len()].close)
710    }
711
712    /// The number of requests sent whose response has not completed:
713    /// 0 when idle, up to [`Limits::pipeline_depth`] when pipelining. After
714    /// the connection closed it is the number of requests that never got
715    /// a response (send them again on a new connection if they are safe to
716    /// repeat).
717    ///
718    /// # Examples
719    ///
720    /// ```
721    /// use http_net::{ClientConn, Limits, Request};
722    ///
723    /// let mut conn = ClientConn::with_limits(Limits::new().with_pipeline_depth(4));
724    /// let get = |p: &str| Request::get(p).header("host", "a");
725    /// let mut out = Vec::new();
726    /// conn.send_request(&get("/1"), &mut out)?;
727    /// conn.send_request(&get("/2"), &mut out)?;
728    /// assert_eq!(conn.outstanding(), 2);
729    /// # Ok::<(), http_net::HttpError>(())
730    /// ```
731    #[must_use]
732    pub fn outstanding(&self) -> usize {
733        match self.state {
734            State::Idle => 0,
735            State::Head | State::Interim | State::Body => 1 + self.queued,
736            State::Complete | State::Closed | State::Upgraded => self.queued,
737        }
738    }
739
740    /// Whether [`send_request`](Self::send_request) would accept another
741    /// request now. With no request outstanding: the connection is open
742    /// and nothing unsolicited is buffered. With requests outstanding
743    /// (pipelining): fewer than [`Limits::pipeline_depth`] are outstanding,
744    /// all of them are idempotent with their bodies fully sent, and none
745    /// asked to close, upgrade, `CONNECT`, or expect `100 Continue`. The new
746    /// request must also be idempotent with a full body (RFC 9112 section
747    /// 9.3.2: a client should not pipeline non-idempotent requests).
748    ///
749    /// # Examples
750    ///
751    /// ```
752    /// use http_net::{ClientConn, Limits, Request};
753    ///
754    /// let mut conn = ClientConn::new(); // depth 1: no pipelining
755    /// assert!(conn.can_send());
756    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
757    /// assert!(!conn.can_send());
758    /// # Ok::<(), http_net::HttpError>(())
759    /// ```
760    #[must_use]
761    pub fn can_send(&self) -> bool {
762        match self.state {
763            State::Idle => self.buf.unread().is_empty() && !self.buf.is_eof(),
764            State::Closed | State::Upgraded => false,
765            State::Head | State::Interim | State::Body | State::Complete => {
766                self.outstanding() < usize::from(self.limits.pipeline_depth())
767                    && self.idempotent
768                    && self.req == ReqWrite::Sent
769                    && !self.closing()
770                    && !self.upgrade_asked
771                    && !self.asked.connect
772                    && !self.waiting_continue
773                    && !self.body_refused
774                    && !self.buf.is_eof()
775            }
776        }
777    }
778
779    /// Returns the connection to its initial state for a new socket,
780    /// keeping the buffer and field-index allocations and the limits and
781    /// reporting settings. Requests still outstanding are forgotten.
782    ///
783    /// # Examples
784    ///
785    /// ```
786    /// use http_net::{ClientConn, Progress, Request};
787    ///
788    /// let mut conn = ClientConn::new();
789    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
790    /// conn.reset();
791    /// assert_eq!(conn.progress(), Progress::Idle);
792    /// assert!(conn.can_send());
793    /// # Ok::<(), http_net::HttpError>(())
794    /// ```
795    pub fn reset(&mut self) {
796        self.buf.reset();
797        self.scanner.reset();
798        self.trailers.reset();
799        self.decoder = Decoder::new();
800        self.info = ResponseInfo::EMPTY;
801        self.asked = NO_QUEUED.asked;
802        self.upgrade_asked = false;
803        self.state = State::Idle;
804        self.req = ReqWrite::Sent;
805        self.keep_alive = true;
806        self.interim_bytes = 0;
807        self.interim_count = 0;
808        self.waiting_continue = false;
809        self.body_refused = false;
810        self.req_chunked = false;
811        self.idempotent = true;
812        self.queue_start = 0;
813        self.queued = 0;
814    }
815
816    /// Gives the input buffer's storage back, for a pool.
817    ///
818    /// # Examples
819    ///
820    /// ```
821    /// assert_eq!(http_net::ClientConn::new().into_buffer().capacity(), 0);
822    /// ```
823    #[must_use]
824    pub fn into_buffer(mut self) -> Vec<u8> {
825        self.buf.take_storage()
826    }
827
828    /// Frees the input buffer and the field indexes while no request is
829    /// outstanding and nothing is buffered. Returns whether memory was
830    /// released.
831    ///
832    /// # Examples
833    ///
834    /// ```
835    /// use http_net::{ClientConn, ClientEvent, Request};
836    ///
837    /// let mut conn = ClientConn::new();
838    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
839    /// let _ = conn.feed(b"HTTP/1.1 204 No Content\r\n\r\n");
840    /// while !matches!(conn.poll()?, ClientEvent::Idle) {}
841    /// assert!(conn.shrink_idle());
842    /// # Ok::<(), http_net::HttpError>(())
843    /// ```
844    pub fn shrink_idle(&mut self) -> bool {
845        if self.state != State::Idle {
846            return false;
847        }
848        self.buf.unpin();
849        let freed = self.buf.shrink();
850        if freed {
851            self.scanner.fields = Vec::new();
852            self.trailers.fields = Vec::new();
853        }
854        freed
855    }
856
857    /// Writes body bytes of a streamed request.
858    ///
859    /// Sending body bytes while waiting for `100 Continue` ends the wait.
860    ///
861    /// # Errors
862    ///
863    /// [`HttpError::BodyLengthMismatch`] past the declared length;
864    /// [`HttpError::InvalidState`] when no streamed request is in progress,
865    /// or when the server answered an `expect_continue` request with a final
866    /// status (the body must not be sent then).
867    ///
868    /// # Examples
869    ///
870    /// ```
871    /// use http_net::{ClientConn, Request};
872    ///
873    /// let mut conn = ClientConn::new();
874    /// let mut out = Vec::new();
875    /// conn.send_request(&Request::post("/up").header("host", "a").chunked(), &mut out).unwrap();
876    /// conn.send_body(b"part", &mut out).unwrap();
877    /// conn.end_body(&mut out).unwrap();
878    /// assert!(out.ends_with(b"4\r\npart\r\n0\r\n\r\n"));
879    /// ```
880    pub fn send_body(&mut self, data: &[u8], out: &mut Vec<u8>) -> Result<(), HttpError> {
881        if self.body_refused {
882            return Err(REFUSED);
883        }
884        match &mut self.req {
885            ReqWrite::Streaming(encoder) => {
886                encoder.write(data, out)?;
887                self.waiting_continue = false;
888                Ok(())
889            }
890            ReqWrite::Sent => Err(HttpError::InvalidState("no streamed request in progress")),
891        }
892    }
893
894    /// Ends a streamed request body.
895    ///
896    /// # Errors
897    ///
898    /// [`HttpError::BodyLengthMismatch`] when fewer bytes than declared were
899    /// sent; [`HttpError::InvalidState`] when no streamed request is in
900    /// progress, or when the server answered an `expect_continue` request
901    /// with a final status (the body must not be sent then).
902    ///
903    /// # Examples
904    ///
905    /// ```
906    /// use http_net::{ClientConn, Request};
907    ///
908    /// let mut conn = ClientConn::new();
909    /// let mut out = Vec::new();
910    /// conn.send_request(&Request::post("/").header("host", "a").content_length(2), &mut out).unwrap();
911    /// conn.send_body(b"ok", &mut out).unwrap();
912    /// conn.end_body(&mut out).unwrap();
913    /// assert!(out.ends_with(b"\r\n\r\nok"));
914    /// ```
915    pub fn end_body(&mut self, out: &mut Vec<u8>) -> Result<(), HttpError> {
916        self.end_body_with_trailers(&[], out)
917    }
918
919    /// Ends a streamed chunked request body with a trailer section (see
920    /// [`ServerConn::end_body_with_trailers`](crate::ServerConn::end_body_with_trailers)
921    /// for the fields that are refused).
922    ///
923    /// # Errors
924    ///
925    /// [`HttpError::TrailerNotAllowed`] for a forbidden field or a body
926    /// that is not chunked; the field errors of
927    /// [`Request::header`]; otherwise as [`end_body`](Self::end_body).
928    ///
929    /// # Examples
930    ///
931    /// ```
932    /// use http_net::{ClientConn, Request};
933    ///
934    /// let mut conn = ClientConn::new();
935    /// let mut out = Vec::new();
936    /// conn.send_request(&Request::put("/f").header("host", "a").chunked(), &mut out)?;
937    /// conn.send_body(b"data", &mut out)?;
938    /// conn.end_body_with_trailers(&[("content-digest", b"sha-256=:x:")], &mut out)?;
939    /// assert!(out.ends_with(b"0\r\ncontent-digest: sha-256=:x:\r\n\r\n"));
940    /// # Ok::<(), http_net::HttpError>(())
941    /// ```
942    pub fn end_body_with_trailers(
943        &mut self,
944        trailers: &[(&str, &[u8])],
945        out: &mut Vec<u8>,
946    ) -> Result<(), HttpError> {
947        if self.body_refused {
948            return Err(REFUSED);
949        }
950        let ReqWrite::Streaming(encoder) = &mut self.req else {
951            return Err(HttpError::InvalidState("no streamed request in progress"));
952        };
953        if !trailers.is_empty() && !self.req_chunked {
954            return Err(HttpError::TrailerNotAllowed);
955        }
956        if *encoder == Encoder::Chunked {
957            push_last_chunk_with_trailers(out, trailers)?;
958        } else {
959            check_trailers(trailers)?;
960            encoder.finish(out)?;
961        }
962        self.req = ReqWrite::Sent;
963        self.waiting_continue = false;
964        Ok(())
965    }
966
967    /// Advances the response parser and reports what happened.
968    ///
969    /// # Errors
970    ///
971    /// Any [`HttpError`] parse error; the connection is then closed and must
972    /// not be reused.
973    ///
974    /// # Examples
975    ///
976    /// ```
977    /// use http_net::{ClientConn, HttpError, Request};
978    ///
979    /// let mut conn = ClientConn::new();
980    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
981    /// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 1\r\nContent-Length: 1\r\n\r\nx");
982    /// assert_eq!(conn.poll().unwrap_err(), HttpError::DuplicateContentLength);
983    /// ```
984    pub fn poll(&mut self) -> Result<ClientEvent<'_>, HttpError> {
985        loop {
986            match self.state {
987                State::Idle => {
988                    if !self.buf.unread().is_empty() {
989                        return Err(self.fail(HttpError::UnexpectedData));
990                    }
991                    if self.buf.is_eof() {
992                        self.state = State::Closed;
993                        return Ok(ClientEvent::Closed);
994                    }
995                    return Ok(ClientEvent::Idle);
996                }
997                State::Head => return self.poll_head(),
998                State::Interim => {
999                    self.next_head();
1000                    self.state = State::Head;
1001                }
1002                State::Body => return self.poll_body(),
1003                State::Complete => {
1004                    if self.reusable() && self.queued > 0 {
1005                        // Pipelined: the next response is for the oldest
1006                        // queued request, and may already be buffered.
1007                        self.next_queued();
1008                    } else if self.reusable() {
1009                        self.state = State::Idle;
1010                    } else {
1011                        // Queued requests, if any, will get no response;
1012                        // `outstanding()` says how many.
1013                        self.state = State::Closed;
1014                        return Ok(ClientEvent::Closed);
1015                    }
1016                }
1017                State::Upgraded => return Ok(ClientEvent::Upgraded),
1018                State::Closed => return Ok(ClientEvent::Closed),
1019            }
1020        }
1021    }
1022
1023    fn poll_head(&mut self) -> Result<ClientEvent<'_>, HttpError> {
1024        loop {
1025            let start = self.buf.pin();
1026            let visible = if self.leniency.obs_fold_in_responses {
1027                let eof = self.buf.is_eof();
1028                self.unfold.run(self.buf.tail_mut(start), eof)
1029            } else {
1030                self.buf.from(start).len()
1031            };
1032            let msg = self.buf.from(start);
1033            let progress = self
1034                .scanner
1035                .advance(
1036                    msg.get(..visible).unwrap_or(msg),
1037                    &self.limits,
1038                    HeadKind::Response,
1039                    true,
1040                )
1041                .map_err(|e| self.fail(e))?;
1042            let len = match progress {
1043                Scan::Partial if self.buf.is_eof() => {
1044                    return Err(self.fail(HttpError::UnexpectedEof));
1045                }
1046                Scan::Partial => return Ok(ClientEvent::NeedInput),
1047                Scan::Done(len) => len,
1048            };
1049            let info = interpret_response(
1050                self.buf.from(start),
1051                self.scanner.start_line(),
1052                &self.scanner.fields,
1053                &self.limits,
1054                self.asked,
1055            )
1056            .map_err(|e| self.fail(e))?;
1057            self.buf.consume(len);
1058            self.buf.extend_pin_to_pos();
1059            self.info = info;
1060            let status = info.status;
1061            let switched = if status == 101 {
1062                // RFC 9110 section 7.8: a 101 names the protocols it switches
1063                // to, and only to ones the request offered.
1064                let offered = self.upgrade_asked
1065                    && info.upgrade_field
1066                    && switches_to_offered(
1067                        self.buf.from(start),
1068                        &self.scanner.fields,
1069                        &self.upgrade_offer,
1070                    );
1071                if !offered {
1072                    return Err(self.fail(HttpError::UnexpectedUpgrade));
1073                }
1074                true
1075            } else {
1076                self.asked.connect && (200..300).contains(&status)
1077            };
1078            if switched {
1079                self.waiting_continue = false;
1080                self.state = State::Upgraded;
1081            } else if (100..200).contains(&status) {
1082                // Interim response (100 Continue, 103 Early Hints): budgeted
1083                // by count and by bytes, so a server cannot keep the client
1084                // parsing forever without a final answer.
1085                self.interim_count = self.interim_count.saturating_add(1);
1086                if self.interim_count > self.limits.max_interim() {
1087                    return Err(self.fail(HttpError::TooManyInterim));
1088                }
1089                self.interim_bytes = self.interim_bytes.saturating_add(len);
1090                if self.interim_bytes > self.limits.max_header_bytes() {
1091                    return Err(self.fail(HttpError::HeadersTooLarge));
1092                }
1093                if status == 100 && self.waiting_continue {
1094                    self.waiting_continue = false;
1095                    self.next_head();
1096                    return Ok(ClientEvent::Continue);
1097                }
1098                if self.report_interim {
1099                    self.state = State::Interim;
1100                    return Ok(ClientEvent::Informational(self.view()));
1101                }
1102                self.next_head();
1103                continue;
1104            } else {
1105                if self.waiting_continue {
1106                    // RFC 9110 section 10.1.1: a final status instead of 100
1107                    // means the server does not want the body. A promised
1108                    // body that is never sent leaves the request unfinished,
1109                    // so the connection closes after this response.
1110                    self.waiting_continue = false;
1111                    self.body_refused = self.req != ReqWrite::Sent;
1112                }
1113                self.decoder.start(info.framing);
1114                self.state = State::Body;
1115            }
1116            return Ok(ClientEvent::Response(self.view()));
1117        }
1118    }
1119
1120    /// Drops the current (interim) head and waits for the next one.
1121    fn next_head(&mut self) {
1122        self.buf.unpin();
1123        self.buf.pin_at_pos();
1124        self.scanner.reset();
1125        self.unfold = Unfold::new();
1126    }
1127
1128    fn reusable(&self) -> bool {
1129        self.keep_alive && self.info.keep_alive && self.req == ReqWrite::Sent && !self.body_refused
1130    }
1131
1132    fn poll_body(&mut self) -> Result<ClientEvent<'_>, HttpError> {
1133        let mut framing_bytes = 0;
1134        let step = self.decoder.step(
1135            self.buf.unread(),
1136            self.buf.is_eof(),
1137            &self.limits,
1138            &mut self.trailers,
1139            self.report_trailers,
1140            &mut framing_bytes,
1141        );
1142        self.buf.consume(framing_bytes);
1143        match step.map_err(|e| self.fail(e))? {
1144            Step::Data(n) => {
1145                let start = self.buf.pos();
1146                self.buf.consume(n);
1147                Ok(ClientEvent::Body(self.buf.range(start, start + n)))
1148            }
1149            Step::Trailers => Ok(ClientEvent::Trailers(Headers::new(
1150                self.buf.unread(),
1151                &self.trailers.fields,
1152            ))),
1153            Step::Done => {
1154                self.state = State::Complete;
1155                Ok(ClientEvent::ResponseEnd)
1156            }
1157            Step::NeedMore => Ok(ClientEvent::NeedInput),
1158        }
1159    }
1160
1161    fn fail(&mut self, e: HttpError) -> HttpError {
1162        self.state = State::Closed;
1163        e
1164    }
1165
1166    fn view(&self) -> ResponseHead<'_> {
1167        ResponseHead::new(
1168            self.buf.from(self.buf.pin()),
1169            &self.scanner.fields,
1170            &self.info,
1171        )
1172    }
1173
1174    /// The current response's head, from its arrival until the next request
1175    /// is sent (still available after an upgrade).
1176    ///
1177    /// # Examples
1178    ///
1179    /// ```
1180    /// use http_net::{ClientConn, ClientEvent, Request};
1181    ///
1182    /// let mut conn = ClientConn::new();
1183    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
1184    /// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1185    /// while !matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd) {}
1186    /// assert_eq!(conn.response().unwrap().status(), 200);
1187    /// ```
1188    #[must_use]
1189    pub fn response(&self) -> Option<ResponseHead<'_>> {
1190        match self.state {
1191            State::Body | State::Complete | State::Upgraded => Some(self.view()),
1192            _ => None,
1193        }
1194    }
1195
1196    /// Whether the server switched protocols and the connection now belongs
1197    /// to another protocol.
1198    ///
1199    /// # Examples
1200    ///
1201    /// ```
1202    /// assert!(!http_net::ClientConn::new().is_upgraded());
1203    /// ```
1204    #[must_use]
1205    pub fn is_upgraded(&self) -> bool {
1206        self.state == State::Upgraded
1207    }
1208
1209    /// Input that arrived after the last message parsed: after
1210    /// [`ClientEvent::Upgraded`], the first bytes of the new protocol.
1211    ///
1212    /// # Examples
1213    ///
1214    /// ```
1215    /// use http_net::{ClientConn, ClientEvent, Request};
1216    ///
1217    /// let mut conn = ClientConn::new();
1218    /// conn.send_request(&Request::get("/").header("host", "a").upgrade("x"), &mut Vec::new()).unwrap();
1219    /// let _ = conn.feed(b"HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nUpgrade: x\r\n\r\nhi");
1220    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::Response(_)));
1221    /// assert!(matches!(conn.poll().unwrap(), ClientEvent::Upgraded));
1222    /// assert_eq!(conn.remaining_input(), b"hi");
1223    /// ```
1224    #[must_use]
1225    pub fn remaining_input(&self) -> &[u8] {
1226        self.buf.unread()
1227    }
1228
1229    /// When `true`, each interim response other than `101` (for example
1230    /// `103 Early Hints`) is reported as [`ClientEvent::Informational`]
1231    /// before the final response; when `false` (the default) they are
1232    /// skipped. Interim responses count against
1233    /// [`Limits::max_interim`](crate::Limits::max_interim) either way.
1234    ///
1235    /// # Examples
1236    ///
1237    /// ```
1238    /// use http_net::{ClientConn, ClientEvent, Request};
1239    ///
1240    /// let mut conn = ClientConn::new();
1241    /// conn.set_report_informational(true);
1242    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1243    /// let _ = conn.feed(b"HTTP/1.1 103 Early Hints\r\nLink: </a.css>; rel=preload\r\n\r\nHTTP/1.1 204 No Content\r\n\r\n");
1244    /// let ClientEvent::Informational(hints) = conn.poll()? else { panic!() };
1245    /// assert_eq!(hints.status(), 103);
1246    /// assert_eq!(hints.header("link"), Some(&b"</a.css>; rel=preload"[..]));
1247    /// assert!(matches!(conn.poll()?, ClientEvent::Response(r) if r.status() == 204));
1248    /// # Ok::<(), http_net::HttpError>(())
1249    /// ```
1250    pub fn set_report_informational(&mut self, report: bool) {
1251        self.report_interim = report;
1252    }
1253
1254    /// When `true`, a response's trailer fields are kept (bounded by the
1255    /// trailer budgets of [`Limits`]) and reported as
1256    /// [`ClientEvent::Trailers`] just before [`ClientEvent::ResponseEnd`];
1257    /// when `false` (the default) they are validated and discarded.
1258    ///
1259    /// # Examples
1260    ///
1261    /// ```
1262    /// use http_net::{ClientConn, ClientEvent, Request};
1263    ///
1264    /// let mut conn = ClientConn::new();
1265    /// conn.set_report_trailers(true);
1266    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1267    /// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n2\r\nok\r\n0\r\nServer-Timing: db;dur=5\r\n\r\n");
1268    /// let mut saw = false;
1269    /// loop {
1270    ///     match conn.poll()? {
1271    ///         ClientEvent::Trailers(t) => saw = t.len() == 1,
1272    ///         ClientEvent::ResponseEnd => break,
1273    ///         _ => {}
1274    ///     }
1275    /// }
1276    /// assert!(saw);
1277    /// # Ok::<(), http_net::HttpError>(())
1278    /// ```
1279    pub fn set_report_trailers(&mut self, report: bool) {
1280        self.report_trailers = report;
1281    }
1282
1283    /// Sets the opt-in tolerances for responses (see [`ClientLeniency`]);
1284    /// the default is strict. Takes effect from the next response head.
1285    ///
1286    /// # Examples
1287    ///
1288    /// ```
1289    /// use http_net::{ClientConn, ClientLeniency, HttpError, Request};
1290    ///
1291    /// let folded = b"HTTP/1.1 200 OK\r\nX: a\r\n b\r\nContent-Length: 0\r\n\r\n";
1292    /// let mut strict = ClientConn::new();
1293    /// strict.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1294    /// let _ = strict.feed(folded);
1295    /// assert_eq!(strict.poll().unwrap_err(), HttpError::ObsFold);
1296    ///
1297    /// let mut lenient = ClientConn::new();
1298    /// lenient.set_leniency(ClientLeniency::new().with_obs_fold_in_responses(true));
1299    /// lenient.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1300    /// let _ = lenient.feed(folded);
1301    /// assert!(lenient.poll().is_ok());
1302    /// # Ok::<(), http_net::HttpError>(())
1303    /// ```
1304    pub fn set_leniency(&mut self, leniency: ClientLeniency) {
1305        self.leniency = leniency;
1306    }
1307
1308    /// Whether a request built with
1309    /// [`Request::expect_continue`](crate::Request::expect_continue) is
1310    /// still waiting: no `100 Continue`, no final response, and no body
1311    /// bytes sent yet. A client may stop waiting on its own timer and send
1312    /// the body anyway (RFC 9110 section 10.1.1).
1313    ///
1314    /// # Examples
1315    ///
1316    /// ```
1317    /// use http_net::{ClientConn, ClientEvent, Request};
1318    ///
1319    /// let mut conn = ClientConn::new();
1320    /// let mut out = Vec::new();
1321    /// let upload = Request::put("/big").header("host", "a").content_length(4).expect_continue();
1322    /// conn.send_request(&upload, &mut out)?;
1323    /// assert!(conn.is_waiting_for_continue());
1324    /// let _ = conn.feed(b"HTTP/1.1 100 Continue\r\n\r\n");
1325    /// assert!(matches!(conn.poll()?, ClientEvent::Continue));
1326    /// assert!(!conn.is_waiting_for_continue());
1327    /// conn.send_body(b"data", &mut out)?;
1328    /// conn.end_body(&mut out)?;
1329    /// # Ok::<(), http_net::HttpError>(())
1330    /// ```
1331    #[must_use]
1332    pub fn is_waiting_for_continue(&self) -> bool {
1333        self.waiting_continue
1334    }
1335
1336    /// Whether the connection can carry another request now: no request
1337    /// is outstanding (or the last response completed) and both sides allow
1338    /// keep-alive. With pipelining, [`can_send`](Self::can_send) says
1339    /// whether another request can be sent while some are outstanding.
1340    ///
1341    /// # Examples
1342    ///
1343    /// ```
1344    /// use http_net::{ClientConn, ClientEvent, Request};
1345    ///
1346    /// let mut conn = ClientConn::new();
1347    /// assert!(conn.is_reusable());
1348    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1349    /// assert!(!conn.is_reusable());
1350    /// let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1351    /// while !matches!(conn.poll()?, ClientEvent::ResponseEnd) {}
1352    /// assert!(conn.is_reusable());
1353    /// # Ok::<(), http_net::HttpError>(())
1354    /// ```
1355    #[must_use]
1356    pub fn is_reusable(&self) -> bool {
1357        match self.state {
1358            State::Idle => self.buf.unread().is_empty() && !self.buf.is_eof(),
1359            State::Complete => self.reusable() && self.buf.unread().is_empty(),
1360            _ => false,
1361        }
1362    }
1363
1364    /// The connection's phase, for response deadlines: [`Progress::Idle`]
1365    /// with no request outstanding, [`Progress::WritingBody`] while a
1366    /// request body is streamed, [`Progress::AwaitingResponse`] until the
1367    /// first byte of the response, then [`Progress::Head`] and
1368    /// [`Progress::Body`].
1369    ///
1370    /// # Examples
1371    ///
1372    /// ```
1373    /// use http_net::{ClientConn, Progress, Request};
1374    ///
1375    /// let mut conn = ClientConn::new();
1376    /// assert_eq!(conn.progress(), Progress::Idle);
1377    /// conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new())?;
1378    /// assert_eq!(conn.progress(), Progress::AwaitingResponse);
1379    /// # Ok::<(), http_net::HttpError>(())
1380    /// ```
1381    #[must_use]
1382    pub fn progress(&self) -> Progress {
1383        if matches!(self.req, ReqWrite::Streaming(_))
1384            && !self.body_refused
1385            && !matches!(self.state, State::Closed | State::Upgraded)
1386        {
1387            return Progress::WritingBody;
1388        }
1389        match self.state {
1390            State::Idle => Progress::Idle,
1391            State::Head if self.buf.from(self.buf.pin()).is_empty() => Progress::AwaitingResponse,
1392            State::Head | State::Interim => Progress::Head,
1393            State::Body => Progress::Body,
1394            State::Complete if self.reusable() => Progress::Idle,
1395            State::Complete | State::Closed => Progress::Closed,
1396            State::Upgraded => Progress::Upgraded,
1397        }
1398    }
1399}
1400
1401#[cfg(test)]
1402mod tests {
1403    use super::*;
1404    use crate::head::BodyFraming;
1405
1406    fn get() -> Request {
1407        Request::get("/").header("host", "a")
1408    }
1409
1410    #[test]
1411    fn test_interim_responses_are_skipped() {
1412        let mut conn = ClientConn::new();
1413        conn.send_request(&get(), &mut Vec::new()).unwrap();
1414        let _ = conn.feed(b"HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 103 Early Hints\r\nLink: </a>\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok");
1415        let ClientEvent::Response(r) = conn.poll().unwrap() else {
1416            panic!("expected response");
1417        };
1418        assert_eq!(r.status(), 200);
1419        assert!(matches!(conn.poll().unwrap(), ClientEvent::Body(b"ok")));
1420        assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
1421        assert!(matches!(conn.poll().unwrap(), ClientEvent::Idle));
1422    }
1423
1424    #[test]
1425    fn test_unrequested_upgrade_and_unsolicited_data_are_errors() {
1426        let mut conn = ClientConn::new();
1427        conn.send_request(&get(), &mut Vec::new()).unwrap();
1428        let _ = conn
1429            .feed(b"HTTP/1.1 101 Switching Protocols\r\nUpgrade: x\r\nConnection: upgrade\r\n\r\n");
1430        assert_eq!(conn.poll().unwrap_err(), HttpError::UnexpectedUpgrade);
1431
1432        let mut conn = ClientConn::new();
1433        let _ = conn.feed(b"HTTP/1.1 200 OK\r\n\r\n");
1434        assert_eq!(conn.poll().unwrap_err(), HttpError::UnexpectedData);
1435    }
1436
1437    /// T-21: a `101` switches only to a protocol the request offered (RFC
1438    /// 9110 section 7.8); a back end answering an upgrade to something else
1439    /// must not take over the connection.
1440    #[test]
1441    fn test_switching_protocols_must_name_an_offered_protocol() {
1442        let answer = |offers: &[&str], upgrade: &str| {
1443            let mut request = Request::get("/").header("host", "a");
1444            for offer in offers {
1445                request = request.upgrade(offer);
1446            }
1447            let mut conn = ClientConn::new();
1448            conn.send_request(&request, &mut Vec::new()).unwrap();
1449            let response = alloc::format!(
1450                "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\n{upgrade}\r\n"
1451            );
1452            let _ = conn.feed(response.as_bytes());
1453            match conn.poll() {
1454                Ok(ClientEvent::Response(r)) => {
1455                    assert_eq!(r.status(), 101);
1456                    matches!(conn.poll(), Ok(ClientEvent::Upgraded))
1457                }
1458                Err(e) => {
1459                    assert_eq!(e, HttpError::UnexpectedUpgrade);
1460                    false
1461                }
1462                other => panic!("unexpected {other:?}"),
1463            }
1464        };
1465        // The protocol offered, in any case, with or without a version.
1466        assert!(answer(&["websocket"], "Upgrade: websocket\r\n"));
1467        assert!(answer(&["websocket"], "Upgrade: WebSocket\r\n"));
1468        assert!(answer(&["websocket/13"], "Upgrade: websocket\r\n"));
1469        assert!(answer(&["websocket"], "Upgrade: websocket/13\r\n"));
1470        // One of several offers.
1471        assert!(answer(&["foo", "websocket"], "Upgrade: websocket\r\n"));
1472        // Anything not offered, h2c above all, or no protocol at all.
1473        assert!(!answer(&["websocket"], "Upgrade: h2c\r\n"));
1474        assert!(!answer(&["websocket"], "Upgrade: foo\r\n"));
1475        assert!(!answer(&["websocket"], "Upgrade: websocket, foo\r\n"));
1476        assert!(!answer(
1477            &["websocket"],
1478            "Upgrade: websocket\r\nUpgrade: foo\r\n"
1479        ));
1480        assert!(!answer(&["websocket/13"], "Upgrade: websocket/14\r\n"));
1481        assert!(!answer(&["websocket"], "Upgrade:\r\n"));
1482        assert!(!answer(&["websocket"], ""));
1483    }
1484
1485    #[test]
1486    fn test_head_response_has_no_body_and_connection_is_reused() {
1487        let mut conn = ClientConn::new();
1488        conn.send_request(
1489            &Request::new("HEAD", "/").header("host", "a"),
1490            &mut Vec::new(),
1491        )
1492        .unwrap();
1493        let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 100\r\n\r\n");
1494        let ClientEvent::Response(r) = conn.poll().unwrap() else {
1495            panic!("expected response");
1496        };
1497        assert_eq!(r.framing(), BodyFraming::None);
1498        assert!(matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd));
1499        assert!(matches!(conn.poll().unwrap(), ClientEvent::Idle));
1500        conn.send_request(&get(), &mut Vec::new()).unwrap();
1501        assert!(matches!(
1502            conn.send_request(&get(), &mut Vec::new()),
1503            Err(HttpError::InvalidState(_))
1504        ));
1505    }
1506
1507    #[test]
1508    fn test_close_and_streaming_request_prevent_reuse() {
1509        let mut conn = ClientConn::new();
1510        conn.send_request(&get().close(), &mut Vec::new()).unwrap();
1511        let _ = conn.feed(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
1512        while !matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd) {}
1513        assert!(matches!(conn.poll().unwrap(), ClientEvent::Closed));
1514        assert!(conn.send_request(&get(), &mut Vec::new()).is_err());
1515
1516        let mut conn = ClientConn::new();
1517        let mut out = Vec::new();
1518        conn.send_request(&Request::post("/").header("host", "a").chunked(), &mut out)
1519            .unwrap();
1520        let _ = conn.feed(b"HTTP/1.1 413 Content Too Large\r\nContent-Length: 0\r\n\r\n");
1521        while !matches!(conn.poll().unwrap(), ClientEvent::ResponseEnd) {}
1522        assert!(matches!(conn.poll().unwrap(), ClientEvent::Closed));
1523        assert!(matches!(conn.send_body(b"x", &mut out), Ok(())));
1524        assert!(matches!(conn.end_body(&mut out), Ok(())));
1525        assert!(matches!(
1526            conn.end_body(&mut out),
1527            Err(HttpError::InvalidState(_))
1528        ));
1529    }
1530
1531    #[test]
1532    fn test_eof_before_response_is_an_error() {
1533        let mut conn = ClientConn::new();
1534        conn.send_request(&get(), &mut Vec::new()).unwrap();
1535        conn.feed_eof();
1536        assert_eq!(conn.poll().unwrap_err(), HttpError::UnexpectedEof);
1537    }
1538}