pub struct JsonRequestBuilder<'a, T> { /* private fields */ }Expand description
A request builder that will send a JSON-serialised body.
Obtained from RequestBuilder::json. Finalise with send
(async) or send_sync (sync).
§Example
// Async PUT
let updated: Item = client
.put("/items/42")
.json(UpdateItem { name: "new name".to_string() })
.send()
.await?;
// Sync PATCH
let patched: Item = client
.patch("/items/42")
.json(UpdateItem { name: "new name".to_string() })
.send_sync()?;Implementations§
Source§impl<'a, T: Serialize> JsonRequestBuilder<'a, T>
impl<'a, T: Serialize> JsonRequestBuilder<'a, T>
Sourcepub async fn send<R: DeserializeOwned>(self) -> Result<R, Error>
pub async fn send<R: DeserializeOwned>(self) -> Result<R, Error>
Sends the request asynchronously with the JSON body and deserialises the response as R.
§Example
let ack: Ack = client
.post("/process")
.json(Payload { value: 42 })
.send()
.await?;Examples found in repository?
examples/socket_client_server.rs (line 154)
62async fn main() -> Result<(), Box<dyn std::error::Error>> {
63 // ── Build routes ──────────────────────────────────────────────────────────
64 let store: Arc<Mutex<Vec<Item>>> = Arc::new(Mutex::new(vec![]));
65
66 let mut server = Server::default();
67
68 // Plain GET — no body, no state.
69 server.mechanism(
70 ServerMechanism::get("/health")
71 .onconnect(|| async { reply!(json => Health { ok: true }) })
72 );
73
74 // POST with a JSON body — echoes back the created item.
75 server.mechanism(
76 ServerMechanism::post("/items")
77 .json::<NewItem>()
78 .onconnect(|body: NewItem| async move {
79 reply!(json => Item { id: 1, name: body.name }, status => Status::Created)
80 })
81 );
82
83 // GET with query parameters — filters the stored items by prefix.
84 server.mechanism({
85 let store = store.clone();
86 ServerMechanism::get("/items/search")
87 .state(store)
88 .query::<Filter>()
89 .onconnect(|state: Arc<Mutex<Vec<Item>>>, f: Filter| async move {
90 let items = state.lock().unwrap();
91 let matches: Vec<Item> = items
92 .iter()
93 .filter(|i| i.name.starts_with(&f.prefix))
94 .cloned()
95 .collect();
96 reply!(json => SearchResult { matches })
97 })
98 });
99
100 // POST with shared state — stores the item and returns it.
101 server.mechanism({
102 let store = store.clone();
103 ServerMechanism::post("/items/store")
104 .state(store)
105 .json::<NewItem>()
106 .onconnect(|state: Arc<Mutex<Vec<Item>>>, body: NewItem| async move {
107 let mut s = state.lock().unwrap();
108 let id = s.len() as u32 + 1;
109 let item = Item { id, name: body.name };
110 s.push(item.clone());
111 reply!(json => item, status => Status::Created)
112 })
113 });
114
115 // POST with authenticated-encrypted body (ChaCha20-Poly1305 via SerializationKey).
116 // The body is decrypted before the handler is called; a wrong key returns 403.
117 server.mechanism(
118 ServerMechanism::post("/items/secure")
119 .encryption::<NewItem>(SerializationKey::Default)
120 .onconnect(|body: NewItem| async move {
121 let item = Item { id: 99, name: body.name };
122 // The response must also be sealed so the client can open it.
123 reply!(sealed => item, key => SerializationKey::Default)
124 })
125 );
126
127 // ── Serve with graceful shutdown ──────────────────────────────────────────
128 let (tx, rx) = tokio::sync::oneshot::channel::<()>();
129 let server_handle = tokio::spawn(async move {
130 server.serve_with_graceful_shutdown(
131 ([127, 0, 0, 1], PORT),
132 async { rx.await.ok(); },
133 ).await;
134 });
135
136 // Give the server time to bind before firing requests.
137 tokio::time::sleep(Duration::from_millis(200)).await;
138 println!("Server started on port {PORT}");
139
140 // ── Client requests ───────────────────────────────────────────────────────
141 let client = ClientBuilder::new(Target::Localhost(PORT))
142 .timeout(Duration::from_secs(5))
143 .build_async();
144
145 // GET /health
146 let health: Health = client.get("/health").send().await?;
147 assert!(health.ok);
148 println!("GET /health → ok={}", health.ok);
149
150 // POST /items (JSON body)
151 let created: Item = client
152 .post("/items")
153 .json(NewItem { name: "widget".into() })
154 .send()
155 .await?;
156 assert_eq!(created.name, "widget");
157 println!("POST /items → {:?}", created);
158
159 // POST /items/store (shared state — populates the store)
160 let stored: Item = client
161 .post("/items/store")
162 .json(NewItem { name: "gadget".into() })
163 .send()
164 .await?;
165 println!("POST /items/store → {:?}", stored);
166
167 let stored2: Item = client
168 .post("/items/store")
169 .json(NewItem { name: "gizmo".into() })
170 .send()
171 .await?;
172 println!("POST /items/store → {:?}", stored2);
173
174 // GET /items/search?prefix=ga (query params)
175 let result: SearchResult = client
176 .get("/items/search")
177 .query(Filter { prefix: "ga".into() })
178 .send()
179 .await?;
180 assert!(result.matches.iter().all(|i| i.name.starts_with("ga")));
181 println!("GET /items/search?prefix=ga → {} match(es): {:?}", result.matches.len(), result.matches);
182
183 // POST /items/secure (authenticated-encrypted body)
184 let secure_item = client
185 .post("/items/secure")
186 .encryption(NewItem { name: "secret".into() }, SerializationKey::Default)
187 .send::<Item>()
188 .await?;
189 assert_eq!(secure_item.name, "secret");
190 println!("POST /items/secure → {:?}", secure_item);
191
192 // ── Shutdown ──────────────────────────────────────────────────────────────
193 tx.send(()).ok();
194 server_handle.await?;
195 println!("\nAll requests successful ✓");
196 Ok(())
197}Auto Trait Implementations§
impl<'a, T> Freeze for JsonRequestBuilder<'a, T>where
T: Freeze,
impl<'a, T> !RefUnwindSafe for JsonRequestBuilder<'a, T>
impl<'a, T> Send for JsonRequestBuilder<'a, T>where
T: Send,
impl<'a, T> Sync for JsonRequestBuilder<'a, T>where
T: Sync,
impl<'a, T> Unpin for JsonRequestBuilder<'a, T>where
T: Unpin,
impl<'a, T> UnsafeUnpin for JsonRequestBuilder<'a, T>where
T: UnsafeUnpin,
impl<'a, T> !UnwindSafe for JsonRequestBuilder<'a, T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more