| Crates.io | retrofit-rs-macros |
| lib.rs | retrofit-rs-macros |
| version | 0.2.0 |
| created_at | 2025-10-05 13:01:43.585047+00 |
| updated_at | 2025-10-15 17:00:06.648336+00 |
| description | Procedural macros for Retrofit-rs HTTP client library |
| homepage | https://github.com/okayfine996/retrofit-rs |
| repository | https://github.com/okayfine996/retrofit-rs |
| max_upload_size | |
| id | 1869005 |
| size | 29,826 |
A type-safe, declarative HTTP client library for Rust, inspired by Java Retrofit.
Add Retrofit-rs to your Cargo.toml:
[dependencies]
retrofit-rs = "0.1"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
Define your API:
use retrofit_rs::{api, get, Result};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct User {
id: u64,
name: String,
}
#[api("https://api.github.com")]
trait GitHubApi {
#[get("/users/{username}")]
async fn get_user(&self, username: &str) -> Result<User>;
}
#[tokio::main]
async fn main() -> Result<()> {
let api = GitHubApiClient::new()?;
let user = api.get_user("octocat").await?;
println!("{:#?}", user);
Ok(())
}
For simple scripts and CLI tools that don't need async:
[dependencies]
retrofit-rs = { version = "0.1", default-features = false, features = ["sync"] }
serde = { version = "1", features = ["derive"] }
# Note: No tokio needed!
use retrofit_rs::{api, get, Result};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct User {
id: u64,
name: String,
}
// Note: Add 'blocking' parameter and remove 'async' from methods
#[api("https://api.github.com", blocking)]
trait GitHubApi {
#[get("/users/{username}")]
fn get_user(&self, username: &str) -> Result<User>;
}
fn main() -> Result<()> {
let api = GitHubApiClient::new()?;
let user = api.get_user("octocat")?; // No .await needed
println!("{:#?}", user);
Ok(())
}
use retrofit_rs::{Retrofit, Result};
let client = Retrofit::builder()
.base_url("https://api.example.com")
.build()?;
let request = client.get("/users/{id}")
.path_param("id", "123");
let user: User = client.execute(request).await?;
use std::time::Duration;
let client = Retrofit::builder()
.base_url("https://api.example.com")
.timeout(Duration::from_secs(60)) // Overall timeout (default: 30s)
.connect_timeout(Duration::from_secs(10)) // Connection timeout (default: 10s)
.build()?;
use retrofit_rs::interceptors::{LoggingInterceptor, AuthInterceptor};
let client = Retrofit::builder()
.base_url("https://api.example.com")
.add_interceptor(LoggingInterceptor::body())
.add_interceptor(AuthInterceptor::bearer("token"))
.build()?;
use retrofit_rs::{api, get, post, put, delete, Body, Path, Query};
#[derive(Serialize, Deserialize)]
struct Book {
id: u32,
title: String,
author: String,
}
#[api("http://localhost:3030")]
trait BookApi {
#[get("/books")]
async fn list_books(&self) -> Result<Vec<Book>>;
#[get("/books/{id}")]
async fn get_book(&self, id: Path<u32>) -> Result<Book>;
#[post("/books")]
async fn create_book(&self, book: Body<Book>) -> Result<Book>;
#[put("/books/{id}")]
async fn update_book(&self, id: Path<u32>, book: Body<Book>) -> Result<Book>;
#[delete("/books/{id}")]
async fn delete_book(&self, id: Path<u32>) -> Result<()>;
}
// Use the API
let client = retrofit_rs::Retrofit::builder()
.base_url("http://localhost:3030")
.build()?;
let api = BookApiClient::with_client(client);
// Create
let book = api.create_book(Body::new(new_book)).await?;
// Read
let book = api.get_book(Path::new(1)).await?;
// Update
let updated = api.update_book(Path::new(1), Body::new(book)).await?;
// Delete
api.delete_book(Path::new(1)).await?;
Retrofit-rs supports flexible feature flags to control what gets compiled:
| Feature | Default | Description |
|---|---|---|
async |
✅ | Async HTTP client with tokio |
sync |
❌ | Blocking (sync) HTTP client |
# Default: async
retrofit-rs = "0.1"
# Only blocking (smallest binary, no tokio)
retrofit-rs = { version = "0.1", default-features = false, features = ["sync"] }
# Both async and blocking
retrofit-rs = { version = "0.1", default-features = false, features = ["async", "sync"] }
Benefits:
See FEATURES_GUIDE.md for detailed information.
# Async Examples (requires 'async' feature)
cargo run -p retrofit-rs-examples --example book_crud --features retrofit-rs/async
cargo run -p retrofit-rs-examples --example github --features retrofit-rs/async
# Blocking Examples (requires 'blocking' feature)
cargo run -p retrofit-rs-examples --example github_blocking --features retrofit-rs/blocking
# Or use default features (async)
cargo run -p retrofit-rs-examples --example github
use retrofit_rs::interceptors::LoggingInterceptor;
// Basic logging (method and URL)
.add_interceptor(LoggingInterceptor::basic())
// With headers
.add_interceptor(LoggingInterceptor::headers())
// Full logging (including body)
.add_interceptor(LoggingInterceptor::body())
use retrofit_rs::interceptors::AuthInterceptor;
// Bearer token
.add_interceptor(AuthInterceptor::bearer("token"))
// Basic auth
.add_interceptor(AuthInterceptor::basic("user", "pass"))
// API Key
.add_interceptor(AuthInterceptor::api_key("X-API-Key", "key"))
retrofit-rs/
├── retrofit-rs # Core library
│ ├── Client # Async HTTP client
│ ├── Blocking # Sync HTTP client
│ ├── Interceptors # Middleware system
│ └── Builder # Fluent API
│
└── retrofit-rs-macros # Procedural macros
├── #[api] # API definition (supports async & blocking)
└── #[get/post] # HTTP methods
| Feature | Java Retrofit | Retrofit-rs |
|---|---|---|
| API Style | Annotations | Macros ✨ |
| Type Safety | Runtime | Compile-time ✅ |
| Async | Callback/RxJava | async/await ✅ |
| Blocking | OkHttp sync | Built-in ✅ |
| Performance | JVM overhead | Zero-cost ✅ |
| Memory Safety | GC | Ownership ✅ |
| Feature | Async API | Blocking API |
|---|---|---|
| Use Case | Web servers, high concurrency | CLI tools, scripts, simple clients |
| Syntax | async fn, .await |
Regular fn, no .await |
| Runtime | Requires tokio | No runtime needed |
| Concurrency | Non-blocking, handles many requests | Blocking, one request at a time |
| Performance | High throughput | Simple and predictable |
| Binary Size | Larger (includes runtime) | Smaller (no async runtime) |
| Learning Curve | Steeper (async concepts) | Easier (familiar sync code) |
Retrofit-rs brings the beloved Retrofit API design pattern to Rust, combining Java's proven declarative HTTP client approach with Rust's compile-time safety and zero-cost abstractions.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
Inspired by Square's Retrofit for Java.
Made with ❤️ and 🦀 by the Rust community