pub struct Client { /* private fields */ }Expand description
An encrypted HTTP client that communicates through an enclavia proxy.
All requests are encrypted end-to-end using the Noise protocol and forwarded through a WebSocket proxy to the enclave backend. The client verifies the enclave’s attestation document during connection.
Client is cheaply cloneable and can be shared across tasks.
Implementations§
Source§impl Client
impl Client
Sourcepub async fn connect(url: &str, pcrs: Pcrs) -> Result<Self, Error>
pub async fn connect(url: &str, pcrs: Pcrs) -> Result<Self, Error>
Connect to an enclavia proxy and verify the enclave attestation.
This performs the full connection sequence:
- WebSocket connection to the proxy
- Noise NN handshake
- Attestation request and verification
§Example
// Hex PCRs exactly as printed by `enclavia enclave status` /
// `enclavia reproduce`, copy/paste friendly:
let pcrs = enclavia::Pcrs::from_hex("6be2...", "4b4d...", "21b9...")?;
let client = enclavia::Client::connect("wss://proxy.example.com", pcrs).await?;
let resp = client.get("/api/data").send().await?;Sourcepub fn builder(url: &str) -> ClientBuilder
pub fn builder(url: &str) -> ClientBuilder
Create a builder for more advanced configuration.
Sourcepub fn get(&self, path: &str) -> RequestBuilder
pub fn get(&self, path: &str) -> RequestBuilder
Start building a GET request.
Sourcepub fn post(&self, path: &str) -> RequestBuilder
pub fn post(&self, path: &str) -> RequestBuilder
Start building a POST request.
Sourcepub fn put(&self, path: &str) -> RequestBuilder
pub fn put(&self, path: &str) -> RequestBuilder
Start building a PUT request.
Sourcepub fn delete(&self, path: &str) -> RequestBuilder
pub fn delete(&self, path: &str) -> RequestBuilder
Start building a DELETE request.
Sourcepub fn patch(&self, path: &str) -> RequestBuilder
pub fn patch(&self, path: &str) -> RequestBuilder
Start building a PATCH request.
Sourcepub fn request(&self, method: Method, path: &str) -> RequestBuilder
pub fn request(&self, method: Method, path: &str) -> RequestBuilder
Start building a request with an arbitrary method.
Sourcepub async fn upgrade(
&self,
method: Method,
path: &str,
headers: &[(String, String)],
) -> Result<UpgradedStream, Error>
pub async fn upgrade( &self, method: Method, path: &str, headers: &[(String, String)], ) -> Result<UpgradedStream, Error>
Open an upgraded stream (e.g. WebSocket) through the encrypted channel.
Builds an HTTP/1.1 request with the supplied method, path, and headers,
sends it as a ClientMessage::OpenStream through the Noise tunnel, and
accumulates the workload’s reply bytes (delivered as
ServerMessage::StreamData) until a complete HTTP/1.1 response head is
parsed.
On 101 Switching Protocols the returned UpgradedStream is a raw
bidirectional byte pipe carrying the post-upgrade payload (e.g.
WebSocket frames). On any other status the call returns
Error::UpgradeFailed with the observed status code and the response
head bytes, so the caller can surface the failure verbatim.
The 101 detection lives entirely on the SDK side: the in-enclave server
treats OpenStream as an opaque byte pipe, which keeps the server-side
protocol small enough that a future non-Rust frontend can implement it
without an HTTP parser.
The returned stream implements tokio::io::AsyncRead +
tokio::io::AsyncWrite and can be wrapped with
tokio_tungstenite::WebSocketStream::from_raw_socket to get a
client-side WebSocket endpoint that talks to the workload.
Sourcepub async fn open_stream(
&self,
payload: Vec<u8>,
) -> Result<UpgradedStream, Error>
pub async fn open_stream( &self, payload: Vec<u8>, ) -> Result<UpgradedStream, Error>
Opens a raw bidirectional byte stream to the workload.
The workload’s loopback TCP receives payload first, then bytes flow
bidirectionally over the returned UpgradedStream. No HTTP
semantics: this is the low-level primitive
Client::upgrade is built on top of. Useful for non-HTTP
protocols (raw TCP forwarding, custom wire formats) or for proxies
that handle HTTP parsing themselves (pingora-enclavia hands the
resulting stream to Pingora as a custom L4 transport).
payload is delivered as the first chunk of the in-enclave socket’s
receive buffer; if you don’t have any prologue to ship, pass an empty
Vec<u8> and the channel becomes a plain TCP-shaped pipe from the
first byte.