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
78pub use deboa_bora::bora;
79
80#[macro_export]
81/// Make a GET request to the specified URL.
82///
83/// The `get!` macro is used to make a GET request to the specified URL.
84/// Its first argument is a string literal or a variable. Arrows are
85/// used to specify the body serialization type and the output type.
86///
87/// You can use the `JsonBody`, `XmlBody`, `MsgPack` type for JSON, XML
88/// and MessagePack serialization.
89///
90/// To help understand the macro arguments, here is an example:
91///
92/// get!(url, &mut client, JsonBody, ty)
93///
94/// # Arguments
95///
96/// * `url`         - The URL to make the GET request to.
97/// * `client`      - The client variable to use for the request.
98/// * `res_body_ty` - The body type of the response.
99/// * `res_ty`      - The type of the response.
100///
101/// Please note url can be a string literal or a variable.
102///
103/// # Example
104///
105/// ```compile_fail
106/// let mut client = Deboa::new();
107/// let response = get!("https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Vec<Post>);
108/// assert_eq!(response.len(), 100);
109/// ```
110macro_rules! get {
111    ($url:literal, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
112        $client
113            .execute($url)
114            .await?
115            .body_as::<$res_body_ty, $res_ty>($res_body_ty)
116            .await?
117    };
118
119    ($url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
120        $client
121            .execute($url)
122            .await?
123            .body_as::<$res_body_ty, $res_ty>($res_body_ty)
124            .await?
125    };
126
127    ($url:expr, &mut $client:ident) => {
128        $client.execute($url).await?.text()
129    };
130}
131
132#[macro_export]
133/// Make a POST request to the specified URL.
134///
135/// The `post!` macro is used to make a POST request to the specified URL.
136///
137/// To help understand the macro arguments, here is an example:
138///
139/// post!(input, req_body_ty, url, &mut client, res_body_ty, res_ty)
140///
141/// # Arguments
142///
143/// * `input`       - The input to send with the request.
144/// * `req_body_ty` - The body serialization type of the request.
145/// * `url`         - The URL to make the POST request to.
146/// * `client`      - The client variable to use for the request.
147/// * `res_body_ty` - The body type of the response.
148/// * `res_ty`      - The type of the response.
149///
150/// Please note url can be a string literal or a variable.
151///
152/// # Example
153///
154/// ## Without response body deserialization
155///
156/// ```compile_fail
157/// let mut client = Deboa::new();
158/// let response = post!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts", &mut client);
159/// assert_eq!(response.id, 1);
160/// ```
161///
162/// ## With response body deserialization
163///
164/// ```compile_fail
165/// let mut client = Deboa::new();
166/// let response = post!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Post);
167/// assert_eq!(response.id, 1);
168/// ```
169macro_rules! post {
170    ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
171        $client
172            .execute(
173                deboa::request::DeboaRequest::post($url)?
174                    .body_as($req_body_ty, $input)?
175                    .build()?,
176            )
177            .await?
178    };
179
180    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
181        $client
182            .execute(
183                deboa::request::DeboaRequest::post($url)?
184                    .body_as($req_body_ty, $input)?
185                    .build()?,
186            )
187            .await?
188    };
189
190    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
191        $client
192            .execute(
193                deboa::request::DeboaRequest::post($url)?
194                    .body_as($req_body_ty, $input)?
195                    .build()?,
196            )
197            .await?
198            .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
199    };
200}
201
202#[macro_export]
203/// Make a PUT request to the specified URL.
204///
205/// The `put!` macro is used to make a PUT request to the specified URL
206/// Its first argument is a string literal or a variable.
207///
208/// To help understand the macro arguments, here is an example:
209///
210/// put!(input, req_body_ty, url, &mut client)
211///
212/// # Arguments
213///
214/// * `input`       - The input to send with the request.
215/// * `req_body_ty` - The body serialization type of the request.
216/// * `url`         - The URL to make the PUT request to.
217/// * `client`      - The client variable to use for the request.
218///
219/// Please note url can be a string literal or a variable.
220///
221/// # Example
222///
223/// ```compile_fail
224/// let mut client = Deboa::new();
225/// let response = put!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts/1", &mut client);
226/// assert_eq!(response.id, 1);
227/// ```
228macro_rules! put {
229    ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
230        $client
231            .execute(
232                deboa::request::DeboaRequest::put($url)?
233                    .body_as($req_body_ty, $input)?
234                    .build()?,
235            )
236            .await?
237    };
238
239    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
240        $client
241            .execute(
242                deboa::request::DeboaRequest::put($url)?
243                    .body_as($req_body_ty, $input)?
244                    .build()?,
245            )
246            .await?
247    };
248
249    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
250        $client
251            .execute(
252                deboa::request::DeboaRequest::put($url)?
253                    .body_as($req_body_ty, $input)?
254                    .build()?,
255            )
256            .await?
257            .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
258    };
259}
260
261#[macro_export]
262/// Make a PATCH request to the specified URL.
263///
264/// The `patch!` macro is used to make a PATCH request to the specified URL
265/// Its first argument is a string literal or a variable.
266///
267/// To help understand the macro arguments, here is an example:
268///
269/// patch!(input, req_body_ty, url, &mut client)
270///
271/// # Arguments
272///
273/// * `input`       - The input to send with the request.
274/// * `req_body_ty` - The body serialization type of the request.
275/// * `url`         - The URL to make the PATCH request to.
276/// * `client`      - The client variable to use for the request.
277///
278/// Please note url can be a string literal or a variable.
279///
280/// # Example
281///
282/// ```compile_fail
283/// let mut client = Deboa::new();
284/// let response = patch!(data, JsonBody, "https://jsonplaceholder.typicode.com/posts/1", &mut client);
285/// assert_eq!(response.id, 1);
286/// ```
287macro_rules! patch {
288    ($input:ident, $req_body_ty:ident, $url:literal, &mut $client:ident) => {
289        $client
290            .execute(
291                deboa::request::DeboaRequest::patch($url)?
292                    .body_as($req_body_ty, $input)?
293                    .build()?,
294            )
295            .await?
296    };
297
298    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident) => {
299        $client
300            .execute(
301                deboa::request::DeboaRequest::patch($url)?
302                    .body_as($req_body_ty, $input)?
303                    .build()?,
304            )
305            .await?
306    };
307
308    ($input:ident, $req_body_ty:ident, $url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
309        $client
310            .execute(
311                deboa::request::DeboaRequest::patch($url)?
312                    .body_as($req_body_ty, $input)?
313                    .build()?,
314            )
315            .await?
316            .body_as::<$res_body_ty, $res_ty>($res_body_ty)?
317    };
318}
319
320#[macro_export]
321/// Make a DELETE request to the specified URL.
322///
323/// The `delete!` macro is used to make a DELETE request to the specified URL
324/// Its first argument is a string literal or a variable.
325///
326/// To help understand the macro arguments, here is an example:
327///
328/// delete!(url, &mut client)
329///
330/// # Arguments
331///
332/// * `url`    - The URL to make the DELETE request to.
333/// * `client` - The client variable to use for the request.
334///
335/// Please note url can be a string literal or a variable.
336///
337/// # Example
338///
339/// ```compile_fail
340/// let mut client = Deboa::new();
341/// let response = delete!("https://jsonplaceholder.typicode.com/posts/1", &mut client);
342/// assert_eq!(response.id, 1);
343/// ```
344macro_rules! delete {
345    ($url:literal, &mut $client:ident) => {
346        $client
347            .execute(deboa::request::DeboaRequest::delete($url)?.build()?)
348            .await?
349    };
350
351    ($url:expr, &mut $client:ident) => {
352        $client
353            .execute(deboa::request::DeboaRequest::delete($url)?.build()?)
354            .await?
355    };
356}
357
358#[macro_export]
359/// Make a GET request to the specified URL.
360///
361/// The `fetch!` macro is a more generic version of the `get!` macro.
362/// Its first argument is a string literal or a variable. Arrows are
363/// used to specify the body serialization type and the output type.
364///
365/// You can use the `JsonBody`, `XmlBody`, `MsgPack` type for JSON, XML
366/// and MessagePack serialization.
367///
368/// To help understand the macro arguments, here is an example:
369///
370/// fetch!(url, &mut client, body, ty)
371///
372/// # Arguments
373///
374/// * `url`         - The URL to make the GET request to.
375/// * `client`      - The client variable to use for the request.
376/// * `res_body_ty` - The body type of the response.
377/// * `res_ty`      - The type of the response.
378///
379/// Please note url can be a string literal or a variable.
380///
381/// # Example
382///
383/// ```compile_fail
384/// let mut client = Deboa::new();
385/// let response = fetch!("https://jsonplaceholder.typicode.com/posts", &mut client, JsonBody, Post);
386/// assert_eq!(response.id, 1);
387/// ```
388macro_rules! fetch {
389    ($url:literal, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
390        $client
391            .execute($url)
392            .await?
393            .body_as::<$res_body_ty, $res_ty>($res_body_ty)
394            .await?
395    };
396
397    ($url:expr, &mut $client:ident, $res_body_ty:ident, $res_ty:ty) => {
398        $client
399            .execute($url)
400            .await?
401            .body_as::<$res_body_ty, $res_ty>($res_body_ty)
402            .await?
403    };
404
405    ($url:expr, &mut $client:ident) => {
406        $client.execute($url).await?
407    };
408}
409#[macro_export]
410/// Submit a request to the specified URL.
411///
412/// The `submit!` 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/// * `method`      - The HTTP method to use.
426/// * `input`       - The input to send with the request.
427/// * `url`         - The URL to make the GET request to.
428/// * `client`      - The client variable to use for the request.
429/// * `res_body_ty` - The body type of the response.
430/// * `res_ty`      - The type of the response.
431///
432/// Please note url can be a string literal or a variable.
433///
434/// # Example
435///
436/// ```compile_fail
437/// let mut client = Deboa::new();
438/// let response = submit!("POST", "user=deboa", "https://jsonplaceholder.typicode.com/posts", &mut client);
439/// assert_eq!(response.id, 1);
440/// ```
441macro_rules! submit {
442    ($method:expr, $input:expr, $url:expr, &mut $client:ident) => {
443        $client
444            .execute(
445                deboa::request::DeboaRequest::at($url, $method)?
446                    .text($input)
447                    .build()?,
448            )
449            .await?
450    };
451}