reinhardt_core/parsers/
form.rs1use async_trait::async_trait;
2use bytes::Bytes;
3use http::HeaderMap;
4use std::collections::HashMap;
5
6use super::parser::{ParseError, ParseResult, ParsedData, Parser};
7
8#[derive(Debug, Clone, Default)]
10pub struct FormParser;
11
12impl FormParser {
13 pub fn new() -> Self {
23 Self
24 }
25}
26
27#[async_trait]
28impl Parser for FormParser {
29 fn media_types(&self) -> Vec<String> {
30 vec!["application/x-www-form-urlencoded".to_string()]
31 }
32
33 async fn parse(
34 &self,
35 _content_type: Option<&str>,
36 body: Bytes,
37 _headers: &HeaderMap,
38 ) -> ParseResult<ParsedData> {
39 if body.is_empty() {
40 return Ok(ParsedData::Form(HashMap::new()));
41 }
42
43 match serde_urlencoded::from_bytes::<HashMap<String, String>>(&body) {
44 Ok(form_data) => Ok(ParsedData::Form(form_data)),
45 Err(e) => Err(ParseError::ParseError(format!("Invalid form data: {}", e))),
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[tokio::test]
55 async fn test_form_parser_valid() {
56 let parser = FormParser::new();
57 let body = Bytes::from("name=test&value=123&active=true");
58 let headers = HeaderMap::new();
59
60 let result = parser
61 .parse(Some("application/x-www-form-urlencoded"), body, &headers)
62 .await
63 .unwrap();
64
65 match result {
66 ParsedData::Form(form) => {
67 assert_eq!(form.get("name"), Some(&"test".to_string()));
68 assert_eq!(form.get("value"), Some(&"123".to_string()));
69 assert_eq!(form.get("active"), Some(&"true".to_string()));
70 }
71 _ => panic!("Expected form data"),
72 }
73 }
74
75 #[tokio::test]
76 async fn test_form_parser_empty() {
77 let parser = FormParser::new();
78 let body = Bytes::new();
79 let headers = HeaderMap::new();
80
81 let result = parser
82 .parse(Some("application/x-www-form-urlencoded"), body, &headers)
83 .await
84 .unwrap();
85
86 match result {
87 ParsedData::Form(form) => {
88 assert!(form.is_empty());
89 }
90 _ => panic!("Expected form data"),
91 }
92 }
93
94 #[tokio::test]
95 async fn test_form_parser_url_encoded() {
96 let parser = FormParser::new();
97 let body = Bytes::from("message=Hello%20World&symbol=%26");
98 let headers = HeaderMap::new();
99
100 let result = parser
101 .parse(Some("application/x-www-form-urlencoded"), body, &headers)
102 .await
103 .unwrap();
104
105 match result {
106 ParsedData::Form(form) => {
107 assert_eq!(form.get("message"), Some(&"Hello World".to_string()));
108 assert_eq!(form.get("symbol"), Some(&"&".to_string()));
109 }
110 _ => panic!("Expected form data"),
111 }
112 }
113
114 #[test]
115 fn test_form_parser_media_types() {
116 let parser = FormParser::new();
117 let media_types = parser.media_types();
118
119 assert!(media_types.contains(&"application/x-www-form-urlencoded".to_string()));
120 }
121
122 #[tokio::test]
125 async fn test_form_parse_drf() {
126 let parser = FormParser::new();
128 let body = Bytes::from("field1=abc&field2=defghijk");
129 let headers = HeaderMap::new();
130
131 let result = parser
132 .parse(Some("application/x-www-form-urlencoded"), body, &headers)
133 .await
134 .unwrap();
135
136 match result {
137 ParsedData::Form(form) => {
138 assert_eq!(form.get("field1"), Some(&"abc".to_string()));
140 assert_eq!(form.get("field2"), Some(&"defghijk".to_string()));
141
142 let field1_valid = form.get("field1").map(|v| v.len() <= 3).unwrap_or(false);
144 assert!(field1_valid);
145 }
146 _ => panic!("Expected form data"),
147 }
148 }
149}