| Crates.io | toolcraft-request |
| lib.rs | toolcraft-request |
| version | 0.2.3 |
| created_at | 2025-08-05 03:57:20.337449+00 |
| updated_at | 2025-10-30 07:42:54.042319+00 |
| description | Toolcraft request module |
| homepage | |
| repository | https://github.com/code-serenade/toolcraft.git |
| max_upload_size | |
| id | 1781510 |
| size | 73,081 |
A lightweight, ergonomic HTTP client wrapper around reqwest with support for base URLs, default headers, and streaming responses.
Add this to your Cargo.toml:
[dependencies]
toolcraft-request = "*"
Check the crates.io page for the latest version.
use toolcraft_request::Request;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new request client
let mut client = Request::new()?;
client.set_base_url("https://api.example.com")?;
// Make a simple GET request
let response = client.get("/users", None, None).await?;
println!("Status: {}", response.status());
println!("Body: {}", response.text().await?);
Ok(())
}
use toolcraft_request::{Request, HeaderMap};
let mut client = Request::new()?;
client.set_base_url("https://api.example.com")?;
// Method 1: Build headers manually
let mut headers = HeaderMap::new();
headers.insert("Authorization", "Bearer token123".to_string())?;
headers.insert("User-Agent", "MyApp/1.0".to_string())?;
client.set_default_headers(headers);
// Method 2: Use preset for JSON APIs
let headers = HeaderMap::for_json()?;
client.set_default_headers(headers);
// Sets: Content-Type: application/json
// Accept: application/json
// Method 3: Use preset for form uploads
let headers = HeaderMap::for_form();
client.set_default_headers(headers);
// Returns empty HeaderMap (Content-Type handled by post_form)
let query = vec![
("page".to_string(), "1".to_string()),
("limit".to_string(), "10".to_string()),
];
let response = client.get("/users", Some(query), None).await?;
use serde_json::json;
let body = json!({
"name": "John Doe",
"email": "john@example.com"
});
let response = client.post("/users", &body, None).await?;
use toolcraft_request::HeaderMap;
use serde_json::json;
// Support dynamic header values
let token = get_auth_token().await?;
let mut headers = HeaderMap::new();
headers.insert("Authorization", format!("Bearer {}", token))?;
headers.insert("Content-Type", "application/json".to_string())?;
let body = json!({"data": "value"});
let response = client.post("/api/data", &body, Some(headers)).await?;
use toolcraft_request::{Request, FormField};
let mut client = Request::new()?;
client.set_base_url("https://api.example.com")?;
// Method 1: Upload file from path
let fields = vec![
FormField::text("username", "john_doe"),
FormField::text("description", "My avatar"),
FormField::file("avatar", "/path/to/image.jpg").await?,
];
let response = client.post_form("/upload", fields, None).await?;
// Method 2: Upload from bytes
let file_data = std::fs::read("/path/to/file.pdf")?;
let fields = vec![
FormField::text("title", "Document"),
FormField::file_from_bytes("document", "file.pdf", file_data),
];
let response = client.post_form("/documents", fields, None).await?;
Important: post_form() automatically removes Content-Type header to let reqwest set the correct multipart/form-data with boundary.
use toolcraft_request::HeaderMap;
// Create with presets
let mut headers = HeaderMap::for_json()?; // JSON API preset
// Or: let headers = HeaderMap::for_form(); // Form upload preset
// Or: let mut headers = HeaderMap::new(); // Empty
// Insert headers (supports dynamic strings)
headers.insert("Authorization", "Bearer token".to_string())?;
let custom_header = "X-Request-ID".to_string();
headers.insert(custom_header, "12345".to_string())?;
// Check if header exists
if headers.contains("Authorization") {
println!("Auth header present");
}
// Get header value
if let Some(value) = headers.get("Authorization") {
println!("Auth: {}", value);
}
// Remove header
let removed = headers.remove("Authorization");
assert_eq!(removed, Some("Bearer token".to_string()));
// Merge headers
let mut other_headers = HeaderMap::new();
other_headers.insert("User-Agent", "MyApp/1.0".to_string())?;
headers.merge(other_headers);
use futures_util::StreamExt;
use serde_json::json;
let body = json!({
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
});
let mut stream = client.post_stream("/chat", &body, None).await?;
while let Some(chunk) = stream.next().await {
let bytes = chunk?;
println!("Received {} bytes", bytes.len());
}
match client.get("/api/data", None, None).await {
Ok(response) => println!("Success: {}", response.status()),
Err(e) => eprintln!("Error: {}", e),
}
Request::new() - Create a new Request clientRequest::with_timeout(timeout_sec: u64) - Create client with timeoutset_base_url(&mut self, base_url: &str) - Set base URL for all requestsset_default_headers(&mut self, headers: HeaderMap) - Set default headersget(endpoint, query, headers) - Send GET request
endpoint: &str - API endpointquery: Option<Vec<(String, String)>> - Query parametersheaders: Option<HeaderMap> - Custom headerspost(endpoint, body, headers) - Send POST request with JSON
endpoint: &str - API endpointbody: &serde_json::Value - JSON bodyheaders: Option<HeaderMap> - Custom headersput(endpoint, body, headers) - Send PUT request with JSON
delete(endpoint, headers) - Send DELETE request
post_form(endpoint, form_fields, headers) - Send POST with multipart/form-data
endpoint: &str - API endpointform_fields: Vec<FormField> - Form fields (text and files)headers: Option<HeaderMap> - Custom headerspost_stream(endpoint, body, headers) - Send POST and return byte stream
FormField::text(name, value) - Create text fieldFormField::file(name, path) - Create file field from path (async)FormField::file_from_bytes(name, filename, content) - Create file field from bytesFactory Methods:
new() - Create new empty HeaderMapfor_json() - Create with JSON preset headers (Content-Type + Accept)for_form() - Create for form uploads (empty, Content-Type auto-handled)Management Methods:
insert(key, value) - Insert header (supports dynamic strings, overwrites if exists)get(key) - Get header value as Stringremove(key) - Remove header and return its valuecontains(key) - Check if header existsmerge(other) - Merge another HeaderMap (overwrites on conflict)status() - Get HTTP status codeheaders() - Get response headerstext() - Get response as text (async)json<T>() - Parse response as JSON (async)bytes() - Get response as bytes (async)This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.