Skip to content

A lightweight, blocking HTTP client for testing embedded Rust environments in native environments, built on hyper and tokio.

License

Notifications You must be signed in to change notification settings

ThalusA/native-svc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

native-svc

Rust Crates.io Documentation License

A lightweight, blocking HTTP client for testing embedded Rust environments in native environments, built on hyper and tokio. It implements the embedded_svc::http::client::Connection trait with TLS support, zero-copy buffering, custom error handling, and synchronous I/O over HTTP bodies.

An HTTP adapter that implements the embedded-svc interface using hyper as the backend.

This library enables HTTP/HTTPS requests with a familiar synchronous API while leveraging the power and robustness of hyper under the hood.

πŸš€ Features

  • Synchronous Interface: Simple and familiar API based on embedded-svc
  • HTTPS Support: Secure TLS connections via hyper-tls
  • Body Handling: Complete support for reading and writing request/response bodies
  • HTTP Headers: Full header management with validation
  • Error Handling: Detailed and ergonomic error types
  • Performance: Built on hyper and tokio for optimal performance

πŸ“¦ Installation

Add this to your Cargo.toml:

[dependencies]
native-svc = "0.1.0"

πŸ› οΈ Usage

Simple GET Request

use native_svc::HyperHttpConnection;
use embedded_svc::http::client::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a connection
let conn = HyperHttpConnection::new()?;
let mut client = Client::wrap(conn);

    // Perform a GET request
    let request = client.get("https://httpbin.org/get")?;
    let mut response = request.submit()?;

    // Read the response
    let mut body = Vec::new();
    let mut buf = [0u8; 1024];
    
    while let Ok(n) = response.read(&mut buf) {
        if n == 0 { break; }
        body.extend_from_slice(&buf[..n]);
    }

    println!("Status: {}", response.status());
    println!("Body: {}", String::from_utf8_lossy(&body));
    
    Ok(())
}

POST Request with JSON

use native_svc::HyperHttpConnection;
use embedded_svc::http::client::Client;
use embedded_svc::io::Write;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let conn = HyperHttpConnection::new()?;
let mut client = Client::wrap(conn);

    // Prepare JSON data
    let json_data = r#"{"name": "John", "age": 30}"#;
    let headers = &[
        ("Content-Type", "application/json"),
        ("Content-Length", &json_data.len().to_string()),
    ];

    // Create and send the request
    let mut request = client.post("https://httpbin.org/post", headers)?;
    request.write_all(json_data.as_bytes())?;
    request.flush()?;
    
    let mut response = request.submit()?;

    // Process the response
    println!("Status: {}", response.status());
    if let Some(content_type) = response.header("content-type") {
        println!("Content-Type: {}", content_type);
    }

    Ok(())
}

Error Handling

use native_svc::{HyperHttpConnection, HyperError};

fn make_request() -> Result<String, HyperError> {
let conn = HyperHttpConnection::new()?;
let mut client = embedded_svc::http::client::Client::wrap(conn);

    let request = client.get("https://example.com")?;
    let mut response = request.submit()?;
    
    let mut body = String::new();
    let mut buffer = [0u8; 1024];
    
    loop {
        match response.read(&mut buffer)? {
            0 => break,
            n => body.push_str(&String::from_utf8_lossy(&buffer[..n])),
        }
    }
    
    Ok(body)
}

πŸ—οΈ Architecture

The library is organized into modules:

  • lib.rs: Main HyperHttpConnection structure and trait implementations
  • error.rs: Custom error types with detailed error handling

Implemented Traits

  • embedded_svc::http::client::Connection: Main interface for HTTP connections
  • embedded_svc::io::Read: Reading response body
  • embedded_svc::io::Write: Writing request body
  • embedded_svc::http::Status: HTTP status access
  • embedded_svc::http::Headers: HTTP headers access

πŸ§ͺ Testing

Run tests with:

cargo test

Note: Integration tests require an Internet connection as they use httpbin.org.

πŸ“Š Performance

  • Runtime: Uses Tokio with a multi-threaded runtime
  • Memory: Default internal buffer of 8KB for write operations
  • Connections: HTTPS connections support with connection reuse via hyper

πŸ”’ Security

  • Native TLS/SSL support via hyper-tls

🀝 Contributing

Contributions are welcome! Here's how to contribute:

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Development Guidelines

  • Follow Rust naming conventions
  • Add tests for new functionality
  • Update documentation for public APIs
  • Ensure cargo clippy passes without warnings

πŸ“„ License

This project is licensed under MIT. See the LICENSE files for details.

πŸ”„ Compatibility

  • Rust Version: 1.88.0 or later
  • Platforms: All platforms supported by tokio and hyper
  • HTTP Versions: HTTP/1.1

πŸ™ Acknowledgments

  • The hyper team for their excellent HTTP client
  • The embedded-svc team for standardized traits
  • The Rust community for the incredible ecosystem

πŸ› Known Issues

  • Limited HTTP/2 support (HTTP/1.1 only currently)

Made with ❀️ in Rust

About

A lightweight, blocking HTTP client for testing embedded Rust environments in native environments, built on hyper and tokio.

Topics

Resources

License

Stars

Watchers

Forks

Languages