Skip to main content

http_net/
raw.rs

1//! Tier 3: the bytes and offsets behind a parsed head, copying a head out
2//! (the zero-copy passport path), owned heads, and the stateless parsers.
3//!
4//! A head is its bytes plus `u32` spans into them, so it can be moved or
5//! copied without re-parsing: [`RequestHead::copy_into`] copies the bytes
6//! and spans into a caller's reused vectors and hands back the interpreted
7//! [`HeadFacts`], and [`OwnedRequestHead::from_parts`] rebuilds a view from
8//! them after checking that their structure is intact. The stateless
9//! parsers run the connections' own scanner and interpretation over a
10//! caller's slice, with the field records written into a caller's array:
11//! they allocate nothing.
12
13use alloc::vec::Vec;
14use core::fmt;
15
16use crate::{
17    error::HttpError,
18    head::{
19        Asked, Field, FieldSpan, HeadKind, LineScan, RequestHead, RequestInfo, ResponseHead,
20        ResponseInfo, Scan, SliceSink, Span, check_target, interpret_request, interpret_response,
21        parse_version,
22    },
23    limits::Limits,
24    method::Method,
25    scan::{check_field_value, find_byte, is_ows, is_token},
26};
27
28/// The bytes of a head and the spans of its parts, all relative to
29/// [`bytes`](Self::bytes): what [`RequestHead::raw`] and
30/// [`ResponseHead::raw`] return.
31///
32/// The bytes run from the first byte the connection kept for the message
33/// (any empty lines a client sent before the request line, which RFC 9112
34/// section 2.2 lets a server skip, are included) to the end of the blank
35/// line that ends the head. Spans for parts a head does not have are empty:
36/// `status` on a request, `method` and `target` on a response.
37///
38/// `Debug` shows lengths and spans only, never the bytes, so a raw head in
39/// a log cannot leak a credential.
40///
41/// # Examples
42///
43/// ```
44/// use http_net::{ServerConn, ServerEvent};
45///
46/// let mut conn = ServerConn::new();
47/// let _ = conn.feed(b"GET /a HTTP/1.1\r\nHost: x\r\n\r\nbody bytes are not part of it");
48/// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
49/// let raw = req.raw();
50/// assert_eq!(raw.bytes(), b"GET /a HTTP/1.1\r\nHost: x\r\n\r\n");
51/// assert_eq!(raw.method().get(raw.bytes()), b"GET");
52/// assert_eq!(raw.target().get(raw.bytes()), b"/a");
53/// assert_eq!(raw.version().get(raw.bytes()), b"HTTP/1.1");
54/// assert!(raw.status().is_empty());
55/// assert_eq!(raw.fields().len(), 1);
56/// ```
57#[derive(Clone, Copy)]
58pub struct RawHead<'a> {
59    bytes: &'a [u8],
60    start_line: Span,
61    method: Span,
62    target: Span,
63    version: Span,
64    status: Span,
65    fields: &'a [FieldSpan],
66}
67
68impl<'a> RawHead<'a> {
69    /// The head bytes, from its first byte to the end of the blank line.
70    ///
71    /// # Examples
72    ///
73    /// See [`RawHead`].
74    #[must_use]
75    pub fn bytes(&self) -> &'a [u8] {
76        self.bytes
77    }
78
79    /// The request line or status line, without its CRLF.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// # use http_net::{ServerConn, ServerEvent};
85    /// # let mut conn = ServerConn::new();
86    /// # let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: x\r\n\r\n");
87    /// # let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
88    /// let raw = req.raw();
89    /// assert_eq!(raw.start_line().get(raw.bytes()), b"GET / HTTP/1.1");
90    /// ```
91    #[must_use]
92    pub fn start_line(&self) -> Span {
93        self.start_line
94    }
95
96    /// The method (requests; empty for a response).
97    ///
98    /// # Examples
99    ///
100    /// See [`RawHead`].
101    #[must_use]
102    pub fn method(&self) -> Span {
103        self.method
104    }
105
106    /// The request target (requests; empty for a response).
107    ///
108    /// # Examples
109    ///
110    /// See [`RawHead`].
111    #[must_use]
112    pub fn target(&self) -> Span {
113        self.target
114    }
115
116    /// The protocol version as received (`HTTP/1.0`, `HTTP/1.1`, or another
117    /// `HTTP/1.x`, which `version()` reports as `Http11`).
118    ///
119    /// # Examples
120    ///
121    /// See [`RawHead`].
122    #[must_use]
123    pub fn version(&self) -> Span {
124        self.version
125    }
126
127    /// The three status digits (responses; empty for a request).
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// # use http_net::{ClientConn, ClientEvent, Request};
133    /// # let mut conn = ClientConn::new();
134    /// # conn.send_request(&Request::get("/").header("host", "a"), &mut Vec::new()).unwrap();
135    /// # let _ = conn.feed(b"HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
136    /// # let ClientEvent::Response(resp) = conn.poll().unwrap() else { panic!() };
137    /// let raw = resp.raw();
138    /// assert_eq!(raw.status().get(raw.bytes()), b"404");
139    /// assert!(raw.method().is_empty());
140    /// ```
141    #[must_use]
142    pub fn status(&self) -> Span {
143        self.status
144    }
145
146    /// Every field line's name and value spans, in arrival order.
147    ///
148    /// # Examples
149    ///
150    /// See [`FieldSpan`].
151    #[must_use]
152    pub fn fields(&self) -> &'a [FieldSpan] {
153        self.fields
154    }
155}
156
157impl fmt::Debug for RawHead<'_> {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.debug_struct("RawHead")
160            .field("len", &self.bytes.len())
161            .field("start_line", &self.start_line)
162            .field("fields", &self.fields.len())
163            .finish_non_exhaustive()
164    }
165}
166
167/// The interpreted facts of a request head (method, version, framing,
168/// keep-alive, upgrade and expectation flags, target form, and the spans of
169/// the host and of the target's parts), so a view can be rebuilt from
170/// copied bytes without parsing them again. Returned by
171/// [`RequestHead::copy_into`], taken by [`OwnedRequestHead::from_parts`].
172///
173/// # Examples
174///
175/// ```
176/// use http_net::{OwnedRequestHead, ServerConn, ServerEvent};
177///
178/// let mut conn = ServerConn::new();
179/// let _ = conn.feed(b"GET /x HTTP/1.1\r\nHost: a\r\n\r\n");
180/// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
181/// let (mut bytes, mut fields) = (Vec::new(), Vec::new());
182/// let facts = req.copy_into(&mut bytes, &mut fields);
183/// let owned = OwnedRequestHead::from_parts(bytes, fields, facts)?;
184/// assert_eq!(owned.view().path(), "/x");
185/// # Ok::<(), http_net::HttpError>(())
186/// ```
187#[derive(Clone, Copy, Debug, PartialEq, Eq)]
188pub struct HeadFacts {
189    info: RequestInfo,
190}
191
192/// The length of a validated head inside `bytes`: the line that holds the
193/// last field value (or the start line) ends at the next LF, and the blank
194/// line's CRLF follows it.
195fn head_len(bytes: &[u8], start_line: Span, fields: &[Field]) -> usize {
196    let after = fields.last().map_or(start_line.end, |f| f.value.end) as usize;
197    match bytes.get(after..).and_then(|rest| find_byte(b'\n', rest)) {
198        Some(lf) => (after + lf + 1 + 2).min(bytes.len()),
199        None => bytes.len(),
200    }
201}
202
203impl<'a> RequestHead<'a> {
204    /// The head's bytes and the spans of its parts, for code that works on
205    /// offsets (passports, proxies, other engines).
206    ///
207    /// # Examples
208    ///
209    /// See [`RawHead`].
210    #[must_use]
211    pub fn raw(&self) -> RawHead<'a> {
212        let (head, fields, info) = self.parts();
213        let sl = info.start_line;
214        let bytes = head.get(..head_len(head, sl, fields)).unwrap_or(head);
215        RawHead {
216            bytes,
217            start_line: sl,
218            method: info.method_span,
219            target: info.target,
220            version: Span {
221                start: info.target.end.saturating_add(1),
222                end: sl.end,
223            },
224            status: Span::default(),
225            fields,
226        }
227    }
228
229    /// Copies the head bytes (one copy) and field spans into `bytes` and
230    /// `fields`, which are cleared first, and returns the interpreted facts:
231    /// with them, [`OwnedRequestHead::from_parts`] (or a passport) rebuilds a
232    /// view without parsing again. Once the vectors have grown to the
233    /// largest head seen, the copy allocates nothing.
234    ///
235    /// # Examples
236    ///
237    /// ```
238    /// use http_net::{OwnedRequestHead, ServerConn, ServerEvent};
239    ///
240    /// // A passport's buffers, reused for every request.
241    /// let (mut bytes, mut fields) = (Vec::with_capacity(4096), Vec::with_capacity(64));
242    /// let mut conn = ServerConn::new();
243    /// let _ = conn.feed(b"POST /api HTTP/1.1\r\nHost: a\r\nContent-Length: 2\r\n\r\nhi");
244    /// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
245    /// let facts = req.copy_into(&mut bytes, &mut fields);
246    /// assert_eq!(bytes, b"POST /api HTTP/1.1\r\nHost: a\r\nContent-Length: 2\r\n\r\n");
247    /// let owned = OwnedRequestHead::from_parts(bytes, fields, facts)?;
248    /// assert_eq!(owned.view().content_length(), Some(2));
249    /// # Ok::<(), http_net::HttpError>(())
250    /// ```
251    #[must_use = "the facts are needed to rebuild a view from the copied bytes"]
252    pub fn copy_into(&self, bytes: &mut Vec<u8>, fields: &mut Vec<FieldSpan>) -> HeadFacts {
253        let raw = self.raw();
254        bytes.clear();
255        bytes.extend_from_slice(raw.bytes);
256        fields.clear();
257        fields.extend_from_slice(raw.fields);
258        HeadFacts {
259            info: *self.parts().2,
260        }
261    }
262
263    /// An owned copy of the head, for keeping it across body events or
264    /// sending it to another thread.
265    ///
266    /// # Examples
267    ///
268    /// ```
269    /// use http_net::{ServerConn, ServerEvent};
270    ///
271    /// let mut conn = ServerConn::new();
272    /// let _ = conn.feed(b"GET /keep HTTP/1.1\r\nHost: a\r\n\r\n");
273    /// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
274    /// let owned = req.to_owned();
275    /// drop(conn);
276    /// assert_eq!(owned.view().path(), "/keep");
277    /// ```
278    #[must_use]
279    #[allow(clippy::wrong_self_convention)]
280    pub fn to_owned(&self) -> OwnedRequestHead {
281        let raw = self.raw();
282        OwnedRequestHead {
283            bytes: raw.bytes.to_vec(),
284            fields: raw.fields.to_vec(),
285            facts: HeadFacts {
286                info: *self.parts().2,
287            },
288        }
289    }
290}
291
292impl<'a> ResponseHead<'a> {
293    /// The head's bytes and the spans of its parts (see [`RawHead`]).
294    ///
295    /// # Examples
296    ///
297    /// See [`RawHead::status`].
298    #[must_use]
299    pub fn raw(&self) -> RawHead<'a> {
300        let (head, fields, info) = self.parts();
301        let sl = info.start_line;
302        let bytes = head.get(..head_len(head, sl, fields)).unwrap_or(head);
303        RawHead {
304            bytes,
305            start_line: sl,
306            method: Span::default(),
307            target: Span::default(),
308            version: Span {
309                start: sl.start,
310                end: sl.start.saturating_add(8).min(sl.end),
311            },
312            status: Span {
313                start: sl.start.saturating_add(9).min(sl.end),
314                end: sl.start.saturating_add(12).min(sl.end),
315            },
316            fields,
317        }
318    }
319}
320
321/// A request head that owns its bytes and spans: from
322/// [`RequestHead::to_owned`], or rebuilt from a passport's parts with
323/// [`from_parts`](Self::from_parts). `Debug` shows the head the way
324/// [`RequestHead`] does, credential values redacted.
325///
326/// # Examples
327///
328/// See [`RequestHead::to_owned`] and [`HeadFacts`].
329#[derive(Clone, PartialEq, Eq)]
330pub struct OwnedRequestHead {
331    bytes: Vec<u8>,
332    fields: Vec<FieldSpan>,
333    facts: HeadFacts,
334}
335
336impl OwnedRequestHead {
337    /// A view of the owned head, with every accessor of a borrowed one.
338    ///
339    /// # Examples
340    ///
341    /// See [`RequestHead::to_owned`].
342    #[must_use]
343    pub fn view(&self) -> RequestHead<'_> {
344        RequestHead::new(&self.bytes, &self.fields, &self.facts.info)
345    }
346
347    /// Rebuilds an owned head from copied parts ([`RequestHead::copy_into`]),
348    /// checking first that they still describe one head: every span lies
349    /// inside `bytes`, the start line and every field line have the
350    /// structure the parser accepted (method, target, and version where the
351    /// facts say, each field name a token followed by a colon, each value
352    /// without control bytes or surrounding whitespace, the lines in order
353    /// and back to back, the blank line last), and the host and target
354    /// spans in the facts point where they should. A passport whose
355    /// structure was changed is refused, never read. The check is
356    /// structural, not an integrity check: a change that keeps every rule (a
357    /// different target, `Host`, or field value of valid bytes) is accepted,
358    /// so a passport that crosses a trust boundary needs its own MAC.
359    ///
360    /// The framing facts themselves (body length, keep-alive) are taken as
361    /// given: they come from the same trusted copy, and recomputing them
362    /// would be the parse this is meant to avoid.
363    ///
364    /// # Errors
365    ///
366    /// [`HttpError::InvalidState`], naming the first rule that failed.
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// use http_net::{HttpError, OwnedRequestHead, ServerConn, ServerEvent};
372    ///
373    /// let mut conn = ServerConn::new();
374    /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
375    /// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
376    /// let (mut bytes, mut fields) = (Vec::new(), Vec::new());
377    /// let facts = req.copy_into(&mut bytes, &mut fields);
378    /// bytes[16] = b' '; // the first field name now starts with a space
379    /// assert!(matches!(
380    ///     OwnedRequestHead::from_parts(bytes, fields, facts),
381    ///     Err(HttpError::InvalidState(_))
382    /// ));
383    /// # Ok::<(), http_net::HttpError>(())
384    /// ```
385    pub fn from_parts(
386        bytes: Vec<u8>,
387        fields: Vec<FieldSpan>,
388        facts: HeadFacts,
389    ) -> Result<Self, HttpError> {
390        validate(&bytes, &fields, &facts.info).map_err(HttpError::InvalidState)?;
391        Ok(Self {
392            bytes,
393            fields,
394            facts,
395        })
396    }
397
398    /// Gives the parts back, so a passport pool can reuse the vectors for
399    /// the next head without allocating.
400    ///
401    /// # Examples
402    ///
403    /// ```
404    /// use http_net::{ServerConn, ServerEvent};
405    ///
406    /// let mut conn = ServerConn::new();
407    /// let _ = conn.feed(b"GET /a HTTP/1.1\r\nHost: a\r\n\r\n");
408    /// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
409    /// let (mut bytes, mut fields, _facts) = req.to_owned().into_parts();
410    /// let capacity = bytes.capacity();
411    /// bytes.clear();
412    /// fields.clear();
413    /// assert_eq!(bytes.capacity(), capacity);
414    /// ```
415    #[must_use]
416    pub fn into_parts(self) -> (Vec<u8>, Vec<FieldSpan>, HeadFacts) {
417        (self.bytes, self.fields, self.facts)
418    }
419
420    /// Drops the head, zeroing its bytes first, including any spare
421    /// capacity (a vector reused through [`RequestHead::copy_into`] can
422    /// still hold an earlier, longer head there). A plain drop frees the
423    /// bytes as they are, so an `Authorization` or `Cookie` value lingers
424    /// in freed memory; call this where
425    /// [`ServerConn::set_wipe`](crate::ServerConn::set_wipe) is on. A clone
426    /// is a separate copy and needs its own `wipe`.
427    ///
428    /// # Examples
429    ///
430    /// ```
431    /// use http_net::{ServerConn, ServerEvent};
432    ///
433    /// let mut conn = ServerConn::new();
434    /// conn.set_wipe(true);
435    /// let _ = conn.feed(b"GET / HTTP/1.1\r\nHost: a\r\nAuthorization: Bearer s3cret\r\n\r\n");
436    /// let ServerEvent::Request(req) = conn.poll().unwrap() else { panic!() };
437    /// let head = req.to_owned();
438    /// assert_eq!(head.view().path(), "/");
439    /// head.wipe();
440    /// ```
441    pub fn wipe(self) {
442        let mut bytes = self.bytes;
443        let capacity = bytes.capacity();
444        bytes.resize(capacity, 0);
445        crate::buffer::zero(&mut bytes);
446    }
447}
448
449impl fmt::Debug for OwnedRequestHead {
450    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451        fmt::Debug::fmt(&self.view(), f)
452    }
453}
454
455/// The checks behind [`OwnedRequestHead::from_parts`].
456fn validate(bytes: &[u8], fields: &[Field], info: &RequestInfo) -> Result<(), &'static str> {
457    let len = bytes.len();
458    let sl = info.start_line;
459    if !sl.fits(len) || sl.is_empty() {
460        return Err("the start line span is outside the head");
461    }
462    // Only empty lines (RFC 9112 section 2.2) may come before the start line.
463    let before = Span {
464        start: 0,
465        end: sl.start,
466    }
467    .get(bytes);
468    if before.len() % 2 != 0 || !before.chunks(2).all(|c| c == b"\r\n") {
469        return Err("bytes before the start line are not empty lines");
470    }
471    if bytes.get(sl.end as usize..sl.end as usize + 2) != Some(b"\r\n") {
472        return Err("the start line does not end in CRLF");
473    }
474    // method SP target SP version
475    let m = info.method_span;
476    let t = info.target;
477    if m.start != sl.start || m.is_empty() || !m.fits(len) {
478        return Err("the method span does not start the start line");
479    }
480    if !is_token(m.get(bytes)) || Method::from_bytes(m.get(bytes)) != info.method {
481        return Err("the method bytes do not match the facts");
482    }
483    if t.start != m.end + 1
484        || t.is_empty()
485        || t.end >= sl.end
486        || bytes.get(m.end as usize) != Some(&b' ')
487    {
488        return Err("the target span is not after the method");
489    }
490    if bytes.get(t.end as usize) != Some(&b' ') {
491        return Err("the target is not followed by a space");
492    }
493    if check_target(info.method, t.get(bytes)).is_err() {
494        return Err("the target bytes are not a valid target for the method");
495    }
496    let version = Span {
497        start: t.end + 1,
498        end: sl.end,
499    };
500    if parse_version(version.get(bytes)) != Ok(info.version) {
501        return Err("the version bytes do not match the facts");
502    }
503    let inside_target = |s: Span| s.start >= t.start && s.end <= t.end && s.start <= s.end;
504    if !inside_target(info.origin) {
505        return Err("the origin span is outside the target");
506    }
507    if info.authority.is_some_and(|a| !inside_target(a)) {
508        return Err("the authority span is outside the target");
509    }
510    // Field lines, back to back after the start line.
511    let mut pos = sl.end as usize + 2;
512    for field in fields {
513        let (name, value) = (field.name, field.value);
514        if name.start as usize != pos || name.is_empty() || !name.fits(len) {
515            return Err("a field line does not start where the previous line ended");
516        }
517        if !is_token(name.get(bytes)) || bytes.get(name.end as usize) != Some(&b':') {
518            return Err("a field name is not a token followed by a colon");
519        }
520        if !value.fits(len) || value.start < name.end + 1 {
521            return Err("a field value span is outside its line");
522        }
523        let lead = Span {
524            start: name.end + 1,
525            end: value.start,
526        };
527        if !lead.get(bytes).iter().all(|&b| is_ows(b)) {
528            return Err("bytes between a colon and its value are not whitespace");
529        }
530        let v = value.get(bytes);
531        if v.first().is_some_and(|&b| is_ows(b)) || v.last().is_some_and(|&b| is_ows(b)) {
532            return Err("a field value has surrounding whitespace");
533        }
534        if check_field_value(v).is_err() {
535            return Err("a field value holds a byte a field may not");
536        }
537        let mut end = value.end as usize;
538        while bytes.get(end).is_some_and(|&b| is_ows(b)) {
539            end += 1;
540        }
541        if bytes.get(end..end + 2) != Some(b"\r\n") {
542            return Err("a field line does not end in CRLF after its value");
543        }
544        pos = end + 2;
545    }
546    if pos + 2 != len || bytes.get(pos..) != Some(b"\r\n") {
547        return Err("the head does not end with the blank line");
548    }
549    if let Some(host) = info.host {
550        let is_host_value = fields
551            .iter()
552            .any(|f| f.value == host && f.name.get(bytes).eq_ignore_ascii_case(b"host"));
553        if !is_host_value {
554            return Err("the host span is not the value of a Host field");
555        }
556    }
557    Ok(())
558}
559
560/// The result of a stateless parse: a complete head and how many input
561/// bytes it took, or `Partial` when the input ends before the head does.
562///
563/// # Examples
564///
565/// ```
566/// use http_net::{FieldSpan, Limits, Parsed, parse_request_head};
567///
568/// let mut fields = [FieldSpan::default(); 16];
569/// let parsed = parse_request_head(b"GET / HTTP/1.1\r\nHo", &Limits::new(), &mut fields)?;
570/// assert!(matches!(parsed, Parsed::Partial));
571/// # Ok::<(), http_net::HttpError>(())
572/// ```
573#[non_exhaustive]
574#[derive(Debug)]
575pub enum Parsed<T> {
576    /// A whole head: `len` bytes of the input, any leading empty lines
577    /// included; the body (if any) starts there.
578    Complete {
579        /// The parsed head.
580        head: T,
581        /// The bytes of input the head took.
582        len: usize,
583    },
584    /// The input ends before the head does: call again with more input.
585    Partial,
586}
587
588/// A request head from [`parse_request_head`], borrowing the input and the
589/// caller's field array.
590///
591/// # Examples
592///
593/// See [`parse_request_head`].
594#[derive(Clone, Copy)]
595pub struct ParsedRequest<'a> {
596    bytes: &'a [u8],
597    fields: &'a [FieldSpan],
598    info: RequestInfo,
599}
600
601impl ParsedRequest<'_> {
602    /// The usual view of the head.
603    ///
604    /// # Examples
605    ///
606    /// See [`parse_request_head`].
607    #[must_use]
608    pub fn view(&self) -> RequestHead<'_> {
609        RequestHead::new(self.bytes, self.fields, &self.info)
610    }
611
612    /// The interpreted facts, as [`RequestHead::copy_into`] returns them.
613    ///
614    /// # Examples
615    ///
616    /// ```
617    /// use http_net::{FieldSpan, Limits, Parsed, parse_request_head};
618    ///
619    /// let mut fields = [FieldSpan::default(); 4];
620    /// let Parsed::Complete { head, .. } = parse_request_head(b"GET / HTTP/1.0\r\n\r\n", &Limits::new(), &mut fields)? else { panic!() };
621    /// let _facts = head.facts();
622    /// # Ok::<(), http_net::HttpError>(())
623    /// ```
624    #[must_use]
625    pub fn facts(&self) -> HeadFacts {
626        HeadFacts { info: self.info }
627    }
628}
629
630impl fmt::Debug for ParsedRequest<'_> {
631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632        fmt::Debug::fmt(&self.view(), f)
633    }
634}
635
636/// A response head from [`parse_response_head`].
637///
638/// # Examples
639///
640/// See [`parse_response_head`].
641#[derive(Clone, Copy)]
642pub struct ParsedResponse<'a> {
643    bytes: &'a [u8],
644    fields: &'a [FieldSpan],
645    info: ResponseInfo,
646}
647
648impl ParsedResponse<'_> {
649    /// The usual view of the head.
650    ///
651    /// # Examples
652    ///
653    /// See [`parse_response_head`].
654    #[must_use]
655    pub fn view(&self) -> ResponseHead<'_> {
656        ResponseHead::new(self.bytes, self.fields, &self.info)
657    }
658}
659
660impl fmt::Debug for ParsedResponse<'_> {
661    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662        fmt::Debug::fmt(&self.view(), f)
663    }
664}
665
666/// Parses one request head from the start of `input`, with the rules and
667/// budgets of [`ServerConn`](crate::ServerConn) (the same scanner and
668/// interpretation code), writing the field records into `fields`.
669/// Allocates nothing. Unlike `ServerConn`, it does not check for the HTTP/2
670/// connection preface first; call [`is_h2_preface`](crate::is_h2_preface)
671/// for that.
672///
673/// It is stateless: given more input after `Partial`, it parses again from
674/// the start. A caller that receives a head in many small pieces and needs
675/// linear total work should use `ServerConn`, which resumes where it
676/// stopped. A head with more fields than `fields` holds is
677/// [`HttpError::TooManyHeaders`] (as is one over
678/// [`Limits::max_headers`]).
679///
680/// # Errors
681///
682/// Every request parse error `ServerConn::poll` can return for a head,
683/// except `UnexpectedEof` (running out of input is `Partial` here) and
684/// `Http2Preface` (the preface is reported as
685/// [`HttpError::UnsupportedVersion`]; call
686/// [`is_h2_preface`](crate::is_h2_preface) first to tell them apart).
687///
688/// # Examples
689///
690/// ```
691/// use http_net::{FieldSpan, Limits, Parsed, parse_request_head};
692///
693/// let input = b"POST /notes HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\nhello";
694/// let mut fields = [FieldSpan::default(); 32];
695/// let Parsed::Complete { head, len } = parse_request_head(input, &Limits::new(), &mut fields)? else {
696///     panic!("incomplete");
697/// };
698/// let req = head.view();
699/// assert_eq!(req.path(), "/notes");
700/// assert_eq!(req.content_length(), Some(5));
701/// assert_eq!(&input[len..], b"hello");
702/// # Ok::<(), http_net::HttpError>(())
703/// ```
704pub fn parse_request_head<'a>(
705    input: &'a [u8],
706    limits: &Limits,
707    fields: &'a mut [FieldSpan],
708) -> Result<Parsed<ParsedRequest<'a>>, HttpError> {
709    let mut lines = LineScan::new();
710    let mut sink = SliceSink::new(fields);
711    let len = match lines.advance(input, limits, HeadKind::Request, &mut sink)? {
712        Scan::Partial => return Ok(Parsed::Partial),
713        Scan::Done(len) => len,
714    };
715    let (slots, count) = sink.into_parts();
716    let slots: &'a [FieldSpan] = slots;
717    let fields = slots.get(..count).unwrap_or(&[]);
718    let bytes = input.get(..len).unwrap_or(input);
719    let info = interpret_request(bytes, lines.start_line(), fields, limits)?;
720    Ok(Parsed::Complete {
721        head: ParsedRequest {
722            bytes,
723            fields,
724            info,
725        },
726        len,
727    })
728}
729
730/// Parses one response head from the start of `input` with the rules of
731/// [`ClientConn`](crate::ClientConn), framed by the method of the request
732/// it answers (a response to `HEAD` has no body; a 2xx to `CONNECT` is a
733/// tunnel; any other method frames by the fields). Interim (1xx) heads are returned like any other; check
734/// [`ResponseHead::is_informational`] and parse the next head after `len`.
735/// No [`ClientLeniency`](crate::ClientLeniency) applies, so obsolete line
736/// folding is always [`HttpError::ObsFold`]. Allocates nothing.
737///
738/// # Errors
739///
740/// Every response parse error `ClientConn::poll` can return for a head
741/// (`UnexpectedEof` aside), and [`HttpError::TooManyHeaders`] when the head
742/// has more fields than `fields` holds.
743///
744/// # Examples
745///
746/// ```
747/// use http_net::{BodyFraming, FieldSpan, Limits, Method, Parsed, parse_response_head};
748///
749/// let input = b"HTTP/1.1 200 OK\r\nContent-Length: 100\r\n\r\n";
750/// let mut fields = [FieldSpan::default(); 8];
751/// let Parsed::Complete { head, .. } = parse_response_head(input, &Limits::new(), Method::Head, &mut fields)? else {
752///     panic!("incomplete");
753/// };
754/// // A response to HEAD has no body, whatever its fields say.
755/// assert_eq!(head.view().framing(), BodyFraming::None);
756/// assert_eq!(head.view().content_length(), Some(100));
757/// # Ok::<(), http_net::HttpError>(())
758/// ```
759pub fn parse_response_head<'a>(
760    input: &'a [u8],
761    limits: &Limits,
762    request_method: Method,
763    fields: &'a mut [FieldSpan],
764) -> Result<Parsed<ParsedResponse<'a>>, HttpError> {
765    let mut lines = LineScan::new();
766    let mut sink = SliceSink::new(fields);
767    let len = match lines.advance(input, limits, HeadKind::Response, &mut sink)? {
768        Scan::Partial => return Ok(Parsed::Partial),
769        Scan::Done(len) => len,
770    };
771    let (slots, count) = sink.into_parts();
772    let slots: &'a [FieldSpan] = slots;
773    let fields = slots.get(..count).unwrap_or(&[]);
774    let bytes = input.get(..len).unwrap_or(input);
775    let asked = Asked::from_method(request_method);
776    let info = interpret_response(bytes, lines.start_line(), fields, limits, asked)?;
777    Ok(Parsed::Complete {
778        head: ParsedResponse {
779            bytes,
780            fields,
781            info,
782        },
783        len,
784    })
785}
786
787#[cfg(test)]
788mod tests {
789    use alloc::vec;
790
791    use super::*;
792    use crate::{ServerConn, ServerEvent};
793
794    fn owned_parts(input: &[u8]) -> (Vec<u8>, Vec<FieldSpan>, HeadFacts) {
795        let mut conn = ServerConn::new();
796        let _ = conn.feed(input);
797        let Ok(ServerEvent::Request(req)) = conn.poll() else {
798            panic!("no request in {input:?}");
799        };
800        let (mut bytes, mut fields) = (Vec::new(), Vec::new());
801        let facts = req.copy_into(&mut bytes, &mut fields);
802        (bytes, fields, facts)
803    }
804
805    #[test]
806    fn test_span_get_and_len_never_panic() {
807        let head = b"abc";
808        assert_eq!(Span { start: 0, end: 3 }.get(head), b"abc");
809        assert_eq!(Span { start: 2, end: 9 }.get(head), b"");
810        assert_eq!(Span { start: 3, end: 1 }.get(head), b"");
811        assert_eq!(Span { start: 3, end: 1 }.len(), 0);
812        assert_eq!(
813            Span {
814                start: u32::MAX,
815                end: u32::MAX
816            }
817            .get(head),
818            b""
819        );
820        assert!(Span { start: 1, end: 1 }.is_empty());
821    }
822
823    #[test]
824    fn test_raw_head_spans_point_at_the_parts() {
825        let (bytes, fields, _) =
826            owned_parts(b"\r\nPUT /f?q HTTP/1.0\r\nX:  v \r\nHost: h\r\n\r\nbody");
827        assert_eq!(bytes, b"\r\nPUT /f?q HTTP/1.0\r\nX:  v \r\nHost: h\r\n\r\n");
828        assert_eq!(fields.len(), 2);
829        assert_eq!(fields[0].value.get(&bytes), b"v");
830        let mut conn = ServerConn::new();
831        let _ = conn.feed(&bytes);
832        let Ok(ServerEvent::Request(req)) = conn.poll() else {
833            panic!()
834        };
835        let raw = req.raw();
836        assert_eq!(raw.bytes(), &bytes[..]);
837        assert_eq!(raw.start_line().get(raw.bytes()), b"PUT /f?q HTTP/1.0");
838        assert_eq!(raw.version().get(raw.bytes()), b"HTTP/1.0");
839        assert!(!alloc::format!("{raw:?}").contains("PUT"));
840    }
841
842    #[test]
843    fn test_owned_head_view_equals_original() {
844        let input = b"GET http://a.test/p?q=1 HTTP/1.1\r\nHost: b\r\nCookie: s=1\r\nVia: 1.1 x\r\nVia: 1.1 y\r\n\r\n";
845        let mut conn = ServerConn::new();
846        let _ = conn.feed(input);
847        let Ok(ServerEvent::Request(req)) = conn.poll() else {
848            panic!()
849        };
850        let owned = req.to_owned();
851        let view = owned.view();
852        assert_eq!(view.method_str(), req.method_str());
853        assert_eq!(view.target(), req.target());
854        assert_eq!(view.target_form(), req.target_form());
855        assert_eq!(view.path(), req.path());
856        assert_eq!(view.query(), req.query());
857        assert_eq!(view.host(), req.host());
858        assert_eq!(view.version(), req.version());
859        assert_eq!(view.framing(), req.framing());
860        assert_eq!(view.keep_alive(), req.keep_alive());
861        assert!(view.headers().eq(req.headers()));
862        assert!(view.header_all("via").eq(req.header_all("via")));
863        assert_eq!(alloc::format!("{owned:?}"), alloc::format!("{req:?}"));
864        let (b, f, facts) = owned_parts(input);
865        let rebuilt = OwnedRequestHead::from_parts(b, f, facts).unwrap();
866        assert_eq!(rebuilt, owned);
867    }
868
869    #[test]
870    fn test_from_parts_accepts_every_valid_copy() {
871        for input in [
872            &b"GET / HTTP/1.1\r\nHost: a\r\n\r\n"[..],
873            b"\r\n\r\nGET / HTTP/1.0\r\n\r\n",
874            b"OPTIONS * HTTP/1.1\r\nHost: a\r\nX:\r\nY: \t \r\n\r\n",
875            b"CONNECT a:443 HTTP/1.1\r\nHost: a:443\r\n\r\n",
876            b"POST /x HTTP/1.1\r\nHost: \r\nTransfer-Encoding: chunked\r\n\r\n",
877        ] {
878            let (b, f, facts) = owned_parts(input);
879            assert!(
880                OwnedRequestHead::from_parts(b, f, facts).is_ok(),
881                "{input:?}"
882            );
883        }
884    }
885
886    /// Every way a passport buffer can be changed after the copy is refused.
887    #[test]
888    fn test_from_parts_refuses_every_tampered_part() {
889        let input = b"GET /a HTTP/1.1\r\nHost: h\r\nX-Two: v\r\n\r\n";
890        let (bytes, fields, facts) = owned_parts(input);
891        let refused = |b: Vec<u8>, f: Vec<FieldSpan>, facts: HeadFacts| {
892            matches!(
893                OwnedRequestHead::from_parts(b, f, facts),
894                Err(HttpError::InvalidState(_))
895            )
896        };
897        // Bytes changed under the spans.
898        let tamper_byte = |i: usize, b: u8| {
899            let mut v = bytes.clone();
900            v[i] = b;
901            v
902        };
903        assert!(refused(tamper_byte(0, b'P'), fields.clone(), facts)); // method
904        assert!(refused(tamper_byte(3, b'_'), fields.clone(), facts)); // SP after method
905        assert!(refused(tamper_byte(5, b'#'), fields.clone(), facts)); // target byte
906        assert!(refused(tamper_byte(13, b'2'), fields.clone(), facts)); // version
907        assert!(refused(tamper_byte(15, b'X'), fields.clone(), facts)); // start-line CRLF
908        assert!(refused(tamper_byte(17, b' '), fields.clone(), facts)); // name
909        assert!(refused(tamper_byte(21, b'='), fields.clone(), facts)); // colon
910        assert!(refused(tamper_byte(23, 0), fields.clone(), facts)); // value control byte
911        assert!(refused(tamper_byte(24, b'x'), fields.clone(), facts)); // field CRLF
912        let mut shorter = bytes.clone();
913        let _ = shorter.pop();
914        assert!(refused(shorter, fields.clone(), facts)); // blank line cut
915        let mut longer = bytes.clone();
916        longer.push(b'x');
917        assert!(refused(longer, fields.clone(), facts)); // bytes past the head
918        let mut leading = b"x\r\n".to_vec();
919        leading.extend_from_slice(&bytes);
920        assert!(refused(leading, fields.clone(), facts)); // junk before the start line
921        // Spans moved.
922        let tamper_field = |i: usize, change: &dyn Fn(&mut FieldSpan)| {
923            let mut f = fields.clone();
924            change(&mut f[i]);
925            f
926        };
927        assert!(refused(
928            bytes.clone(),
929            tamper_field(0, &|f| f.name.end += 1),
930            facts
931        ));
932        assert!(refused(
933            bytes.clone(),
934            tamper_field(0, &|f| f.name.start += 1),
935            facts
936        ));
937        assert!(refused(
938            bytes.clone(),
939            tamper_field(0, &|f| f.value.end += 50),
940            facts
941        ));
942        assert!(refused(
943            bytes.clone(),
944            tamper_field(0, &|f| f.value.start = 0),
945            facts
946        ));
947        assert!(refused(
948            bytes.clone(),
949            tamper_field(1, &|f| f.value.end -= 1),
950            facts
951        ));
952        assert!(refused(
953            bytes.clone(),
954            tamper_field(1, &|f| *f = FieldSpan::default()),
955            facts
956        ));
957        let mut swapped = fields.clone();
958        swapped.swap(0, 1);
959        assert!(refused(bytes.clone(), swapped, facts)); // out of order
960        let mut dropped = fields.clone();
961        let _ = dropped.pop();
962        assert!(refused(bytes.clone(), dropped, facts)); // a line no span covers
963        let mut doubled = fields.clone();
964        doubled.push(fields[1]);
965        assert!(refused(bytes.clone(), doubled, facts)); // overlapping
966        // Facts moved.
967        let tamper_facts = |change: &dyn Fn(&mut RequestInfo)| {
968            let mut info = facts.info;
969            change(&mut info);
970            HeadFacts { info }
971        };
972        assert!(refused(
973            bytes.clone(),
974            fields.clone(),
975            tamper_facts(&|i| i.start_line.end += 1)
976        ));
977        assert!(refused(
978            bytes.clone(),
979            fields.clone(),
980            tamper_facts(&|i| i.target.end += 1)
981        ));
982        assert!(refused(
983            bytes.clone(),
984            fields.clone(),
985            tamper_facts(&|i| i.method = Method::Post)
986        ));
987        assert!(refused(
988            bytes.clone(),
989            fields.clone(),
990            tamper_facts(&|i| i.host = Some(fields[1].value))
991        ));
992        assert!(refused(
993            bytes.clone(),
994            fields.clone(),
995            tamper_facts(&|i| i.origin = Span { start: 0, end: 3 })
996        ));
997        assert!(refused(
998            bytes.clone(),
999            fields.clone(),
1000            tamper_facts(&|i| i.authority = Some(Span { start: 0, end: 3 }))
1001        ));
1002        // The untouched parts are still accepted.
1003        assert!(OwnedRequestHead::from_parts(bytes, fields, facts).is_ok());
1004    }
1005
1006    #[test]
1007    fn test_stateless_request_parse_complete_partial_and_errors() {
1008        let mut fields = [FieldSpan::default(); 4];
1009        let input = b"GET / HTTP/1.1\r\nHost: a\r\n\r\nGET";
1010        let Ok(Parsed::Complete { head, len }) =
1011            parse_request_head(input, &Limits::new(), &mut fields)
1012        else {
1013            panic!()
1014        };
1015        assert_eq!(len, input.len() - 3);
1016        assert_eq!(head.view().host(), Some("a"));
1017        for cut in 0..len {
1018            let mut fields = [FieldSpan::default(); 4];
1019            assert!(matches!(
1020                parse_request_head(&input[..cut], &Limits::new(), &mut fields),
1021                Ok(Parsed::Partial)
1022            ));
1023        }
1024        let mut fields = [FieldSpan::default(); 4];
1025        assert_eq!(
1026            parse_request_head(b"GET / HTTP/1.1\r\n\r\n", &Limits::new(), &mut fields).err(),
1027            Some(HttpError::MissingHost)
1028        );
1029        assert_eq!(
1030            parse_request_head(
1031                b"GET / HTTP/1.1\nHost: a\r\n\r\n",
1032                &Limits::new(),
1033                &mut fields
1034            )
1035            .err(),
1036            Some(HttpError::BareLf)
1037        );
1038        // More fields than the caller's array holds.
1039        let mut one = [FieldSpan::default(); 1];
1040        assert_eq!(
1041            parse_request_head(
1042                b"GET / HTTP/1.1\r\nHost: a\r\nX: 1\r\n\r\n",
1043                &Limits::new(),
1044                &mut one
1045            )
1046            .err(),
1047            Some(HttpError::TooManyHeaders)
1048        );
1049        let mut none: [FieldSpan; 0] = [];
1050        assert!(matches!(
1051            parse_request_head(b"GET / HTTP/1.0\r\n\r\n", &Limits::new(), &mut none),
1052            Ok(Parsed::Complete { .. })
1053        ));
1054    }
1055
1056    #[test]
1057    fn test_stateless_response_parse_follows_what_was_asked() {
1058        let mut fields = [FieldSpan::default(); 4];
1059        let input = b"HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc";
1060        let Ok(Parsed::Complete { head, len }) =
1061            parse_response_head(input, &Limits::new(), Method::Get, &mut fields)
1062        else {
1063            panic!()
1064        };
1065        assert_eq!(head.view().framing(), crate::BodyFraming::Length(3));
1066        assert_eq!(&input[len..], b"abc");
1067        assert_eq!(
1068            head.view().raw().status().get(head.view().raw().bytes()),
1069            b"200"
1070        );
1071        let mut fields = [FieldSpan::default(); 4];
1072        let Ok(Parsed::Complete { head, .. }) =
1073            parse_response_head(input, &Limits::new(), Method::Connect, &mut fields)
1074        else {
1075            panic!()
1076        };
1077        assert_eq!(head.view().framing(), crate::BodyFraming::None);
1078        let mut fields = [FieldSpan::default(); 4];
1079        assert_eq!(
1080            parse_response_head(
1081                b"\r\nHTTP/1.1 200 OK\r\n\r\n",
1082                &Limits::new(),
1083                Method::Get,
1084                &mut fields
1085            )
1086            .err(),
1087            Some(HttpError::InvalidStartLine)
1088        );
1089        let mut fields = [FieldSpan::default(); 4];
1090        assert!(matches!(
1091            parse_response_head(b"HTTP/1.1 103 Early Hints\r\nLink: </a>\r\n\r\n", &Limits::new(), Method::Get, &mut fields),
1092            Ok(Parsed::Complete { head, .. }) if head.view().is_informational()
1093        ));
1094        let v = vec![b'x'; 3];
1095        let mut fields = [FieldSpan::default(); 4];
1096        assert!(matches!(
1097            parse_response_head(&v, &Limits::new(), Method::Get, &mut fields),
1098            Ok(Parsed::Partial)
1099        ));
1100    }
1101}