1use crate::prelude::*;
4
5#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
6use serde::Deserialize;
7
8#[cfg(feature = "reqwest")]
9use serde::Serialize;
10
11#[cfg(feature = "salvo")]
12#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
13use salvo::Request;
14
15#[cfg(feature = "reqwest")]
16use reqwest::RequestBuilder;
17
18#[cfg(feature = "salvo")]
19#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
20#[salvo::async_trait]
21pub trait MsgPackParser {
22 async fn parse_msgpack<'de, T: Deserialize<'de>>(&'de mut self) -> MResult<T>;
23 async fn parse_msgpack_with_max_size<'de, T: Deserialize<'de>>(&'de mut self, max_size: usize) -> MResult<T>;
24}
25
26#[cfg(feature = "salvo")]
27#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
28#[salvo::async_trait]
29impl MsgPackParser for Request {
30 #[inline]
32 async fn parse_msgpack<'de, T: Deserialize<'de>>(&'de mut self) -> MResult<T> {
33 self.parse_msgpack_with_max_size(salvo::http::request::secure_max_size()).await
34 }
35
36 #[inline]
38 async fn parse_msgpack_with_max_size<'de, T: Deserialize<'de>>(&'de mut self, max_size: usize) -> MResult<T> {
39 let ctype = self.content_type();
40 if let Some(ctype) = ctype {
41 if ctype.subtype() == salvo::http::mime::MSGPACK {
42 let payload = self.payload_with_max_size(max_size).await?;
43 let payload = if payload.is_empty() {
44 "null".as_bytes()
45 } else {
46 payload.as_ref()
47 };
48 log::debug!("{:?}", payload);
49 return rmp_serde::from_slice::<T>(payload).consider(Some(StatusCode::BAD_REQUEST), None, true)
50 }
51 }
52 Err(
53 ErrorResponse {
54 status_code: Some(StatusCode::BAD_REQUEST),
55 error_text: "Bad content type, must be `application/msgpack`.".into(),
56 original_text: None,
57 public_error: true
58 }
59 )
60 }
61}
62
63#[cfg(feature = "reqwest")]
64#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
65pub trait MsgPackBuilder {
66 fn msgpack<T: Serialize + ?Sized>(self, msgpack: &T) -> MResult<RequestBuilder>;
67}
68
69#[cfg(feature = "reqwest")]
70#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
71impl MsgPackBuilder for RequestBuilder {
72 fn msgpack<T: Serialize + ?Sized>(self, msgpack: &T) -> MResult<RequestBuilder> {
73 let (cli, mut req) = self.build_split();
74 let mut error = None;
75 if let Ok(req) = req.as_mut() {
76 match rmp_serde::to_vec(msgpack) {
77 Ok(body) => {
78 if !req.headers().contains_key(reqwest::header::CONTENT_TYPE) {
79 req.headers_mut().insert(reqwest::header::CONTENT_TYPE, reqwest::header::HeaderValue::from_static("application/msgpack"));
80 }
81 *req.body_mut() = Some(body.into());
82 },
83 Err(err) => { error = Some(err); },
84 }
85 }
86 if let Some(err) = error {
87 Err(err.to_string().into())
88 } else {
89 Ok(RequestBuilder::from_parts(cli, req?))
90 }
91 }
92}
93
94#[cfg(feature = "reqwest")]
95#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
96pub trait MsgPackBuilder {
97 fn msgpack<T: Serialize + ?Sized>(self, msgpack: &T) -> CResult<reqwest::Request>;
98}
99
100#[cfg(feature = "reqwest")]
101#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
102impl MsgPackBuilder for RequestBuilder {
103 fn msgpack<T: Serialize + ?Sized>(self, msgpack: &T) -> CResult<reqwest::Request> {
104 let mut req = self.build();
105 let mut error = None;
106 if let Ok(req) = req.as_mut() {
107 match rmp_serde::to_vec(msgpack) {
108 Ok(body) => {
109 if !req.headers().contains_key(reqwest::header::CONTENT_TYPE) {
110 req.headers_mut().insert(reqwest::header::CONTENT_TYPE, reqwest::header::HeaderValue::from_static("application/msgpack"));
111 }
112 *req.body_mut() = Some(body.into());
113 },
114 Err(err) => { error = Some(err); },
115 }
116 }
117 if let Some(err) = error {
118 Err(err.to_string().into())
119 } else {
120 Ok(req?)
121 }
122 }
123}