use base64::{engine::general_purpose::STANDARD, Engine};
use http_signature_normalization_reqwest::{digest::ring::Sha256, prelude::*};
use reqwest::{
header::{ACCEPT, USER_AGENT},
Client,
};
async fn request(config: Config) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let digest = Sha256::new();
let client = Client::new();
let request = client
.post("http://127.0.0.1:8010/")
.header(USER_AGENT, "Reqwest")
.header(ACCEPT, "text/plain")
.signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| {
println!("Signing String\n{}", s);
Ok(STANDARD.encode(s)) as Result<_, MyError>
})
.await?;
let body = client
.execute(request)
.await
.map_err(MyError::SendRequest)?
.bytes()
.await
.map_err(MyError::Body)?;
println!("{:?}", body);
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
std::env::set_var("RUST_LOG", "info");
pretty_env_logger::init();
tokio::spawn(async move {
let config = Config::default().require_header("accept");
request(config.clone()).await?;
request(config.mastodon_compat()).await
})
.await?
}
#[derive(Debug)]
pub enum MyError {
Convert(SignError),
SendRequest(reqwest::Error),
Body(reqwest::Error),
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Convert(_) => f.write_str("Failed to create signing string"),
Self::SendRequest(_) => f.write_str("Failed to send request"),
Self::Body(_) => f.write_str("Failed to retrieve response body"),
}
}
}
impl std::error::Error for MyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Convert(c) => Some(c),
Self::SendRequest(s) => Some(s),
Self::Body(b) => Some(b),
}
}
}
impl From<SignError> for MyError {
fn from(value: SignError) -> Self {
Self::Convert(value)
}
}
impl From<reqwest::Error> for MyError {
fn from(value: reqwest::Error) -> Self {
Self::SendRequest(value)
}
}