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}