
Nanofish
A lightweight, no_std HTTP client for embedded systems built on Embassy networking with zero-copy response handling.
Nanofish is designed for embedded systems with limited memory. It provides a simple HTTP client that works without heap allocation, making it suitable for microcontrollers and IoT devices. The library uses zero-copy response handling where response data is borrowed directly from user-provided buffers, keeping memory usage predictable and efficient.
Key Features
- Zero-Copy Response Handling - Response data is borrowed directly from user-provided buffers with no copying
- User-Controlled Memory - You provide the buffer and control exactly how much memory is used
- No Standard Library - Full
no_stdcompatibility with no heap allocations - Embassy Integration - Built on Embassy's async networking
- Complete HTTP Support - All standard HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, CONNECT)
- Smart Response Parsing - Automatic text/binary detection based on Content-Type headers
- Easy Header Management - Pre-defined constants and helper methods for common headers
- Optional TLS Support - HTTPS support with embedded-tls when enabled
- Timeout & Retry Support - Built-in handling for network issues
- DNS Resolution - Automatic hostname resolution
Zero-Copy Architecture
Unlike traditional HTTP clients that copy response data multiple times, Nanofish uses a zero-copy approach:
Traditional HTTP Clients:
Network → Internal Buffer (copy #1) → Response Struct (copy #2) → User Code (copy #3)
Nanofish Zero-Copy:
Network → YOUR Buffer (direct) → Zero-Copy References → User Code (no copies!)
Benefits:
- Better Performance - No memory copying overhead
- Memory Efficient - Uses only the memory you provide
- Predictable - No hidden allocations
- Embedded-Friendly - Works well in resource-limited environments
Installation & Feature Flags
Basic HTTP Support (Default)
[]
= "0.7.0"
With TLS/HTTPS Support
[]
= { = "0.7.0", = ["tls"] }
Available Features
tls- Enables HTTPS/TLS support viaembedded-tls- When disabled (default): Only HTTP requests are supported
- When enabled: Full HTTPS support with TLS 1.2/1.3
Quick Start
Here's a simple example showing how to use Nanofish:
use ;
use Stack;
async
let client = new;
let mut response_buffer = ;
let headers = ;
let custom_headers = ;
let = client.get.await?;
println!;
Zero-Copy Benefits
// Traditional approach (copies data):
// 1. Read from network → internal buffer (copy #1)
// 2. Parse response → response struct (copy #2)
// 3. User gets → copied data (copy #3)
// Nanofish zero-copy approach:
// 1. Read from network → YOUR buffer (direct)
// 2. Parse response → references to YOUR buffer (zero-copy)
// 3. User gets → direct references to YOUR buffer (zero-copy)
let mut small_buffer = ; // For small responses
let mut large_buffer = ; // For large responses
// Same API, different memory usage - YOU decide!
let = client.get.await?;
let = client.get.await?;
Header Convenience Features
Nanofish provides helpful APIs for working with HTTP headers:
Pre-defined Header Constants
use headers;
// Common header names
let content_type = CONTENT_TYPE; // "Content-Type"
let authorization = AUTHORIZATION; // "Authorization"
let user_agent = USER_AGENT; // "User-Agent"
let accept = ACCEPT; // "Accept"
Pre-defined MIME Types
use mime_types;
// Common MIME types
let json = JSON; // "application/json"
let xml = XML; // "application/xml"
let text = TEXT; // "text/plain"
let html = HTML; // "text/html"
Convenience Methods
use ;
// Easy creation of common headers
let headers = ;
Response Handling
Nanofish automatically determines the appropriate response body type based on the Content-Type header:
use ResponseBody;
// The response body is automatically parsed based on content type
match &response.body
if response.is_success
if response.is_client_error
if response.is_server_error
// You can also check status directly on the status code:
if response.status_code.is_success
if let Some = response.content_length
## HTTP Methods Support
Nanofish provides convenience methods for all standard HTTP verbs:
```rust,ignore
// All methods require a buffer and return (HttpResponse, bytes_read)
let mut buffer = ;
// GET request
let = client.get.await?;
// POST request with JSON body
let json_body = br#"{"name": "John", "email": "john@example.com"}"#;
let post_headers = ;
let = client.post.await?;
// PUT request
let = client.put.await?;
// DELETE request
let = client.delete.await?;
// Other HTTP methods
let = client.patch.await?;
let = client.head.await?;
let = client.options.await?;
let = client.trace.await?;
let = client.connect.await?;
All methods return a Result<(HttpResponse, usize), Error> where:
HttpResponsecontains zero-copy references to data in your bufferusizeis the number of bytes read into your buffer
Memory Efficiency Examples
Choose your buffer size based on your needs:
// Scenario 1: Memory-constrained device (1KB buffer)
let mut tiny_buffer = ;
let = client.get.await?;
// Perfect for small API responses, status checks, etc.
// Scenario 2: Streaming large data (32KB buffer)
let mut large_buffer = ;
let = client.get.await?;
// Handle larger responses, file downloads, etc.
// Scenario 3: Reuse the same buffer for multiple requests
let mut shared_buffer = ;
for url in urls