Update versions and examples

This commit is contained in:
Aode (Lion) 2022-03-08 12:00:17 -06:00
parent 2d13b04199
commit 02b85e55d8
3 changed files with 99 additions and 71 deletions

View file

@ -1,7 +1,7 @@
[package]
name = "http-signature-normalization-actix"
description = "An HTTP Signatures library that leaves the signing to you"
version = "0.6.0"
version = "0.6.1"
authors = ["asonix <asonix@asonix.dog>"]
license-file = "LICENSE"
readme = "README.md"

View file

@ -13,72 +13,49 @@ This crate provides extensions the ClientRequest type from Actix Web, and provid
#### First, add this crate to your dependencies
```toml
actix-rt = "2.0.2"
actix-web = "4.0.0-beta.3"
actix-rt = "2.6.0"
actix-web = "4.0.0"
thiserror = "0.1"
http-signature-normalization-actix = { version = "0.5.0-beta.2", default-features = false, features = ["sha-2"] }
http-signature-normalization-actix = { version = "0.6.0", default-features = false, features = ["sha-2"] }
sha2 = "0.9"
```
#### Then, use it in your client
```rust
use actix_web::client::Client;
use http_signature_normalization_actix::prelude::*;
use sha2::{Digest, Sha256};
#[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::default();
let mut digest = Sha256::new();
async fn request(config: Config) -> Result<(), Box<dyn std::error::Error>> {
let digest = Sha256::new();
let mut response = Client::default()
.post("http://127.0.0.1:8010/")
.header("User-Agent", "Actix Web")
.authorization_signature_with_digest(&config, "my-key-id", &mut digest, "My request body", |s| {
.append_header(("User-Agent", "Actix Web"))
.append_header(("Accept", "text/plain"))
.insert_header(actix_web::http::header::Date(SystemTime::now().into()))
.signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| {
info!("Signing String\n{}", s);
Ok(base64::encode(s)) as Result<_, MyError>
})?
})
.await?
.send()
.await
.map_err(|e| {
eprintln!("Error, {}", e);
error!("Error, {}", e);
MyError::SendRequest
})?;
let body = response.body().await.map_err(|e| {
eprintln!("Error, {}", e);
error!("Error, {}", e);
MyError::Body
})?;
println!("{:?}", body);
info!("{:?}", body);
Ok(())
}
#[derive(Debug, thiserror::Error)]
pub enum MyError {
#[error("Failed to read header, {0}")]
Convert(#[from] ToStrError),
#[error("Failed to create header, {0}")]
Header(#[from] InvalidHeaderValue),
#[error("Failed to send request")]
SendRequest,
#[error("Failed to retrieve request body")]
Body,
}
```
#### Or, use it in your server
```rust
use actix_web::{http::StatusCode, web, App, HttpResponse, HttpServer, ResponseError};
use futures::future::{err, ok, Ready};
use http_signature_normalization_actix::prelude::*;
use sha2::{Digest, Sha256};
#[derive(Clone, Debug)]
struct MyVerify;
@ -95,39 +72,52 @@ impl SignatureVerify for MyVerify {
) -> Self::Future {
match algorithm {
Some(Algorithm::Hs2019) => (),
_ => return err(MyError::Algorithm),
_ => return ready(Err(MyError::Algorithm)),
};
if key_id != "my-key-id" {
return err(MyError::Key);
return ready(Err(MyError::Key));
}
let decoded = match base64::decode(&signature) {
Ok(decoded) => decoded,
Err(_) => return err(MyError::Decode),
Err(_) => return ready(Err(MyError::Decode)),
};
ok(decoded == signing_string.as_bytes())
info!("Signing String\n{}", signing_string);
ready(Ok(decoded == signing_string.as_bytes()))
}
}
async fn index((_, sig_verified): (DigestVerified, SignatureVerified)) -> &'static str {
println!("Signature verified for {}", sig_verified.key_id());
async fn index(
(_, sig_verified): (DigestVerified, SignatureVerified),
req: HttpRequest,
_body: web::Bytes,
) -> &'static str {
info!("Verified request for {}", sig_verified.key_id());
info!("{:?}", req);
"Eyyyyup"
}
#[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::default();
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let subscriber = tracing_subscriber::Registry::default()
.with(env_filter)
.with(ErrorLayer::default())
.with(tracing_subscriber::fmt::layer());
tracing::subscriber::set_global_default(subscriber)?;
let config = Config::default().require_header("accept").require_digest();
HttpServer::new(move || {
App::new()
.wrap(VerifyDigest::new(Sha256::new()).optional())
.wrap(
VerifySignature::new(MyVerify, config.clone())
.authorization()
.optional(),
)
.wrap(VerifySignature::new(MyVerify, config.clone()).optional())
.wrap(TracingLogger::default())
.route("/", web::post().to(index))
})
.bind("127.0.0.1:8010")?
@ -139,7 +129,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("Failed to verify, {}", _0)]
#[error("Failed to verify, {0}")]
Verify(#[from] PrepareVerifyError),
#[error("Unsupported algorithm")]

View file

@ -8,10 +8,14 @@
//!
//! ### Use it in a server
//! ```rust,ignore
//! use actix_web::{http::StatusCode, web, App, HttpResponse, HttpServer, ResponseError};
//! use actix_web::{http::StatusCode, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError};
//! use http_signature_normalization_actix::prelude::*;
//! use sha2::{Digest, Sha256};
//! use std::future::{ready, Ready};
//! use tracing::info;
//! use tracing_actix_web::TracingLogger;
//! use tracing_error::ErrorLayer;
//! use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
//!
//! #[derive(Clone, Debug)]
//! struct MyVerify;
@ -41,27 +45,40 @@
//! Err(_) => return ready(Err(MyError::Decode)),
//! };
//!
//! info!("Signing String\n{}", signing_string);
//!
//! ready(Ok(decoded == signing_string.as_bytes()))
//! }
//! }
//!
//! async fn index((_, sig_verified): (DigestVerified, SignatureVerified)) -> &'static str {
//! println!("Signature verified for {}", sig_verified.key_id());
//! async fn index(
//! (_, sig_verified): (DigestVerified, SignatureVerified),
//! req: HttpRequest,
//! _body: web::Bytes,
//! ) -> &'static str {
//! info!("Verified request for {}", sig_verified.key_id());
//! info!("{:?}", req);
//! "Eyyyyup"
//! }
//!
//! #[actix_rt::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let config = Config::default();
//! let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
//!
//! let subscriber = tracing_subscriber::Registry::default()
//! .with(env_filter)
//! .with(ErrorLayer::default())
//! .with(tracing_subscriber::fmt::layer());
//!
//! tracing::subscriber::set_global_default(subscriber)?;
//!
//! let config = Config::default().require_header("accept").require_digest();
//!
//! HttpServer::new(move || {
//! App::new()
//! .wrap(VerifyDigest::new(Sha256::new()).optional())
//! .wrap(
//! VerifySignature::new(MyVerify, config.clone())
//! .authorization()
//! .optional(),
//! )
//! .wrap(VerifySignature::new(MyVerify, config.clone()).optional())
//! .wrap(TracingLogger::default())
//! .route("/", web::post().to(index))
//! })
//! .bind("127.0.0.1:8010")?
@ -73,7 +90,7 @@
//!
//! #[derive(Debug, thiserror::Error)]
//! enum MyError {
//! #[error("Failed to verify, {}", _0)]
//! #[error("Failed to verify, {0}")]
//! Verify(#[from] PrepareVerifyError),
//!
//! #[error("Unsupported algorithm")]
@ -103,34 +120,55 @@
//! use awc::Client;
//! use http_signature_normalization_actix::prelude::*;
//! use sha2::{Digest, Sha256};
//! use std::time::SystemTime;
//! use tracing::{error, info};
//! use tracing_error::ErrorLayer;
//! use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
//!
//! #[actix_rt::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let config = Config::default();
//! async fn request(config: Config) -> Result<(), Box<dyn std::error::Error>> {
//! let digest = Sha256::new();
//!
//! let mut response = Client::default()
//! .post("http://127.0.0.1:8010/")
//! .header("User-Agent", "Actix Web")
//! .set(actix_web::http::header::Date(SystemTime::now().into()))
//! .append_header(("User-Agent", "Actix Web"))
//! .append_header(("Accept", "text/plain"))
//! .insert_header(actix_web::http::header::Date(SystemTime::now().into()))
//! .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| {
//! println!("Signing String\n{}", s);
//! info!("Signing String\n{}", s);
//! Ok(base64::encode(s)) as Result<_, MyError>
//! })
//! .await?
//! .send()
//! .await
//! .map_err(|e| {
//! eprintln!("Error, {}", e);
//! error!("Error, {}", e);
//! MyError::SendRequest
//! })?;
//!
//! let body = response.body().await.map_err(|e| {
//! eprintln!("Error, {}", e);
//! error!("Error, {}", e);
//! MyError::Body
//! })?;
//!
//! println!("{:?}", body);
//! info!("{:?}", body);
//! Ok(())
//! }
//!
//! #[actix_rt::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
//!
//! let subscriber = tracing_subscriber::Registry::default()
//! .with(env_filter)
//! .with(ErrorLayer::default())
//! .with(tracing_subscriber::fmt::layer());
//!
//! tracing::subscriber::set_global_default(subscriber)?;
//!
//! let config = Config::default().require_header("accept").require_digest();
//!
//! request(config.clone()).await?;
//! request(config.mastodon_compat()).await?;
//! Ok(())
//! }
//!
@ -154,7 +192,7 @@
//!
//! impl From<JoinError> for MyError {
//! fn from(_: JoinError) -> Self {
//! MyError::Canceled,
//! MyError::Canceled
//! }
//! }
//! ```