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}