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}