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