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}