geph4_protocol/binder/
client.rs1use std::{convert::TryInto, time::Duration};
2
3use async_compat::CompatExt;
4use async_trait::async_trait;
5
6use nanorpc::RpcTransport;
7
8use reqwest::{
9 header::{HeaderMap, HeaderName},
10 StatusCode,
11};
12
13use super::protocol::{box_decrypt, box_encrypt};
14
15pub struct E2eeHttpTransport {
17 binder_lpk: x25519_dalek::PublicKey,
18 endpoint: String,
19 client: reqwest::Client,
20}
21
22#[async_trait]
23impl RpcTransport for E2eeHttpTransport {
24 type Error = anyhow::Error;
25
26 async fn call_raw(
27 &self,
28 req: nanorpc::JrpcRequest,
29 ) -> Result<nanorpc::JrpcResponse, Self::Error> {
30 let eph_sk = x25519_dalek::StaticSecret::new(rand::thread_rng());
31 let encrypted_req =
32 box_encrypt(&serde_json::to_vec(&req)?, eph_sk.clone(), self.binder_lpk);
33 let resp = self
34 .client
35 .post(&self.endpoint)
36 .body(encrypted_req)
37 .send()
38 .compat()
39 .await?;
40 if resp.status() != StatusCode::OK {
41 anyhow::bail!("non-200 status: {}", resp.status());
42 }
43 let encrypted_resp = resp.bytes().compat().await?;
44 let (resp, _) = box_decrypt(&encrypted_resp, eph_sk)?;
45 Ok(serde_json::from_slice(&resp)?)
46 }
47}
48
49impl E2eeHttpTransport {
50 pub fn new(binder_lpk: [u8; 32], endpoint: String, headers: Vec<(String, String)>) -> Self {
52 Self {
53 binder_lpk: x25519_dalek::PublicKey::from(binder_lpk),
54 endpoint,
55 client: reqwest::ClientBuilder::new()
56 .default_headers({
57 let mut hh = HeaderMap::new();
58 for (k, v) in headers {
59 hh.insert::<HeaderName>(
60 k.to_ascii_lowercase().try_into().unwrap(),
61 v.to_ascii_lowercase().parse().unwrap(),
62 );
63 }
64 hh
65 })
66 .no_proxy()
67 .http1_only()
68 .pool_idle_timeout(Duration::from_secs(1)) .build()
70 .unwrap(),
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use async_compat::CompatExt;
78 use reqwest::header::HeaderMap;
79
80 #[test]
81 fn reqwest_domain_front() {
82 smolscale::block_on(
83 async move {
84 let client = reqwest::ClientBuilder::new()
85 .default_headers({
86 let mut hh = HeaderMap::new();
87 hh.insert("host", "loving-bell-981479.netlify.app".parse().unwrap());
88 hh
89 })
90 .build()
91 .unwrap();
92 let resp = client
93 .get("https://www.netlify.com/v4")
94 .send()
95 .await
96 .unwrap();
97 dbg!(resp);
98 }
99 .compat(),
100 );
101 }
102}