{"id":30769385,"url":"https://github.com/seemueller-io/hyper-custom-cert","last_synced_at":"2025-09-04T22:10:46.049Z","repository":{"id":309970009,"uuid":"1038218300","full_name":"seemueller-io/hyper-custom-cert","owner":"seemueller-io","description":"http client for use with self-signed certificates","archived":false,"fork":false,"pushed_at":"2025-08-28T19:31:49.000Z","size":95,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-28T23:46:21.192Z","etag":null,"topics":["client","http","rust","tls"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/hyper-custom-cert","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seemueller-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-14T20:15:48.000Z","updated_at":"2025-08-28T19:30:45.000Z","dependencies_parsed_at":"2025-08-14T22:31:15.682Z","dependency_job_id":"fd5824d4-b0a4-4584-bf72-8114739e1881","html_url":"https://github.com/seemueller-io/hyper-custom-cert","commit_stats":null,"previous_names":["seemueller-io/hyper-custom-cert"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/seemueller-io/hyper-custom-cert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seemueller-io%2Fhyper-custom-cert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seemueller-io%2Fhyper-custom-cert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seemueller-io%2Fhyper-custom-cert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seemueller-io%2Fhyper-custom-cert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seemueller-io","download_url":"https://codeload.github.com/seemueller-io/hyper-custom-cert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seemueller-io%2Fhyper-custom-cert/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273680344,"owners_count":25148785,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client","http","rust","tls"],"created_at":"2025-09-04T22:10:42.920Z","updated_at":"2025-09-04T22:10:46.020Z","avatar_url":"https://github.com/seemueller-io.png","language":"Rust","readme":"# hyper-custom-cert\n\n[![Crates.io](https://img.shields.io/crates/v/hyper-custom-cert.svg)](https://crates.io/crates/hyper-custom-cert)\n[![Documentation](https://docs.rs/hyper-custom-cert/badge.svg)](https://docs.rs/hyper-custom-cert)\n[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE)\n\nA small, ergonomic HTTP client wrapper around hyper with optional support for custom Root CAs and a dev-only insecure mode for self-signed certificates.\n\n## Features\n\n- **Secure by Default**: Uses the operating system's native trust store via `native-tls`\n- **Custom CA Support**: Optional `rustls` feature for connecting to services with custom Certificate Authorities\n- **Development Mode**: Optional `insecure-dangerous` feature for testing with self-signed certificates (⚠️ **NEVER use in production**)\n- **WebAssembly Compatible**: Proper WASM support with appropriate security constraints\n- **Certificate Pinning**: Advanced security feature for production environments\n- **Builder Pattern**: Ergonomic configuration with sensible defaults\n\n## Quick Start\n\n`cargo add hyper-custom-cert`\n\n### Basic Usage (Secure Default)\n\n```rust\nuse hyper_custom_cert::HttpClient;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Uses OS trust store by default - secure for public HTTPS endpoints\n    let client = HttpClient::new();\n    \n    // Make requests to publicly trusted endpoints\n    client.request(\"https://httpbin.org/get\").await?;\n    \n    Ok(())\n}\n```\n\n### Custom Root CA (Production)\n\nFor connecting to services with custom/private Certificate Authorities:\n\n```toml\n[dependencies]\nhyper-custom-cert = { version = \"\u003clatest\u003e\", features = [\"rustls\"] }\n```\n\n```rust\nuse hyper_custom_cert::HttpClient;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Load your organization's Root CA\n    let client = HttpClient::builder()\n        .with_root_ca_file(\"path/to/your-org-root-ca.pem\")\n        .build();\n    \n    // Now you can connect to services signed by your custom CA\n    client.request(\"https://internal.your-org.com/api\").await?;\n    \n    Ok(())\n}\n```\n\n### Certificate Pinning (Enhanced Security)\n\nFor high-security environments where you want to pin specific certificates:\n\n```rust\nuse hyper_custom_cert::HttpClient;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // SHA-256 fingerprints of certificates you want to accept\n    let pin1 = [0x12, 0x34, /* ... 30 more bytes */];\n    let pin2 = [0xab, 0xcd, /* ... 30 more bytes */];\n    \n    let client = HttpClient::builder()\n        .with_pinned_cert_sha256(vec![pin1, pin2])\n        .build();\n    \n    // Only accepts connections to certificates matching the pins\n    client.request(\"https://secure-api.example.com\").await?;\n    \n    Ok(())\n}\n```\n\n### Development/Testing Only (⚠️ Dangerous)\n\n**WARNING**: This mode disables certificate validation. Only use for local development and testing.\n\n```toml\n[dependencies]\nhyper-custom-cert = { version = \"0.1.0\", features = [\"insecure-dangerous\"] }\n```\n\n```rust\nuse hyper_custom_cert::HttpClient;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // ⚠️ EXTREMELY DANGEROUS - Only for local development\n    let client = HttpClient::builder()\n        .insecure_accept_invalid_certs(true)\n        .build();\n    \n    // Can connect to self-signed certificates (NOT for production!)\n    client.request(\"https://localhost:8443\").await?;\n    \n    Ok(())\n}\n```\n\n## Configuration Options\n\n### Builder Methods\n\n```rust\nuse hyper_custom_cert::HttpClient;\nuse std::time::Duration;\nuse std::collections::HashMap;\n\nlet mut headers = HashMap::new();\nheaders.insert(\"User-Agent\".to_string(), \"MyApp/1.0\".to_string());\n\nlet client = HttpClient::builder()\n    .with_timeout(Duration::from_secs(30))\n    .with_default_headers(headers)\n    .with_root_ca_file(\"custom-ca.pem\")  // Requires 'rustls' feature\n    .build();\n```\n\n### Available Methods\n\n| Method | Feature Required | Description |\n|--------|-----------------|-------------|\n| `new()` | None | Creates client with OS trust store (secure default) |\n| `builder()` | None | Returns a builder for custom configuration |\n| `with_timeout(Duration)` | None | Sets request timeout |\n| `with_default_headers(HashMap)` | None | Sets default headers for all requests |\n| `with_root_ca_pem(\u0026[u8])` | `rustls` | Adds custom CA from PEM bytes |\n| `with_root_ca_file(Path)` | `rustls` | Adds custom CA from PEM file |\n| `with_pinned_cert_sha256(Vec\u003c[u8; 32]\u003e)` | `rustls` | Enables certificate pinning |\n| `insecure_accept_invalid_certs(bool)` | `insecure-dangerous` | ⚠️ Disables certificate validation |\n| `with_self_signed_certs()` | `insecure-dangerous` | ⚠️ Convenience for self-signed certs |\n\n## Feature Flags\n\n### `native-tls` (Default)\n\n- **Default**: ✅ Enabled\n- **Security**: ✅ Secure - Uses OS trust store\n- **Use Case**: Public HTTPS endpoints with standard certificates\n- **Dependencies**: `hyper-tls`, `native-tls`\n\n### `rustls`\n\n- **Default**: ❌ Disabled\n- **Security**: ✅ Secure - Custom CA validation\n- **Use Case**: Private/custom Certificate Authorities\n- **Dependencies**: `hyper-rustls`, `rustls-pemfile`\n- **Enables**: `with_root_ca_pem()`, `with_root_ca_file()`, `with_pinned_cert_sha256()`\n\n### `insecure-dangerous`\n\n- **Default**: ❌ Disabled\n- **Security**: ❌ **EXTREMELY DANGEROUS**\n- **Use Case**: **Development/testing ONLY**\n- **Warning**: **NEVER enable in production**\n- **Enables**: `insecure_accept_invalid_certs()`, `with_self_signed_certs()`\n\n## WebAssembly (WASM) Support\n\nThis crate supports WebAssembly targets with important security considerations:\n\n```rust\n// WASM builds will compile, but certain operations are restricted\n#[cfg(target_arch = \"wasm32\")]\n{\n    let client = HttpClient::new(); // ✅ Works\n    // Custom CA operations may return WasmNotImplemented errors\n}\n```\n\n**WASM Limitations:**\n- Custom Root CA installation requires browser/OS-level certificate management\n- Some TLS configuration options may not be available\n- Certificate pinning may be limited by browser security policies\n\n**Browser Certificate Installation:**\n1. Download your organization's Root CA certificate\n2. Install it in your browser's certificate store\n3. Mark it as trusted for websites\n4. Your WASM application will then trust endpoints signed by that CA\n\n## Error Handling\n\n```rust\nuse hyper_custom_cert::{HttpClient, ClientError};\n\nmatch client.request(\"https://example.com\").await {\n    Ok(_) =\u003e println!(\"Request successful\"),\n    Err(ClientError::WasmNotImplemented) =\u003e {\n        println!(\"This operation isn't supported in WASM\");\n    }\n    Err(e) =\u003e {\n        println!(\"Request failed: {}\", e);\n    }\n}\n```\n\n## Security Best Practices\n\n### Production Recommendations\n\n1. **Use Default Mode**: Stick with `native-tls` for public endpoints\n2. **Custom CA Only When Needed**: Only use `rustls` feature when connecting to private CAs\n3. **Never Use `insecure-dangerous`**: This feature should never be enabled in production\n4. **Keep Dependencies Updated**: Monitor for security advisories\n5. **Certificate Pinning**: Consider pinning for high-security applications\n\n### Development vs Production\n\n```rust\n// ✅ GOOD: Production configuration\n#[cfg(not(debug_assertions))]\nlet client = HttpClient::new(); // Uses OS trust store\n\n// ✅ GOOD: Development configuration  \n#[cfg(debug_assertions)]\nlet client = HttpClient::builder()\n    .insecure_accept_invalid_certs(true)  // Only in debug builds\n    .build();\n```\n\n## Examples\n\nSee the `examples/` directory for complete working examples:\n\n- `examples/self-signed-certs/` - Comprehensive examples for all modes\n- Example of connecting to public endpoints (default mode)\n- Example of using custom Root CA for private services\n- Example of development mode with self-signed certificates\n\n## Testing\n\n```bash\n# Test with default features\ncargo test\n\n# Test with rustls features\ncargo test --features rustls\n\n# Test with all features (for development)\ncargo test --features rustls,insecure-dangerous\n\n# Test WASM compatibility\ncargo test --target wasm32-unknown-unknown\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Ensure all tests pass: `cargo test --all-features`\n6. Submit a pull request\n\n## License\n\nThis project is licensed under either of:\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))\n- MIT License ([LICENSE-MIT](LICENSE-MIT))\n\nat your option.\n\n## Security Policy\n\nFor security vulnerabilities, please see [SECURITY.md](SECURITY.md) for our responsible disclosure policy.\n\n---\n\n**Remember**: This library prioritizes security by default. The `insecure-dangerous` feature exists solely for development convenience and should never be used in production environments.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseemueller-io%2Fhyper-custom-cert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseemueller-io%2Fhyper-custom-cert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseemueller-io%2Fhyper-custom-cert/lists"}