micro_http/codec/
request_decoder.rs

1//! HTTP request decoder module
2//!
3//! This module provides functionality for decoding HTTP requests using a streaming approach.
4//! It handles both header parsing and payload decoding through a state machine pattern.
5//!
6//! # Components
7//!
8//! - [`RequestDecoder`]: Main decoder that coordinates header and payload parsing
9//! - Header parsing: Uses [`HeaderDecoder`] for parsing request headers
10//! - Payload handling: Uses [`PayloadDecoder`] for handling request bodies if any
11//!
12//! # Example
13//!
14//! ```no_run
15//! use micro_http::codec::RequestDecoder;
16//! use tokio_util::codec::Decoder;
17//! use bytes::BytesMut;
18//!
19//! let mut decoder = RequestDecoder::new();
20//! let mut buffer = BytesMut::new();
21//! // ... add request data to buffer ...
22//! let result = decoder.decode(&mut buffer);
23//! ```
24
25use crate::codec::body::PayloadDecoder;
26use crate::codec::header::HeaderDecoder;
27use crate::protocol::{Message, ParseError, PayloadItem, PayloadSize, RequestHeader};
28use bytes::BytesMut;
29use tokio_util::codec::Decoder;
30
31/// A decoder for HTTP requests that handles both headers and payload
32///
33/// The decoder operates in two phases:
34/// 1. Header parsing: Decodes the request headers using [`HeaderDecoder`]
35/// 2. Payload parsing: If present, decodes the request body using [`PayloadDecoder`]
36///
37/// # State Machine
38///
39/// The decoder maintains its state through the `payload_decoder` field:
40/// - `None`: Currently parsing headers
41/// - `Some(PayloadDecoder)`: Currently parsing payload
42#[derive(Debug)]
43pub struct RequestDecoder {
44    header_decoder: HeaderDecoder,
45    payload_decoder: Option<PayloadDecoder>,
46}
47
48impl RequestDecoder {
49    /// Creates a new `RequestDecoder` instance
50    pub fn new() -> Self {
51        Default::default()
52    }
53}
54
55impl Default for RequestDecoder {
56    fn default() -> Self {
57        Self { header_decoder: HeaderDecoder, payload_decoder: None }
58    }
59}
60
61impl Decoder for RequestDecoder {
62    type Item = Message<(RequestHeader, PayloadSize)>;
63    type Error = ParseError;
64
65    /// Attempts to decode an HTTP request from the provided buffer
66    ///
67    /// # Returns
68    ///
69    /// - `Ok(Some(Message::Header(_)))`: Successfully decoded request headers
70    /// - `Ok(Some(Message::Payload(_)))`: Successfully decoded a payload chunk
71    /// - `Ok(None)`: Need more data to proceed
72    /// - `Err(_)`: Encountered a parsing error
73    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
74        // parse payload if have payload_decoder
75        if let Some(payload_decoder) = &mut self.payload_decoder {
76            let message = match payload_decoder.decode(src)? {
77                Some(item @ PayloadItem::Chunk(_)) => Some(Message::Payload(item)),
78                Some(item @ PayloadItem::Eof) => {
79                    // no need payload decoder in this request now
80                    self.payload_decoder.take();
81                    Some(Message::Payload(item))
82                }
83                None => None,
84            };
85
86            return Ok(message);
87        }
88
89        // parse request
90        let message = match self.header_decoder.decode(src)? {
91            Some((header, payload_size)) => {
92                self.payload_decoder = Some(payload_size.into());
93                Some(Message::Header((header, payload_size)))
94            }
95            None => None,
96        };
97
98        Ok(message)
99    }
100}