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