mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-11-21 17:00:59 +00:00
Update versions and examples
This commit is contained in:
parent
2d13b04199
commit
02b85e55d8
3 changed files with 99 additions and 71 deletions
|
@ -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"
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
|
Loading…
Reference in a new issue