chuchi_core/request/
builder.rs1use super::Request;
2use crate::body::Body;
3use crate::header::{
4 values::IntoHeaderName, ContentType, HeaderValue, HeaderValues, Method,
5 RequestHeader, Uri, CONTENT_LENGTH, CONTENT_TYPE,
6};
7
8use std::fmt;
9use std::net::SocketAddr;
10
11#[derive(Debug)]
15pub struct RequestBuilder {
16 header: RequestHeader,
17 body: Body,
18}
19
20impl RequestBuilder {
21 pub fn new(uri: Uri) -> Self {
23 Self {
24 header: RequestHeader {
25 address: ([127, 0, 0, 1], 0).into(),
26 method: Method::GET,
27 uri,
28 values: HeaderValues::new(),
29 },
30 body: Body::new(),
31 }
32 }
33
34 pub fn address(mut self, addr: impl Into<SocketAddr>) -> Self {
36 self.header.address = addr.into();
37 self
38 }
39
40 pub fn method(mut self, method: Method) -> Self {
42 self.header.method = method;
43 self
44 }
45
46 pub fn content_type(self, content_type: impl Into<ContentType>) -> Self {
48 self.header(CONTENT_TYPE, content_type.into())
49 }
50
51 pub fn header<K, V>(mut self, key: K, val: V) -> Self
60 where
61 K: IntoHeaderName,
62 V: TryInto<HeaderValue>,
63 V::Error: fmt::Debug,
64 {
65 self.values_mut().insert(key, val);
66 self
67 }
68
69 pub fn values_mut(&mut self) -> &mut HeaderValues {
71 &mut self.header.values
72 }
73
74 pub fn body(mut self, body: impl Into<Body>) -> Self {
76 self.body = body.into();
77 self
78 }
79
80 #[cfg(feature = "json")]
82 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
83 pub fn serialize<S>(self, value: &S) -> Result<Self, super::SerializeError>
84 where
85 S: serde::Serialize + ?Sized,
86 {
87 Ok(self
88 .body(Body::serialize(value).map_err(super::SerializeError::Json)?))
89 }
90
91 #[cfg(feature = "query")]
96 #[cfg_attr(docsrs, doc(cfg(feature = "query")))]
97 pub fn serialize_query<S>(
98 mut self,
99 value: &S,
100 ) -> Result<Self, super::SerializeError>
101 where
102 S: serde::Serialize + ?Sized,
103 {
104 let mut parts = self.header.uri.into_parts();
105
106 let query = serde_urlencoded::to_string(value)
107 .map_err(super::SerializeError::UrlEncoded)?;
108
109 parts.path_and_query = Some(
110 format!(
111 "{}?{}",
112 parts
113 .path_and_query
114 .as_ref()
115 .map(|p| p.path())
116 .unwrap_or("/"),
117 query
118 )
119 .parse()
120 .expect("serde_urlencoded should always return a valid query"),
121 );
122
123 self.header.uri = Uri::from_parts(parts).unwrap();
124
125 Ok(self)
126 }
127
128 pub fn build(mut self) -> Request {
131 if let Some(len) = self.body.len() {
134 self.values_mut().insert(CONTENT_LENGTH, len);
135 }
136
137 Request::new(self.header, self.body)
138 }
139}