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
42pub struct RequestDecoder {
43    header_decoder: HeaderDecoder,
44    payload_decoder: Option<PayloadDecoder>,
45}
46
47impl RequestDecoder {
48    /// Creates a new `RequestDecoder` instance
49    pub fn new() -> Self {
50        Default::default()
51    }
52}
53
54impl Default for RequestDecoder {
55    fn default() -> Self {
56        Self { header_decoder: HeaderDecoder, payload_decoder: None }
57    }
58}
59
60impl Decoder for RequestDecoder {
61    type Item = Message<(RequestHeader, PayloadSize)>;
62    type Error = ParseError;
63
64    /// Attempts to decode an HTTP request from the provided buffer
65    ///
66    /// # Returns
67    ///
68    /// - `Ok(Some(Message::Header(_)))`: Successfully decoded request headers
69    /// - `Ok(Some(Message::Payload(_)))`: Successfully decoded a payload chunk
70    /// - `Ok(None)`: Need more data to proceed
71    /// - `Err(_)`: Encountered a parsing error
72    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
73        // parse payload if have payload_decoder
74        if let Some(payload_decoder) = &mut self.payload_decoder {
75            let message = match payload_decoder.decode(src)? {
76                Some(item @ PayloadItem::Chunk(_)) => Some(Message::Payload(item)),
77                Some(item @ PayloadItem::Eof) => {
78                    // no need payload decoder in this request now
79                    self.payload_decoder.take();
80                    Some(Message::Payload(item))
81                }
82                None => None,
83            };
84
85            return Ok(message);
86        }
87
88        // parse request
89        let message = match self.header_decoder.decode(src)? {
90            Some((header, payload_size)) => {
91                self.payload_decoder = Some(payload_size.into());
92                Some(Message::Header((header, payload_size)))
93            }
94            None => None,
95        };
96
97        Ok(message)
98    }
99}