buzzrelay/src/send.rs

62 lines
1.9 KiB
Rust
Raw Normal View History

2022-12-20 02:13:44 +00:00
use std::{
sync::Arc,
time::{Instant, SystemTime},
2022-12-20 02:13:44 +00:00
};
2022-12-13 03:12:35 +00:00
use http::StatusCode;
2022-12-20 02:13:44 +00:00
use metrics::histogram;
2022-12-11 00:07:39 +00:00
use serde::Serialize;
use sigh::{PrivateKey, SigningConfig, alg::RsaSha256};
2023-05-14 20:58:00 +00:00
use crate::{digest, error::Error};
2022-12-11 00:07:39 +00:00
pub async fn send<T: Serialize>(
client: &reqwest::Client,
2022-12-13 03:12:35 +00:00
uri: &str,
2022-12-11 00:07:39 +00:00
key_id: &str,
private_key: &PrivateKey,
2022-12-19 20:20:13 +00:00
body: &T,
2023-05-14 20:58:00 +00:00
) -> Result<(), Error> {
2022-12-19 20:20:13 +00:00
let body = Arc::new(
serde_json::to_vec(body)?
2022-12-19 20:20:13 +00:00
);
send_raw(client, uri, key_id, private_key, body).await
}
pub async fn send_raw(
client: &reqwest::Client,
uri: &str,
key_id: &str,
private_key: &PrivateKey,
body: Arc<Vec<u8>>,
2023-05-14 20:58:00 +00:00
) -> Result<(), Error> {
2022-12-13 03:12:35 +00:00
let url = reqwest::Url::parse(uri)
2023-05-14 20:44:26 +00:00
.map_err(|_| Error::InvalidUri)?;
2023-05-14 20:58:00 +00:00
let host = format!("{}", url.host().ok_or(Error::InvalidUri)?);
2023-05-14 20:44:26 +00:00
let digest_header = digest::generate_header(&body)
2023-05-14 20:58:00 +00:00
.map_err(|()| Error::Digest)?;
2022-12-11 00:07:39 +00:00
let mut req = http::Request::builder()
.method("POST")
2022-12-13 03:12:35 +00:00
.uri(uri)
2022-12-20 02:13:44 +00:00
.header("host", &host)
2022-12-11 00:07:39 +00:00
.header("content-type", "application/activity+json")
.header("date", httpdate::fmt_http_date(SystemTime::now()))
2022-12-11 00:07:39 +00:00
.header("digest", digest_header)
.body(body.as_ref().clone())?;
2022-12-20 02:13:44 +00:00
let t1 = Instant::now();
2022-12-19 23:15:00 +00:00
SigningConfig::new(RsaSha256, private_key, key_id)
2022-12-11 00:07:39 +00:00
.sign(&mut req)?;
2022-12-20 02:13:44 +00:00
let t2 = Instant::now();
2022-12-18 20:31:50 +00:00
let req: reqwest::Request = req.try_into()?;
let res = client.execute(req)
2022-12-11 00:07:39 +00:00
.await?;
2022-12-20 02:13:44 +00:00
let t3 = Instant::now();
2022-12-20 03:10:45 +00:00
histogram!("relay_http_request_duration", t2 - t1);
2022-12-13 03:12:35 +00:00
if res.status() >= StatusCode::OK && res.status() < StatusCode::MULTIPLE_CHOICES {
histogram!("relay_http_response_duration", t3 - t2, "res" => "ok");
2022-12-13 03:12:35 +00:00
Ok(())
} else {
histogram!("relay_http_response_duration", t3 - t2, "res" => "err");
2022-12-13 03:12:35 +00:00
let response = res.text().await?;
2023-05-14 20:58:00 +00:00
Err(Error::Response(response))
2022-12-13 03:12:35 +00:00
}
2022-12-11 00:07:39 +00:00
}