micro_http/codec/
request_decoder.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! HTTP request decoder module
//! 
//! This module provides functionality for decoding HTTP requests using a streaming approach.
//! It handles both header parsing and payload decoding through a state machine pattern.
//! 
//! # Components
//! 
//! - [`RequestDecoder`]: Main decoder that coordinates header and payload parsing
//! - Header parsing: Uses [`HeaderDecoder`] for parsing request headers
//! - Payload handling: Uses [`PayloadDecoder`] for handling request bodies if any
//! 
//! # Example
//! 
//! ```no_run
//! use micro_http::codec::RequestDecoder;
//! use tokio_util::codec::Decoder;
//! use bytes::BytesMut;
//! 
//! let mut decoder = RequestDecoder::new();
//! let mut buffer = BytesMut::new();
//! // ... add request data to buffer ...
//! let result = decoder.decode(&mut buffer);
//! ```

use crate::codec::body::PayloadDecoder;
use crate::codec::header::HeaderDecoder;
use crate::protocol::{Message, ParseError, PayloadItem, RequestHeader};
use bytes::BytesMut;
use tokio_util::codec::Decoder;

/// A decoder for HTTP requests that handles both headers and payload
/// 
/// The decoder operates in two phases:
/// 1. Header parsing: Decodes the request headers using [`HeaderDecoder`]
/// 2. Payload parsing: If present, decodes the request body using [`PayloadDecoder`]
/// 
/// # State Machine
/// 
/// The decoder maintains its state through the `payload_decoder` field:
/// - `None`: Currently parsing headers
/// - `Some(PayloadDecoder)`: Currently parsing payload
pub struct RequestDecoder {
    header_decoder: HeaderDecoder,
    payload_decoder: Option<PayloadDecoder>,
}

impl RequestDecoder {
    /// Creates a new `RequestDecoder` instance
    pub fn new() -> Self {
        Default::default()
    }
}

impl Default for RequestDecoder {
    fn default() -> Self {
        Self { header_decoder: HeaderDecoder, payload_decoder: None }
    }
}

impl Decoder for RequestDecoder {
    type Item = Message<RequestHeader>;
    type Error = ParseError;

    /// Attempts to decode an HTTP request from the provided buffer
    /// 
    /// # Returns
    /// 
    /// - `Ok(Some(Message::Header(_)))`: Successfully decoded request headers
    /// - `Ok(Some(Message::Payload(_)))`: Successfully decoded a payload chunk
    /// - `Ok(None)`: Need more data to proceed
    /// - `Err(_)`: Encountered a parsing error
    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        // parse payload if have payload_decoder
        if let Some(payload_decoder) = &mut self.payload_decoder {
            let message = match payload_decoder.decode(src)? {
                Some(item @ PayloadItem::Chunk(_)) => Some(Message::Payload(item)),
                Some(item @ PayloadItem::Eof) => {
                    // no need payload decoder in this request now
                    self.payload_decoder.take();
                    Some(Message::Payload(item))
                }
                None => None,
            };

            return Ok(message);
        }

        // parse request
        let message = match self.header_decoder.decode(src)? {
            Some((header, payload_decoder)) => {
                self.payload_decoder = Some(payload_decoder);
                Some(Message::Header(header))
            }
            None => None,
        };

        Ok(message)
    }
}