reqwest_builder/
serialization.rs1use crate::errors::ReqwestBuilderError;
2use http::HeaderMap;
3use serde::Serialize;
4use std::collections::HashMap;
5
6pub fn serialize_to_form_params<T: Serialize>(
8 data: &T,
9) -> std::result::Result<HashMap<String, String>, ReqwestBuilderError> {
10 let value = serde_json::to_value(data)?;
11
12 let obj = value.as_object().ok_or_else(|| {
13 ReqwestBuilderError::SerializationError("Data must serialize to a JSON object".to_string())
14 })?;
15
16 let mut params = HashMap::new();
17 for (key, val) in obj {
18 let value_str = match val {
19 serde_json::Value::String(s) => s.clone(),
20 serde_json::Value::Number(n) => n.to_string(),
21 serde_json::Value::Bool(b) => b.to_string(),
22 serde_json::Value::Null => continue, _ => val.to_string(), };
25 params.insert(key.clone(), value_str);
26 }
27
28 Ok(params)
29}
30
31pub fn serialize_to_header_map<T: Serialize>(
33 headers: &T,
34) -> std::result::Result<HeaderMap, ReqwestBuilderError> {
35 let mut header_map = HeaderMap::new();
36 let value = serde_json::to_value(headers)?;
37
38 let obj = value.as_object().ok_or_else(|| {
39 ReqwestBuilderError::SerializationError(
40 "Headers must serialize to a JSON object".to_string(),
41 )
42 })?;
43
44 for (key, val) in obj {
45 if let Some(val_str) = val.as_str() {
46 let header_name = http::HeaderName::from_bytes(key.as_bytes()).map_err(|e| {
47 ReqwestBuilderError::HeaderError {
48 key: key.clone(),
49 value: val_str.to_string(),
50 source: format!("Invalid header name: {}", e),
51 }
52 })?;
53
54 let header_value = http::HeaderValue::from_str(val_str).map_err(|e| {
55 ReqwestBuilderError::HeaderError {
56 key: key.clone(),
57 value: val_str.to_string(),
58 source: format!("Invalid header value: {}", e),
59 }
60 })?;
61
62 header_map.insert(header_name, header_value);
63 } else {
64 return Err(ReqwestBuilderError::HeaderError {
65 key: key.clone(),
66 value: val.to_string(),
67 source: "Header value must be a string".to_string(),
68 });
69 }
70 }
71
72 Ok(header_map)
73}
74
75pub fn construct_url(base_url: &url::Url, endpoint: &str) -> String {
77 let base_str = base_url.as_str().trim_end_matches('/');
78 let endpoint_str = endpoint.trim_start_matches('/');
79
80 if endpoint_str.is_empty() {
81 return base_str.to_string();
82 }
83
84 format!("{base_str}/{endpoint_str}")
85}