Hoppscotch Relay
A high-performance HTTP request-response relay used by Hoppscotch Desktop and Hoppscotch Agent for advanced request handling including CORS override, custom headers, certificates, proxies, and local system integration. It uses a custom fork of curl-rust with static OpenSSL builds for consistent SSL/TLS behavior across different platforms.
Features
- 🚀 Full HTTP Support: Handle GET, POST, PUT, DELETE, and other HTTP methods
- 📦 Multiple Body Types:
- Raw text/JSON
- URL-encoded forms
- Multipart form data
- File uploads
- 🔒 Security:
- Client certificate authentication (PEM & PFX/PKCS#12)
- Custom root certificate bundles
- Certificate validation control
- 🌐 Proxy Support:
- HTTP/HTTPS proxy configuration
- Authentication support
- NTLM support
- ⚡ Performance:
- Async design
- Request cancellation support
- Progress logs
- 📊 Detailed Metrics:
- Response timing
- Status tracking
- Header parsing
Installation
Add this to your Cargo.toml:
[dependencies]
hoppscotch-relay = "0.1.1"
Usage
Basic Request
use hoppscotch_relay::{RequestWithMetadata, KeyValuePair};
use tokio_util::sync::CancellationToken;
// Create a basic GET request
let request = RequestWithMetadata::new(
1, // Request ID
"GET".to_string(), // Method
"https://api.example.com/data".to_string(), // Endpoint
vec![ // Headers
KeyValuePair {
key: "Accept".to_string(),
value: "application/json".to_string(),
}
],
None, // Body
true, // Validate certificates
vec![], // Root certificate bundles
None, // Client certificate
None, // Proxy configuration
);
// Execute the request with cancellation support
let cancel_token = CancellationToken::new();
let response = hoppscotch_relay::run_request_task(&request, cancel_token)?;
println!("Status: {} {}", response.status, response.status_text);
println!("Response time: {}ms", response.time_end_ms - response.time_start_ms);
POST Request with JSON Body
let mut request = RequestWithMetadata::new(
2,
"POST".to_string(),
"https://api.example.com/users".to_string(),
vec![
KeyValuePair {
key: "Content-Type".to_string(),
value: "application/json".to_string(),
}
],
Some(BodyDef::Text(r#"{"name": "John Doe"}"#.to_string())),
true,
vec![],
None,
None,
);
let response = hoppscotch_relay::run_request_task(&request, CancellationToken::new())?;
File Upload with Form Data
let form_data = vec![
FormDataEntry {
key: "file".to_string(),
value: FormDataValue::File {
filename: "document.pdf".to_string(),
data: std::fs::read("document.pdf")?,
mime: "application/pdf".to_string(),
},
},
FormDataEntry {
key: "description".to_string(),
value: FormDataValue::Text("Important document".to_string()),
},
];
let mut request = RequestWithMetadata::new(
3,
"POST".to_string(),
"https://api.example.com/upload".to_string(),
vec![],
Some(BodyDef::FormData(form_data)),
true,
vec![],
None,
None,
);
Client Certificate Authentication
let client_cert = ClientCertDef::PEMCert {
certificate_pem: std::fs::read("client.crt")?,
key_pem: std::fs::read("client.key")?,
};
let mut request = RequestWithMetadata::new(
4,
"GET".to_string(),
"https://secure-api.example.com".to_string(),
vec![],
None,
true,
vec![],
Some(client_cert),
None,
);
Proxy Configuration
let proxy_config = ProxyConfig {
url: "http://proxy.example.com:8080".to_string(),
};
let mut request = RequestWithMetadata::new(
5,
"GET".to_string(),
"https://api.example.com".to_string(),
vec![],
None,
true,
vec![],
None,
Some(proxy_config),
);
Request Cancellation
The library supports request cancellation through Tokio's CancellationToken:
use tokio_util::sync::CancellationToken;
let cancel_token = CancellationToken::new();
let cancel_token_clone = cancel_token.clone();
// Spawn the request in a separate task
let request_handle = tokio::spawn(async move {
hoppscotch_relay::run_request_task(&request, cancel_token_clone)
});
// Cancel the request after 5 seconds
tokio::time::sleep(Duration::from_secs(5)).await;
cancel_token.cancel();
Building from Source
- Clone the repository:
git clone https://github.com/hoppscotch/hoppscotch-relay
cd hoppscotch-relay
- Build the project:
cargo build --release