feat: openssl based hoppscotch-relay for request forwarding (#4442)
This commit is contained in:
201
packages/hoppscotch-relay/README.md
Normal file
201
packages/hoppscotch-relay/README.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Hoppscotch Relay
|
||||
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
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`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
hoppscotch-relay = "0.1.1"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Request
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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`:
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/hoppscotch/hoppscotch-relay
|
||||
cd hoppscotch-relay
|
||||
```
|
||||
|
||||
2. Build the project:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
Reference in New Issue
Block a user