1use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::collections::HashMap;
9use std::sync::Arc;
10
11#[cfg(feature = "di")]
12use crate::di::ResolvedDependencies;
13#[cfg(feature = "di")]
14use bytes::Bytes;
15
16#[derive(Debug, Clone)]
27pub struct RequestData {
28 pub path_params: Arc<HashMap<String, String>>,
30 pub query_params: Value,
32 pub validated_params: Option<Value>,
34 pub raw_query_params: Arc<HashMap<String, Vec<String>>>,
36 pub body: Value,
38 #[cfg(feature = "di")]
40 pub raw_body: Option<Bytes>,
41 #[cfg(not(feature = "di"))]
42 pub raw_body: Option<Vec<u8>>,
43 pub headers: Arc<HashMap<String, String>>,
45 pub cookies: Arc<HashMap<String, String>>,
47 pub method: String,
49 pub path: String,
51 #[cfg(feature = "di")]
53 pub dependencies: Option<Arc<ResolvedDependencies>>,
54}
55
56impl Serialize for RequestData {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: serde::Serializer,
60 {
61 use serde::ser::SerializeStruct;
62 let mut state = serializer.serialize_struct("RequestData", 10)?;
63 state.serialize_field("path_params", &*self.path_params)?;
64 state.serialize_field("query_params", &self.query_params)?;
65 state.serialize_field("validated_params", &self.validated_params)?;
66 state.serialize_field("raw_query_params", &*self.raw_query_params)?;
67 state.serialize_field("body", &self.body)?;
68 #[cfg(feature = "di")]
69 state.serialize_field("raw_body", &self.raw_body.as_ref().map(|b| b.as_ref()))?;
70 #[cfg(not(feature = "di"))]
71 state.serialize_field("raw_body", &self.raw_body)?;
72 state.serialize_field("headers", &*self.headers)?;
73 state.serialize_field("cookies", &*self.cookies)?;
74 state.serialize_field("method", &self.method)?;
75 state.serialize_field("path", &self.path)?;
76 state.end()
77 }
78}
79
80impl<'de> Deserialize<'de> for RequestData {
81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82 where
83 D: serde::Deserializer<'de>,
84 {
85 #[derive(Deserialize)]
86 #[serde(field_identifier, rename_all = "snake_case")]
87 enum Field {
88 PathParams,
89 QueryParams,
90 ValidatedParams,
91 RawQueryParams,
92 Body,
93 RawBody,
94 Headers,
95 Cookies,
96 Method,
97 Path,
98 }
99
100 struct RequestDataVisitor;
101
102 impl<'de> serde::de::Visitor<'de> for RequestDataVisitor {
103 type Value = RequestData;
104
105 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
106 formatter.write_str("struct RequestData")
107 }
108
109 fn visit_map<V>(self, mut map: V) -> Result<RequestData, V::Error>
110 where
111 V: serde::de::MapAccess<'de>,
112 {
113 let mut path_params = None;
114 let mut query_params = None;
115 let mut validated_params = None;
116 let mut raw_query_params = None;
117 let mut body = None;
118 let mut raw_body = None;
119 let mut headers = None;
120 let mut cookies = None;
121 let mut method = None;
122 let mut path = None;
123
124 while let Some(key) = map.next_key()? {
125 match key {
126 Field::PathParams => {
127 path_params = Some(Arc::new(map.next_value()?));
128 }
129 Field::QueryParams => {
130 query_params = Some(map.next_value()?);
131 }
132 Field::ValidatedParams => {
133 validated_params = Some(map.next_value()?);
134 }
135 Field::RawQueryParams => {
136 raw_query_params = Some(Arc::new(map.next_value()?));
137 }
138 Field::Body => {
139 body = Some(map.next_value()?);
140 }
141 Field::RawBody => {
142 let bytes_vec: Option<Vec<u8>> = map.next_value()?;
143 #[cfg(feature = "di")]
144 {
145 raw_body = bytes_vec.map(Bytes::from);
146 }
147 #[cfg(not(feature = "di"))]
148 {
149 raw_body = bytes_vec;
150 }
151 }
152 Field::Headers => {
153 headers = Some(Arc::new(map.next_value()?));
154 }
155 Field::Cookies => {
156 cookies = Some(Arc::new(map.next_value()?));
157 }
158 Field::Method => {
159 method = Some(map.next_value()?);
160 }
161 Field::Path => {
162 path = Some(map.next_value()?);
163 }
164 }
165 }
166
167 Ok(RequestData {
168 path_params: path_params.ok_or_else(|| serde::de::Error::missing_field("path_params"))?,
169 query_params: query_params.ok_or_else(|| serde::de::Error::missing_field("query_params"))?,
170 validated_params,
171 raw_query_params: raw_query_params
172 .ok_or_else(|| serde::de::Error::missing_field("raw_query_params"))?,
173 body: body.ok_or_else(|| serde::de::Error::missing_field("body"))?,
174 raw_body,
175 headers: headers.ok_or_else(|| serde::de::Error::missing_field("headers"))?,
176 cookies: cookies.ok_or_else(|| serde::de::Error::missing_field("cookies"))?,
177 method: method.ok_or_else(|| serde::de::Error::missing_field("method"))?,
178 path: path.ok_or_else(|| serde::de::Error::missing_field("path"))?,
179 #[cfg(feature = "di")]
180 dependencies: None,
181 })
182 }
183 }
184
185 const FIELDS: &[&str] = &[
186 "path_params",
187 "query_params",
188 "validated_params",
189 "raw_query_params",
190 "body",
191 "raw_body",
192 "headers",
193 "cookies",
194 "method",
195 "path",
196 ];
197 deserializer.deserialize_struct("RequestData", FIELDS, RequestDataVisitor)
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use serde_json::{Value, json};
205
206 #[derive(Default)]
207 struct RequestDataCollections {
208 raw_query_params: HashMap<String, Vec<String>>,
209 headers: HashMap<String, String>,
210 cookies: HashMap<String, String>,
211 path_params: HashMap<String, String>,
212 }
213
214 fn create_request_data(
215 path: &str,
216 method: &str,
217 body: Value,
218 query_params: Value,
219 collections: RequestDataCollections,
220 ) -> RequestData {
221 RequestData {
222 path_params: Arc::new(collections.path_params),
223 query_params,
224 validated_params: None,
225 raw_query_params: Arc::new(collections.raw_query_params),
226 body,
227 raw_body: None,
228 headers: Arc::new(collections.headers),
229 cookies: Arc::new(collections.cookies),
230 method: method.to_string(),
231 path: path.to_string(),
232 #[cfg(feature = "di")]
233 dependencies: None,
234 }
235 }
236
237 #[test]
238 fn test_request_data_minimal() {
239 let data = create_request_data(
240 "/api/users",
241 "GET",
242 json!(null),
243 json!({}),
244 RequestDataCollections::default(),
245 );
246
247 assert_eq!(data.path, "/api/users");
248 assert_eq!(data.method, "GET");
249 assert_eq!(data.body, json!(null));
250 }
251
252 #[test]
253 fn test_request_data_with_json_body() {
254 let body = json!({
255 "name": "test_user",
256 "email": "test@example.com",
257 "age": 30
258 });
259
260 let data = create_request_data(
261 "/api/users",
262 "POST",
263 body.clone(),
264 json!({}),
265 RequestDataCollections::default(),
266 );
267
268 assert_eq!(data.body, body);
269 assert_eq!(data.body["name"], "test_user");
270 assert_eq!(data.body["email"], "test@example.com");
271 assert_eq!(data.body["age"], 30);
272 }
273
274 #[test]
275 fn test_request_data_with_query_params() {
276 let mut raw_query_params = HashMap::new();
277 raw_query_params.insert("page".to_string(), vec!["1".to_string()]);
278 raw_query_params.insert("limit".to_string(), vec!["10".to_string()]);
279 raw_query_params.insert("tags".to_string(), vec!["rust".to_string(), "web".to_string()]);
280
281 let query_params = json!({
282 "page": "1",
283 "limit": "10",
284 "tags": ["rust", "web"]
285 });
286
287 let data = create_request_data(
288 "/api/users",
289 "GET",
290 json!(null),
291 query_params,
292 RequestDataCollections {
293 raw_query_params,
294 ..Default::default()
295 },
296 );
297
298 assert_eq!(data.raw_query_params.get("page"), Some(&vec!["1".to_string()]));
299 assert_eq!(data.raw_query_params.get("limit"), Some(&vec!["10".to_string()]));
300 assert_eq!(
301 data.raw_query_params.get("tags"),
302 Some(&vec!["rust".to_string(), "web".to_string()])
303 );
304 }
305
306 #[test]
307 fn test_request_data_with_headers() {
308 let mut headers = HashMap::new();
309 headers.insert("content-type".to_string(), "application/json".to_string());
310 headers.insert("authorization".to_string(), "Bearer token123".to_string());
311 headers.insert("user-agent".to_string(), "Mozilla/5.0".to_string());
312
313 let data = create_request_data(
314 "/api/users",
315 "GET",
316 json!(null),
317 json!({}),
318 RequestDataCollections {
319 headers,
320 ..Default::default()
321 },
322 );
323
324 assert_eq!(data.headers.get("content-type"), Some(&"application/json".to_string()));
325 assert_eq!(data.headers.get("authorization"), Some(&"Bearer token123".to_string()));
326 assert_eq!(data.headers.get("user-agent"), Some(&"Mozilla/5.0".to_string()));
327 }
328
329 #[test]
330 fn test_request_data_with_cookies() {
331 let mut cookies = HashMap::new();
332 cookies.insert("session_id".to_string(), "abc123xyz".to_string());
333 cookies.insert("user_id".to_string(), "user_42".to_string());
334 cookies.insert("theme".to_string(), "dark".to_string());
335
336 let data = create_request_data(
337 "/api/users",
338 "GET",
339 json!(null),
340 json!({}),
341 RequestDataCollections {
342 cookies,
343 ..Default::default()
344 },
345 );
346
347 assert_eq!(data.cookies.get("session_id"), Some(&"abc123xyz".to_string()));
348 assert_eq!(data.cookies.get("user_id"), Some(&"user_42".to_string()));
349 assert_eq!(data.cookies.get("theme"), Some(&"dark".to_string()));
350 }
351
352 #[test]
353 fn test_request_data_with_path_params() {
354 let mut path_params = HashMap::new();
355 path_params.insert("user_id".to_string(), "123".to_string());
356 path_params.insert("post_id".to_string(), "456".to_string());
357
358 let data = create_request_data(
359 "/api/users/123/posts/456",
360 "GET",
361 json!(null),
362 json!({}),
363 RequestDataCollections {
364 path_params,
365 ..Default::default()
366 },
367 );
368
369 assert_eq!(data.path_params.get("user_id"), Some(&"123".to_string()));
370 assert_eq!(data.path_params.get("post_id"), Some(&"456".to_string()));
371 }
372
373 #[test]
374 fn test_request_data_all_fields_populated() {
375 let mut path_params = HashMap::new();
376 path_params.insert("id".to_string(), "user_99".to_string());
377
378 let mut raw_query_params = HashMap::new();
379 raw_query_params.insert("filter".to_string(), vec!["active".to_string()]);
380
381 let mut headers = HashMap::new();
382 headers.insert("content-type".to_string(), "application/json".to_string());
383
384 let mut cookies = HashMap::new();
385 cookies.insert("session".to_string(), "xyz789".to_string());
386
387 let body = json!({
388 "name": "John",
389 "email": "john@example.com"
390 });
391
392 let query_params = json!({
393 "filter": "active"
394 });
395
396 let data = create_request_data(
397 "/api/users/user_99",
398 "PUT",
399 body,
400 query_params,
401 RequestDataCollections {
402 raw_query_params,
403 headers,
404 cookies,
405 path_params,
406 },
407 );
408
409 assert_eq!(data.path, "/api/users/user_99");
410 assert_eq!(data.method, "PUT");
411 assert_eq!(data.path_params.get("id"), Some(&"user_99".to_string()));
412 assert_eq!(data.body["name"], "John");
413 assert_eq!(data.headers.get("content-type"), Some(&"application/json".to_string()));
414 assert_eq!(data.cookies.get("session"), Some(&"xyz789".to_string()));
415 }
416
417 #[test]
418 fn test_request_data_empty_collections() {
419 let data = create_request_data(
420 "/api/test",
421 "GET",
422 json!(null),
423 json!({}),
424 RequestDataCollections::default(),
425 );
426
427 assert!(data.path_params.is_empty());
428 assert!(data.raw_query_params.is_empty());
429 assert!(data.headers.is_empty());
430 assert!(data.cookies.is_empty());
431 }
432
433 #[test]
434 fn test_request_data_clone() {
435 let mut path_params = HashMap::new();
436 path_params.insert("id".to_string(), "123".to_string());
437
438 let data1 = create_request_data(
439 "/api/users/123",
440 "GET",
441 json!({"name": "test"}),
442 json!({}),
443 RequestDataCollections {
444 path_params,
445 ..Default::default()
446 },
447 );
448
449 let data2 = data1.clone();
450
451 assert_eq!(data1.path, data2.path);
452 assert_eq!(data1.method, data2.method);
453 assert_eq!(data1.body, data2.body);
454 assert_eq!(data1.path_params, data2.path_params);
455 }
456
457 #[test]
458 fn test_request_data_various_http_methods() {
459 let methods = vec!["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
460
461 for method in methods {
462 let data = create_request_data(
463 "/api/test",
464 method,
465 json!(null),
466 json!({}),
467 RequestDataCollections::default(),
468 );
469
470 assert_eq!(data.method, method);
471 }
472 }
473
474 #[test]
475 fn test_request_data_raw_body_none() {
476 let data = create_request_data(
477 "/api/test",
478 "GET",
479 json!(null),
480 json!({}),
481 RequestDataCollections::default(),
482 );
483
484 assert!(data.raw_body.is_none());
485 }
486
487 #[cfg(not(feature = "di"))]
488 #[test]
489 fn test_request_data_raw_body_some() {
490 let raw_body_bytes = vec![1, 2, 3, 4, 5];
491 let mut data = create_request_data(
492 "/api/test",
493 "POST",
494 json!(null),
495 json!({}),
496 RequestDataCollections::default(),
497 );
498
499 data.raw_body = Some(raw_body_bytes.clone());
500 assert_eq!(data.raw_body, Some(raw_body_bytes));
501 }
502
503 #[cfg(not(feature = "di"))]
504 #[test]
505 fn request_data_serializes_and_deserializes() {
506 let mut headers = HashMap::new();
507 headers.insert("content-type".to_string(), "application/json".to_string());
508
509 let mut cookies = HashMap::new();
510 cookies.insert("session".to_string(), "abc".to_string());
511
512 let mut raw_query_params = HashMap::new();
513 raw_query_params.insert("tags".to_string(), vec!["rust".to_string(), "http".to_string()]);
514
515 let mut path_params = HashMap::new();
516 path_params.insert("id".to_string(), "123".to_string());
517
518 let mut data = create_request_data(
519 "/api/items/123",
520 "POST",
521 json!({"name": "demo"}),
522 json!({"tags": ["rust", "http"]}),
523 RequestDataCollections {
524 raw_query_params,
525 headers,
526 cookies,
527 path_params,
528 },
529 );
530 data.raw_body = Some(vec![9, 8, 7]);
531
532 let encoded = serde_json::to_string(&data).expect("serialize RequestData");
533 let decoded: RequestData = serde_json::from_str(&encoded).expect("deserialize RequestData");
534
535 assert_eq!(decoded.path, "/api/items/123");
536 assert_eq!(decoded.method, "POST");
537 assert_eq!(decoded.body["name"], "demo");
538 assert_eq!(decoded.query_params["tags"][0], "rust");
539 assert_eq!(
540 decoded.raw_query_params.get("tags").unwrap(),
541 &vec!["rust".to_string(), "http".to_string()]
542 );
543 assert_eq!(decoded.headers.get("content-type").unwrap(), "application/json");
544 assert_eq!(decoded.cookies.get("session").unwrap(), "abc");
545 assert_eq!(decoded.path_params.get("id").unwrap(), "123");
546 assert_eq!(decoded.raw_body, Some(vec![9, 8, 7]));
547 }
548
549 #[test]
550 fn test_request_data_multiple_query_param_values() {
551 let mut raw_query_params = HashMap::new();
552 raw_query_params.insert(
553 "colors".to_string(),
554 vec!["red".to_string(), "green".to_string(), "blue".to_string()],
555 );
556
557 let data = create_request_data(
558 "/api/items",
559 "GET",
560 json!(null),
561 json!({}),
562 RequestDataCollections {
563 raw_query_params,
564 ..Default::default()
565 },
566 );
567
568 let colors = data.raw_query_params.get("colors").unwrap();
569 assert_eq!(colors.len(), 3);
570 assert!(colors.contains(&"red".to_string()));
571 assert!(colors.contains(&"green".to_string()));
572 assert!(colors.contains(&"blue".to_string()));
573 }
574
575 #[test]
576 fn test_request_data_complex_json_body() {
577 let body = json!({
578 "user": {
579 "name": "Alice",
580 "profile": {
581 "age": 28,
582 "location": "San Francisco"
583 }
584 },
585 "tags": ["admin", "active"],
586 "metadata": {
587 "created_at": "2024-01-01",
588 "updated_at": "2024-12-01"
589 }
590 });
591
592 let data = create_request_data("/api/users", "POST", body, json!({}), RequestDataCollections::default());
593
594 assert_eq!(data.body["user"]["name"], "Alice");
595 assert_eq!(data.body["user"]["profile"]["age"], 28);
596 assert_eq!(data.body["tags"][0], "admin");
597 assert_eq!(data.body["metadata"]["created_at"], "2024-01-01");
598 }
599
600 #[test]
601 fn test_request_data_special_characters_in_paths() {
602 let data = create_request_data(
603 "/api/users/john@example.com/posts",
604 "GET",
605 json!(null),
606 json!({}),
607 RequestDataCollections::default(),
608 );
609
610 assert_eq!(data.path, "/api/users/john@example.com/posts");
611 }
612
613 #[test]
614 fn test_request_data_special_characters_in_params() {
615 let mut path_params = HashMap::new();
616 path_params.insert("email".to_string(), "test@example.com".to_string());
617 path_params.insert("slug".to_string(), "my-post-title".to_string());
618
619 let data = create_request_data(
620 "/api/users/test@example.com",
621 "GET",
622 json!(null),
623 json!({}),
624 RequestDataCollections {
625 path_params,
626 ..Default::default()
627 },
628 );
629
630 assert_eq!(data.path_params.get("email"), Some(&"test@example.com".to_string()));
631 assert_eq!(data.path_params.get("slug"), Some(&"my-post-title".to_string()));
632 }
633
634 #[test]
635 fn test_request_data_null_and_empty_values() {
636 let body = json!({
637 "name": null,
638 "email": "",
639 "age": 0,
640 "active": false
641 });
642
643 let data = create_request_data("/api/users", "POST", body, json!({}), RequestDataCollections::default());
644
645 assert!(data.body["name"].is_null());
646 assert_eq!(data.body["email"], "");
647 assert_eq!(data.body["age"], 0);
648 assert_eq!(data.body["active"], false);
649 }
650
651 #[test]
652 fn test_request_data_serialization() {
653 let mut path_params = HashMap::new();
654 path_params.insert("id".to_string(), "123".to_string());
655
656 let mut headers = HashMap::new();
657 headers.insert("content-type".to_string(), "application/json".to_string());
658
659 let data = create_request_data(
660 "/api/users/123",
661 "GET",
662 json!({"name": "test"}),
663 json!({"page": "1"}),
664 RequestDataCollections {
665 headers,
666 path_params,
667 ..Default::default()
668 },
669 );
670
671 let serialized = serde_json::to_string(&data);
672 assert!(serialized.is_ok());
673 }
674
675 #[test]
676 fn test_request_data_delete_request() {
677 let mut path_params = HashMap::new();
678 path_params.insert("id".to_string(), "999".to_string());
679
680 let data = create_request_data(
681 "/api/users/999",
682 "DELETE",
683 json!(null),
684 json!({}),
685 RequestDataCollections {
686 path_params,
687 ..Default::default()
688 },
689 );
690
691 assert_eq!(data.method, "DELETE");
692 assert_eq!(data.path_params.get("id"), Some(&"999".to_string()));
693 }
694
695 #[test]
696 fn test_request_data_array_body() {
697 let body = json!([
698 {"id": 1, "name": "item1"},
699 {"id": 2, "name": "item2"},
700 {"id": 3, "name": "item3"}
701 ]);
702
703 let data = create_request_data("/api/items", "POST", body, json!({}), RequestDataCollections::default());
704
705 assert!(data.body.is_array());
706 assert_eq!(data.body.as_array().unwrap().len(), 3);
707 assert_eq!(data.body[0]["id"], 1);
708 assert_eq!(data.body[2]["name"], "item3");
709 }
710
711 #[test]
712 fn test_request_data_case_sensitive_keys() {
713 let mut headers = HashMap::new();
714 headers.insert("Content-Type".to_string(), "application/json".to_string());
715 headers.insert("content-type".to_string(), "text/plain".to_string());
716
717 let data = create_request_data(
718 "/api/test",
719 "GET",
720 json!(null),
721 json!({}),
722 RequestDataCollections {
723 headers,
724 ..Default::default()
725 },
726 );
727
728 assert_eq!(data.headers.get("Content-Type"), Some(&"application/json".to_string()));
729 assert_eq!(data.headers.get("content-type"), Some(&"text/plain".to_string()));
730 }
731
732 #[test]
733 fn test_request_data_serialization_with_all_fields() {
734 let mut path_params = HashMap::new();
735 path_params.insert("id".to_string(), "42".to_string());
736
737 let mut raw_query_params = HashMap::new();
738 raw_query_params.insert("page".to_string(), vec!["2".to_string()]);
739
740 let mut headers = HashMap::new();
741 headers.insert("authorization".to_string(), "Bearer xyz".to_string());
742
743 let mut cookies = HashMap::new();
744 cookies.insert("token".to_string(), "abc123".to_string());
745
746 let data = create_request_data(
747 "/api/resource/42",
748 "PUT",
749 json!({"status": "updated"}),
750 json!({"page": "2"}),
751 RequestDataCollections {
752 raw_query_params,
753 headers,
754 cookies,
755 path_params,
756 },
757 );
758
759 let serialized = serde_json::to_string(&data).expect("serialization failed");
760 assert!(!serialized.is_empty());
761 assert!(serialized.contains("\"id\":\"42\""));
762 assert!(serialized.contains("PUT"));
763 }
764
765 #[test]
766 fn test_request_data_deserialization() {
767 let json_str = r#"{
768 "path_params": {"user_id": "123"},
769 "query_params": {"page": "1"},
770 "raw_query_params": {"page": ["1"]},
771 "body": {"name": "test"},
772 "raw_body": null,
773 "headers": {"content-type": "application/json"},
774 "cookies": {"session": "abc"},
775 "method": "POST",
776 "path": "/api/users"
777 }"#;
778
779 let deserialized: RequestData = serde_json::from_str(json_str).expect("deserialization failed");
780
781 assert_eq!(deserialized.method, "POST");
782 assert_eq!(deserialized.path, "/api/users");
783 assert_eq!(deserialized.path_params.get("user_id"), Some(&"123".to_string()));
784 assert_eq!(deserialized.body["name"], "test");
785 assert_eq!(
786 deserialized.headers.get("content-type"),
787 Some(&"application/json".to_string())
788 );
789 assert_eq!(deserialized.cookies.get("session"), Some(&"abc".to_string()));
790 }
791
792 #[test]
793 fn test_request_data_roundtrip_serialization() {
794 let mut path_params = HashMap::new();
795 path_params.insert("item_id".to_string(), "789".to_string());
796
797 let mut raw_query_params = HashMap::new();
798 raw_query_params.insert("sort".to_string(), vec!["desc".to_string()]);
799
800 let mut headers = HashMap::new();
801 headers.insert("x-custom-header".to_string(), "value123".to_string());
802
803 let mut cookies = HashMap::new();
804 cookies.insert("prefer".to_string(), "dark_mode".to_string());
805
806 let original = create_request_data(
807 "/api/items/789",
808 "DELETE",
809 json!({"reason": "archived"}),
810 json!({"sort": "desc"}),
811 RequestDataCollections {
812 raw_query_params,
813 headers,
814 cookies,
815 path_params,
816 },
817 );
818
819 let serialized = serde_json::to_string(&original).expect("serialization failed");
820 let deserialized: RequestData = serde_json::from_str(&serialized).expect("deserialization failed");
821
822 assert_eq!(deserialized.method, original.method);
823 assert_eq!(deserialized.path, original.path);
824 assert_eq!(deserialized.body, original.body);
825 assert_eq!(deserialized.path_params, original.path_params);
826 }
827
828 #[test]
829 fn test_request_data_large_json_body() {
830 let mut large_obj = serde_json::Map::new();
831 for i in 0..100 {
832 large_obj.insert(
833 format!("field_{}", i),
834 json!({"value": i, "name": format!("item_{}", i)}),
835 );
836 }
837 let body = json!(large_obj);
838
839 let data = create_request_data(
840 "/api/batch",
841 "POST",
842 body.clone(),
843 json!({}),
844 RequestDataCollections::default(),
845 );
846
847 assert!(data.body.is_object());
848 assert_eq!(data.body.as_object().unwrap().len(), 100);
849 }
850
851 #[test]
852 fn test_request_data_deeply_nested_json() {
853 let body = json!({
854 "level1": {
855 "level2": {
856 "level3": {
857 "level4": {
858 "level5": {
859 "value": "deep"
860 }
861 }
862 }
863 }
864 }
865 });
866
867 let data = create_request_data("/api/nested", "GET", body, json!({}), RequestDataCollections::default());
868
869 assert_eq!(
870 data.body["level1"]["level2"]["level3"]["level4"]["level5"]["value"],
871 "deep"
872 );
873 }
874
875 #[test]
876 fn test_request_data_unicode_in_fields() {
877 let mut path_params = HashMap::new();
878 path_params.insert("name".to_string(), "用户".to_string());
879
880 let mut cookies = HashMap::new();
881 cookies.insert("msg".to_string(), "こんにちは".to_string());
882
883 let body = json!({
884 "greeting": "مرحبا",
885 "emoji": "🚀"
886 });
887
888 let data = create_request_data(
889 "/api/users/用户",
890 "POST",
891 body,
892 json!({}),
893 RequestDataCollections {
894 cookies,
895 path_params,
896 ..Default::default()
897 },
898 );
899
900 assert_eq!(data.path_params.get("name"), Some(&"用户".to_string()));
901 assert_eq!(data.cookies.get("msg"), Some(&"こんにちは".to_string()));
902 assert_eq!(data.body["emoji"], "🚀");
903 }
904
905 #[test]
906 fn test_request_data_multiple_headers_with_same_prefix() {
907 let mut headers = HashMap::new();
908 headers.insert("x-custom-1".to_string(), "value1".to_string());
909 headers.insert("x-custom-2".to_string(), "value2".to_string());
910 headers.insert("x-custom-3".to_string(), "value3".to_string());
911
912 let data = create_request_data(
913 "/api/test",
914 "GET",
915 json!(null),
916 json!({}),
917 RequestDataCollections {
918 headers,
919 ..Default::default()
920 },
921 );
922
923 assert_eq!(data.headers.get("x-custom-1"), Some(&"value1".to_string()));
924 assert_eq!(data.headers.get("x-custom-2"), Some(&"value2".to_string()));
925 assert_eq!(data.headers.get("x-custom-3"), Some(&"value3".to_string()));
926 assert_eq!(data.headers.len(), 3);
927 }
928
929 #[test]
930 fn test_request_data_numeric_values_in_json() {
931 let body = json!({
932 "int": 42,
933 "float": 3.2,
934 "negative": -100,
935 "zero": 0,
936 "large": 9223372036854775807i64
937 });
938
939 let data = create_request_data(
940 "/api/numbers",
941 "POST",
942 body,
943 json!({}),
944 RequestDataCollections::default(),
945 );
946
947 assert_eq!(data.body["int"], 42);
948 assert_eq!(data.body["float"], 3.2);
949 assert_eq!(data.body["negative"], -100);
950 assert_eq!(data.body["zero"], 0);
951 }
952
953 #[test]
954 fn test_request_data_boolean_values_in_json() {
955 let body = json!({
956 "is_active": true,
957 "is_admin": false
958 });
959
960 let data = create_request_data("/api/config", "GET", body, json!({}), RequestDataCollections::default());
961
962 assert_eq!(data.body["is_active"], true);
963 assert_eq!(data.body["is_admin"], false);
964 }
965
966 #[test]
967 fn test_request_data_missing_optional_raw_body() {
968 let data = create_request_data(
969 "/api/test",
970 "GET",
971 json!(null),
972 json!({}),
973 RequestDataCollections::default(),
974 );
975
976 assert!(data.raw_body.is_none());
977 }
978
979 #[test]
980 fn test_request_data_path_with_query_string_format() {
981 let data = create_request_data(
982 "/api/search?q=test&limit=10",
983 "GET",
984 json!(null),
985 json!({"q": "test", "limit": "10"}),
986 RequestDataCollections::default(),
987 );
988
989 assert_eq!(data.path, "/api/search?q=test&limit=10");
990 }
991
992 #[test]
993 fn test_request_data_root_path() {
994 let data = create_request_data("/", "GET", json!(null), json!({}), RequestDataCollections::default());
995
996 assert_eq!(data.path, "/");
997 }
998
999 #[test]
1000 fn test_request_data_empty_string_values() {
1001 let mut headers = HashMap::new();
1002 headers.insert("empty-header".to_string(), "".to_string());
1003
1004 let mut path_params = HashMap::new();
1005 path_params.insert("id".to_string(), "".to_string());
1006
1007 let data = create_request_data(
1008 "/api/test",
1009 "GET",
1010 json!(null),
1011 json!({}),
1012 RequestDataCollections {
1013 headers,
1014 path_params,
1015 ..Default::default()
1016 },
1017 );
1018
1019 assert_eq!(data.headers.get("empty-header"), Some(&"".to_string()));
1020 assert_eq!(data.path_params.get("id"), Some(&"".to_string()));
1021 }
1022
1023 #[test]
1024 fn test_request_data_deserialization_missing_field() {
1025 let json_str = r#"{
1026 "path_params": {"user_id": "123"},
1027 "query_params": {"page": "1"},
1028 "raw_query_params": {"page": ["1"]},
1029 "body": {"name": "test"},
1030 "raw_body": null,
1031 "headers": {"content-type": "application/json"},
1032 "cookies": {"session": "abc"}
1033 }"#;
1034
1035 let result: Result<RequestData, _> = serde_json::from_str(json_str);
1036 assert!(result.is_err());
1037 }
1038
1039 #[test]
1040 fn test_request_data_deserialization_extra_fields_rejected() {
1041 let json_str = r#"{
1042 "path_params": {"user_id": "123"},
1043 "query_params": {"page": "1"},
1044 "raw_query_params": {"page": ["1"]},
1045 "body": {"name": "test"},
1046 "raw_body": null,
1047 "headers": {"content-type": "application/json"},
1048 "cookies": {"session": "abc"},
1049 "method": "GET",
1050 "path": "/api/test",
1051 "extra_field": "not allowed"
1052 }"#;
1053
1054 let result: Result<RequestData, _> = serde_json::from_str(json_str);
1055 assert!(result.is_err());
1056 }
1057
1058 #[test]
1059 fn test_request_data_multiple_raw_body_values() {
1060 let mut raw_query_params = HashMap::new();
1061 raw_query_params.insert(
1062 "data".to_string(),
1063 vec!["val1".to_string(), "val2".to_string(), "val3".to_string()],
1064 );
1065
1066 let data = create_request_data(
1067 "/api/test",
1068 "POST",
1069 json!(null),
1070 json!({}),
1071 RequestDataCollections {
1072 raw_query_params,
1073 ..Default::default()
1074 },
1075 );
1076
1077 let values = data.raw_query_params.get("data").unwrap();
1078 assert_eq!(values.len(), 3);
1079 assert_eq!(values[0], "val1");
1080 assert_eq!(values[1], "val2");
1081 assert_eq!(values[2], "val3");
1082 }
1083
1084 #[test]
1085 fn test_request_data_debug_output() {
1086 let data = create_request_data(
1087 "/api/test",
1088 "GET",
1089 json!({"key": "value"}),
1090 json!({}),
1091 RequestDataCollections::default(),
1092 );
1093
1094 let debug_str = format!("{:?}", data);
1095 assert!(debug_str.contains("RequestData"));
1096 assert!(debug_str.contains("/api/test"));
1097 }
1098
1099 #[test]
1100 fn test_request_data_clone_independence() {
1101 let mut path_params1 = HashMap::new();
1102 path_params1.insert("id".to_string(), "original".to_string());
1103
1104 let data1 = create_request_data(
1105 "/api/users/1",
1106 "GET",
1107 json!({"name": "original"}),
1108 json!({}),
1109 RequestDataCollections {
1110 path_params: path_params1,
1111 ..Default::default()
1112 },
1113 );
1114
1115 let data2 = data1.clone();
1116
1117 assert_eq!(data1.path_params.get("id"), data2.path_params.get("id"));
1118 assert_eq!(data1.body["name"], data2.body["name"]);
1119 }
1120
1121 #[test]
1122 fn deserialize_errors_on_missing_required_field() {
1123 let value = json!({
1124 "path_params": {},
1125 "query_params": {},
1126 "raw_query_params": {},
1127 "body": null,
1128 "raw_body": null,
1129 "headers": {},
1130 "cookies": {},
1131 "method": "GET"
1132 });
1133
1134 let err = serde_json::from_value::<RequestData>(value).unwrap_err();
1135 assert!(err.to_string().contains("missing field"));
1136 }
1137
1138 #[test]
1139 fn deserialize_errors_on_invalid_raw_body_type() {
1140 let value = json!({
1141 "path_params": {},
1142 "query_params": {},
1143 "raw_query_params": {},
1144 "body": null,
1145 "raw_body": "not-bytes",
1146 "headers": {},
1147 "cookies": {},
1148 "method": "GET",
1149 "path": "/"
1150 });
1151
1152 assert!(serde_json::from_value::<RequestData>(value).is_err());
1153 }
1154}