tower_http_client/client/
request_ext.rs1use private::Sealed;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
8#[error(transparent)]
9pub enum SetBodyError<S> {
10 Body(http::Error),
12 Encode(S),
14}
15
16pub trait RequestBuilderExt: Sized + Sealed {
18 #[cfg(feature = "json")]
27 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
28 fn json<T: serde::Serialize + ?Sized>(
29 self,
30 value: &T,
31 ) -> Result<http::Request<bytes::Bytes>, SetBodyError<serde_json::Error>>;
32
33 #[cfg(feature = "form")]
42 #[cfg_attr(docsrs, doc(cfg(feature = "form")))]
43 fn form<T: serde::Serialize + ?Sized>(
44 self,
45 form: &T,
46 ) -> Result<http::Request<String>, SetBodyError<serde_urlencoded::ser::Error>>;
47
48 #[must_use]
54 #[cfg(feature = "typed-header")]
55 #[cfg_attr(docsrs, doc(cfg(feature = "typed_header")))]
56 fn typed_header<T>(self, header: T) -> Self
57 where
58 T: headers::Header;
59}
60
61impl RequestBuilderExt for http::request::Builder {
62 #[cfg(feature = "json")]
63 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
64 fn json<T: serde::Serialize + ?Sized>(
65 mut self,
66 value: &T,
67 ) -> Result<http::Request<bytes::Bytes>, SetBodyError<serde_json::Error>> {
68 use http::{HeaderValue, header::CONTENT_TYPE};
69
70 if let Some(headers) = self.headers_mut() {
71 headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
72 }
73
74 let bytes = bytes::Bytes::from(serde_json::to_vec(value).map_err(SetBodyError::Encode)?);
75 self.body(bytes).map_err(SetBodyError::Body)
76 }
77
78 #[cfg(feature = "form")]
79 #[cfg_attr(docsrs, doc(cfg(feature = "form")))]
80 fn form<T: serde::Serialize + ?Sized>(
81 mut self,
82 form: &T,
83 ) -> Result<http::Request<String>, SetBodyError<serde_urlencoded::ser::Error>> {
84 use http::{HeaderValue, header::CONTENT_TYPE};
85
86 let string = serde_urlencoded::to_string(form).map_err(SetBodyError::Encode)?;
87 if let Some(headers) = self.headers_mut() {
88 headers.insert(
89 CONTENT_TYPE,
90 HeaderValue::from_static("application/x-www-form-urlencoded"),
91 );
92 }
93 self.body(string).map_err(SetBodyError::Body)
94 }
95
96 #[cfg(feature = "typed-header")]
97 #[cfg_attr(docsrs, doc(cfg(feature = "typed_header")))]
98 fn typed_header<T>(mut self, header: T) -> Self
99 where
100 T: headers::Header,
101 {
102 use headers::HeaderMapExt;
103
104 if let Some(headers) = self.headers_mut() {
105 headers.typed_insert(header);
106 }
107 self
108 }
109}
110
111mod private {
112 pub trait Sealed {}
113
114 impl Sealed for http::request::Builder {}
115}