What is deboa-macros?
deboa-macros is a procedural-macro crate for Rust that builds on top of the core HTTP client deboa. Its goal is to simplify common HTTP request patterns using expressive macros---turning verbose boilerplate into concise, type-safe code.
Where deboa provides low-level HTTP capabilities (HTTP/1 + HTTP/2, async runtimes like Tokio or Smol, etc.), deboa-macros layers ergonomic syntax on top so you can focus on logic instead of
request-building ceremony.
Why Macros? --- The Case for deboa-macros
Rust's procedural macros allow developers to run code at compile time to generate boilerplate, enforce patterns, and create domain-specific syntax.
For HTTP requests, much of the code is repetitive:
- building the request
- serializing bodies
- deserializing responses
- handling errors
deboa-macros addresses these pain points with:
- Shorthand macros for common HTTP methods (
get!,post!,put!,patch!,delete!,fetch!) - Compile-time type safety for request/response bodies (via Serde)
- Async/await support
- Declarative API client definitions using the
#[bora]attribute macro
The result is a more pleasant, readable workflow---without sacrificing control or safety.
Key Features & API Overview
✔ Function-like Macros
deboa-macros provides macros corresponding to HTTP verbs:
-
get! -
post! -
put! -
patch! -
delete! -
fetch!(generic method caller)
Each macro expands into an async HTTP call using deboa, with optional body and response type handling.
✔ #[bora] Attribute Macro
The bora macro lets you define a high-level API client declaratively.
You describe:
- the endpoints
- their HTTP methods
- input parameters
- response bodies
- serialization format
The macro generates a fully-typed client struct with async methods.
✔ Serialization Formats Supported
- JSON
- XML
- MessagePack
All wired through Serde.
Example: GET Request Using get!
use deboa::Deboa;
use deboa_extras::http::serde::json::JsonBody;
#[derive(serde::Deserialize)]
struct Post {
id: u32,
title: String,
body: String,
userId: u32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Deboa::new();
let post: Post = get!(
"https://jsonplaceholder.typicode.com/posts/1",
&mut client,
JsonBody,
Post
);
println!("Post title: {}", post.title);
Ok(())
}
Example: Declarative API Client with #[bora]
use deboa::errors::DeboaError;
use deboa_macros::bora;
use vamo::Vamo;
#[derive(Deserialize, Debug)]
pub struct Post {
pub id: u32,
pub title: String,
}
#[bora(
api(
get(name="get_by_id", path="/posts/<id:i32>", res_body=Post, format="json")
)
)]
pub struct PostService;
#[tokio::main]
async fn main() -> Result<(), DeboaError> {
let client = Vamo::new("https://jsonplaceholder.typicode.com");
let mut service = PostService::new(client);
let post = service.get_by_id(1).await?;
println!("id: {}", post.id);
println!("title: {}", post.title);
Ok(())
}
When to Use deboa-macros
Great Fit When:
- You want concise, readable HTTP calls.
- You prefer declarative API client definitions.
- You care about type-safe request/response handling.
- You're working with async Rust.
Consider Using Raw deboa When:
- You need very fine-grained control over request lifecycle.
- You need complex middleware or streaming.
- You prefer explicit, hand-written code over macro-generated abstractions.
Ecosystem Fit
deboa-macros sits on top of a trio of crates:
-
deboa--- core HTTP client -
deboa_extras--- additional serialization/compression helpers -
deboa-macros--- ergonomic macros and declarative API definitions
This combination forms a flexible stack for building REST clients in Rust with minimal boilerplate.
My Take
As a developer, libraries that reduce boilerplate without hiding
important details are always welcome. deboa-macros hits that sweet spot:
- It speeds up API client creation
- It preserves strong typing
- It works seamlessly with Rust async and Serde
- You can still drop down to raw
deboafor advanced behavior
If you're building internal tools, microservices, or interacting with REST APIs, deboa-macros is definitely worth trying.
Conclusion
deboa-macros brings ergonomic macros, type safety, and readability to HTTP client code in Rust. It builds on deboa's solid async foundation to provide high-level, expressive syntax ideal for REST-heavy applications.
If you enjoy clean, declarative Rust with less boilerplate---and still want full control when needed---this crate is a strong choice.
Top comments (0)