deboa_macros/lib.rs
1//! # Deboa Macros
2//!
3//! This crate provides procedural macros for the `deboa` HTTP client to simplify
4//! common HTTP request patterns with a more concise syntax.
5//!
6//! ## Features
7//!
8//! - **Request Macros**: Shortcut macros for common HTTP methods (GET, POST, PUT, PATCH, DELETE)
9//! - **Type Safety**: Compile-time type checking for request/response bodies
10//! - **Async Support**: Seamless integration with async/await syntax
11//! - **Multiple Serialization Formats**: Support for JSON, XML, and MessagePack out of the box
12//!
13//! ## Available Macros
14//!
15//! - `get!`: Make a GET request
16//! - `post!`: Make a POST request with a body
17//! - `put!`: Make a PUT request with a body
18//! - `patch!`: Make a PATCH request with a body
19//! - `delete!`: Make a DELETE request
20//! - `fetch!`: Generic request macro that takes a method parameter
21//!
22//! ## Examples
23//!
24//! ### Basic GET Request
25//! ```compile_fail
26//! use deboa::Deboa;
27//! use deboa_extras::http::serde::json::JsonBody;
28//!
29//! #[derive(serde::Deserialize)]
30//! struct Post {
31//! id: u32,
32//! title: String,
33//! body: String,
34//! userId: u32,
35//! }
36//!
37//! #[tokio::main]
38//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
39//! let mut client = Deboa::new();
40//! let post: Post = get!("https://jsonplaceholder.typicode.com/posts/1", &mut client, JsonBody, Post);
41//! println!("Post title: {}", post.title);
42//! Ok(())
43//! }
44//! ```
45//!
46//! ### POST with JSON Body
47//! ```compile_fail
48//! use deboa::Deboa;
49//! use deboa_extras::http::serde::json::JsonBody;
50//! use serde::Serialize;
51//!
52//! #[derive(Serialize)]
53//! struct NewPost {
54//! title: String,
55//! body: String,
56//! userId: u32,
57//! }
58//!
59//! #[tokio::main]
60//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
61//! let mut client = Deboa::new();
62//! let new_post = NewPost {
63//! title: "Hello World".into(),
64//! body: "This is a test post".into(),
65//! userId: 1,
66//! };
67//! let response = post!(
68//! new_post,
69//! JsonBody,
70//! "https://jsonplaceholder.typicode.com/posts",
71//! &mut client
72//! );
73//! println!(200, response.status());
74//! Ok(())
75//! }
76//! ```
77
78#[macro_export]
79/// Make a GET request to the specified URL.
80///
81/// The `get!` macro is used to make a GET request to the specified URL.
82/// Its first argument is a string literal or a variable. Arrows are
83/// used to specify the body serialization type and the output type.
84///
85/// You can use the `JsonBody`, `XmlBody`, `MsgPack` type for JSON, XML
86/// and MessagePack serialization.
87///
88/// To help understand the macro arguments, here is an example:
89///
90/// get!(url, &mut client, JsonBody, ty)
91///
92/// # Arguments
93///
94/// * `url` - The URL to make the GET request to.
95/// * `client` - The client variable to use for the request.
96/// * `res_body_ty` - The body type of the response.
97/// * `res_ty` - The type of the response.
98///
99/// Please note url can be a string literal or a variable.
100///
101/// # Example
102///
103/// ```compile_fail
104/// let mut client = Deboa::new();
105/// let response = get!("https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Vec<Post>);
106/// assert_eq!(response.len(), 100);
107/// ```
108macro_rules! get {
109 ($url:literal, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
110 $client
111 .execute($url)
112 .await?
113 .body_as::<$res_body_ty, $res_ty>($res_body_ty)
114 .await?
115 };
116
117 ($url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
118 $client
119 .execute($url)
120 .await?
121 .body_as::<$res_body_ty, $res_ty>($res_body_ty)
122 .await?
123 };
124
125 ($url:expr, &mut $client:ident) => {
126 $client
127 .execute($url)
128 .await?
129 .text()
130 };
131}
132
133#[macro_export]
134/// Make a POST request to the specified URL.
135///
136/// The `post!` macro is used to make a POST request to the specified URL.
137///
138/// To help understand the macro arguments, here is an example:
139///
140/// post!(input, req_body_ty, url, &mut client, res_body_ty, res_ty)
141///
142/// # Arguments
143///
144/// * `input` - The input to send with the request.
145/// * `req_body_ty` - The body serialization type of the request.
146/// * `url` - The URL to make the POST request to.
147/// * `client` - The client variable to use for the request.
148/// * `res_body_ty` - The body type of the response.
149/// * `res_ty` - The type of the response.
150///
151/// Please note url can be a string literal or a variable.
152///
153/// # Example
154///
155/// ## Without response body deserialization
156///
157/// ```compile_fail
158/// let mut client = Deboa::new();
159/// let response = post!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts", &mut client);
160/// assert_eq!(response.id, 1);
161/// ```
162///
163/// ## With response body deserialization
164///
165/// ```compile_fail
166/// let mut client = Deboa::new();
167/// let response = post!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Post);
168/// assert_eq!(response.id, 1);
169/// ```
170macro_rules! post {
171 ($input:ident, $url:literal, &mut $client:ident) => {
172 $client
173 .execute(
174 deboa::request::DeboaRequest::post($url)?
175 .body_as(deboa_extras::http::serde::json::JsonBody, $input)?
176 .build()?,
177 )
178 .await?
179 };
180
181 ($input:ident, $url:expr, &mut $client:ident) => {
182 $client
183 .execute(
184 deboa::request::DeboaRequest::post($url)?
185 .body_as(deboa_extras::http::serde::json::JsonBody, $input)?
186 .build()?,
187 )
188 .await?
189 };
190
191 ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
192 $client
193 .execute(
194 deboa::request::DeboaRequest::post($url)?
195 .body_as($req_body_ty, $input)?
196 .build()?,
197 )
198 .await?
199 };
200
201 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
202 $client
203 .execute(
204 deboa::request::DeboaRequest::post($url)?
205 .body_as($req_body_ty, $input)?
206 .build()?,
207 )
208 .await?
209 };
210
211 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
212 $client
213 .execute(
214 deboa::request::DeboaRequest::post($url)?
215 .body_as($req_body_ty, $input)?
216 .build()?,
217 )
218 .await?
219 .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
220 };
221}
222
223#[macro_export]
224/// Make a PUT request to the specified URL.
225///
226/// The `put!` macro is used to make a PUT request to the specified URL
227/// Its first argument is a string literal or a variable.
228///
229/// To help understand the macro arguments, here is an example:
230///
231/// put!(input, req_body_ty, url, &mut client)
232///
233/// # Arguments
234///
235/// * `input` - The input to send with the request.
236/// * `req_body_ty` - The body serialization type of the request.
237/// * `url` - The URL to make the PUT request to.
238/// * `client` - The client variable to use for the request.
239///
240/// Please note url can be a string literal or a variable.
241///
242/// # Example
243///
244/// ```compile_fail
245/// let mut client = Deboa::new();
246/// let response = put!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts/1", &mut client);
247/// assert_eq!(response.id, 1);
248/// ```
249macro_rules! put {
250 ($input:ident, $url:literal, &mut $client:ident) => {
251 $client
252 .execute(
253 deboa::request::DeboaRequest::put($url)?
254 .body_as(deboa_extras::http::serde::json::JsonBody, $input)?
255 .build()?,
256 )
257 .await?
258 };
259
260 ($input:ident, $url:expr, &mut $client:ident) => {
261 $client
262 .execute(
263 deboa::request::DeboaRequest::put($url)?
264 .body_as(deboa_extras::http::serde::json::JsonBody, $input)?
265 .build()?,
266 )
267 .await?
268 };
269
270 ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
271 $client
272 .execute(
273 deboa::request::DeboaRequest::put($url)?
274 .body_as($req_body_ty, $input)?
275 .build()?,
276 )
277 .await?
278 };
279
280 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
281 $client
282 .execute(
283 deboa::request::DeboaRequest::put($url)?
284 .body_as($req_body_ty, $input)?
285 .build()?,
286 )
287 .await?
288 };
289
290 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
291 $client
292 .execute(
293 deboa::request::DeboaRequest::put($url)?
294 .body_as($req_body_ty, $input)?
295 .build()?,
296 )
297 .await?
298 .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
299 };
300}
301
302#[macro_export]
303/// Make a PATCH request to the specified URL.
304///
305/// The `patch!` macro is used to make a PATCH request to the specified URL
306/// Its first argument is a string literal or a variable.
307///
308/// To help understand the macro arguments, here is an example:
309///
310/// patch!(input, req_body_ty, url, &mut client)
311///
312/// # Arguments
313///
314/// * `input` - The input to send with the request.
315/// * `req_body_ty` - The body serialization type of the request.
316/// * `url` - The URL to make the PATCH request to.
317/// * `client` - The client variable to use for the request.
318///
319/// Please note url can be a string literal or a variable.
320///
321/// # Example
322///
323/// ```compile_fail
324/// let mut client = Deboa::new();
325/// let response = patch!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts/1", &mut client);
326/// assert_eq!(response.id, 1);
327/// ```
328macro_rules! patch {
329 ($input:ident, $url:literal, &mut $client:ident) => {
330 $client
331 .execute(
332 deboa::request::DeboaRequest::patch($url)?
333 .body_as(deboa_extras::http::serde::json::JsonBody, $input)?
334 .build()?,
335 )
336 .await?
337 };
338
339 ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
340 $client
341 .execute(
342 deboa::request::DeboaRequest::patch($url)?
343 .body_as($req_body_ty, $input)?
344 .build()?,
345 )
346 .await?
347 };
348
349 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
350 $client
351 .execute(
352 deboa::request::DeboaRequest::patch($url)?
353 .body_as($req_body_ty, $input)?
354 .build()?,
355 )
356 .await?
357 };
358
359 ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
360 $client
361 .execute(
362 deboa::request::DeboaRequest::patch($url)?
363 .body_as($req_body_ty, $input)?
364 .build()?,
365 )
366 .await?
367 .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
368 };
369}
370
371#[macro_export]
372/// Make a DELETE request to the specified URL.
373///
374/// The `delete!` macro is used to make a DELETE request to the specified URL
375/// Its first argument is a string literal or a variable.
376///
377/// To help understand the macro arguments, here is an example:
378///
379/// delete!(url, &mut client)
380///
381/// # Arguments
382///
383/// * `url` - The URL to make the DELETE request to.
384/// * `client` - The client variable to use for the request.
385///
386/// Please note url can be a string literal or a variable.
387///
388/// # Example
389///
390/// ```compile_fail
391/// let mut client = Deboa::new();
392/// let response = delete!("https://jsonplaceholder.typicode.com/posts/1", &mut client);
393/// assert_eq!(response.id, 1);
394/// ```
395macro_rules! delete {
396 ($url:literal, &mut $client:ident) => {
397 $client
398 .execute(deboa::request::DeboaRequest::delete($url)?.build()?)
399 .await?
400 };
401
402 ($url:expr, &mut $client:ident) => {
403 $client
404 .execute(deboa::request::DeboaRequest::delete($url)?.build()?)
405 .await?
406 };
407}
408
409#[macro_export]
410/// Make a GET request to the specified URL.
411///
412/// The `fetch!` macro is a more generic version of the `get!` macro.
413/// Its first argument is a string literal or a variable. Arrows are
414/// used to specify the body serialization type and the output type.
415///
416/// You can use the `JsonBody`, `XmlBody`, `MsgPack` type for JSON, XML
417/// and MessagePack serialization.
418///
419/// To help understand the macro arguments, here is an example:
420///
421/// fetch!(url, &mut client, body, ty)
422///
423/// # Arguments
424///
425/// * `url` - The URL to make the GET request to.
426/// * `client` - The client variable to use for the request.
427/// * `res_body_ty` - The body type of the response.
428/// * `res_ty` - The type of the response.
429///
430/// Please note url can be a string literal or a variable.
431///
432/// # Example
433///
434/// ```compile_fail
435/// let mut client = Deboa::new();
436/// let response = fetch!("https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Post);
437/// assert_eq!(response.id, 1);
438/// ```
439macro_rules! fetch {
440 ($url:literal, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
441 $client
442 .execute($url)
443 .await?
444 .body_as::<$res_body_ty, $res_ty>($res_body_ty)
445 .await?
446 };
447
448 ($url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
449 $client
450 .execute($url)
451 .await?
452 .body_as::<$res_body_ty, $res_ty>($res_body_ty)
453 .await?
454 };
455
456 ($url:expr, &mut $client:ident) => {
457 $client
458 .execute($url)
459 .await?
460 };
461}
462#[macro_export]
463/// Submit a request to the specified URL.
464///
465/// The `submit!` macro is a more generic version of the `get!` macro.
466/// Its first argument is a string literal or a variable. Arrows are
467/// used to specify the body serialization type and the output type.
468///
469/// You can use the `JsonBody`, `XmlBody`, `MsgPack` type for JSON, XML
470/// and MessagePack serialization.
471///
472/// To help understand the macro arguments, here is an example:
473///
474/// fetch!(url, &mut client, body, ty)
475///
476/// # Arguments
477///
478/// * `method` - The HTTP method to use.
479/// * `input` - The input to send with the request.
480/// * `url` - The URL to make the GET request to.
481/// * `client` - The client variable to use for the request.
482/// * `res_body_ty` - The body type of the response.
483/// * `res_ty` - The type of the response.
484///
485/// Please note url can be a string literal or a variable.
486///
487/// # Example
488///
489/// ```compile_fail
490/// let mut client = Deboa::new();
491/// let response = submit!("POST", "user=deboa", "https://jsonplaceholder.typicode.com/posts", &mut client);
492/// assert_eq!(response.id, 1);
493/// ```
494macro_rules! submit {
495 ($method:expr, $input:expr, $url:expr, &mut $client:ident) => {
496 $client
497 .execute(
498 deboa::request::DeboaRequest::at($url, $method)?
499 .text($input)
500 .build()?,
501 )
502 .await?
503 };
504}
505
506#[macro_export]
507/// Make a GET request to the specified URL, returning a stream.
508///
509/// The `stream!` macro is used to make a GET request to the specified URL
510/// Its first argument is a string literal or a variable.
511///
512/// To help understand the macro arguments, here is an example:
513///
514/// stream!(url, &mut client)
515///
516/// # Arguments
517///
518/// * `url` - The URL to make the GET request to.
519/// * `client` - The client variable to use for the request.
520///
521/// Please note url can be a string literal or a variable.
522///
523/// # Example
524///
525/// ```compile_fail
526/// let mut client = Deboa::new();
527/// let response = stream!("https://jsonplaceholder.typicode.com/posts", &mut client);
528/// assert_eq!(response.id, 1);
529/// ```
530macro_rules! stream {
531 ($url:expr, &mut $client:ident) => {
532 $client
533 .execute($url)
534 .await?
535 .stream()
536 };
537}