blob: 00b96f5e37dad4bacd21322b8096668a58ad630e [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//! Core components for signing API requests.
//!
//! This crate provides the foundational types and traits for the reqsign ecosystem.
//! It defines the core abstractions that enable flexible and extensible request signing.
//!
//! ## Overview
//!
//! The crate is built around several key concepts:
//!
//! - **Context**: A container that holds implementations for file reading, HTTP sending, and environment access
//! - **Traits**: Abstract interfaces for credential loading (`ProvideCredential`) and request signing (`SignRequest`)
//! - **Signer**: The main orchestrator that coordinates credential loading and request signing
//!
//! ## Example
//!
//! ```no_run
//! use reqsign_core::{Context, OsEnv, ProvideCredential, Result, SignRequest, Signer, SigningCredential};
//! use http::request::Parts;
//! use std::time::Duration;
//!
//! // Define your credential type
//! #[derive(Clone, Debug)]
//! struct MyCredential {
//! key: String,
//! secret: String,
//! }
//!
//! impl SigningCredential for MyCredential {
//! fn is_valid(&self) -> bool {
//! !self.key.is_empty() && !self.secret.is_empty()
//! }
//! }
//!
//! // Implement credential loader
//! #[derive(Debug)]
//! struct MyLoader;
//!
//! impl ProvideCredential for MyLoader {
//! type Credential = MyCredential;
//!
//! async fn provide_credential(&self, _: &Context) -> Result<Option<Self::Credential>> {
//! Ok(Some(MyCredential {
//! key: "my-access-key".to_string(),
//! secret: "my-secret-key".to_string(),
//! }))
//! }
//! }
//!
//! // Implement request builder
//! #[derive(Debug)]
//! struct MyBuilder;
//!
//! impl SignRequest for MyBuilder {
//! type Credential = MyCredential;
//!
//! async fn sign_request(
//! &self,
//! _ctx: &Context,
//! req: &mut Parts,
//! _cred: Option<&Self::Credential>,
//! _expires_in: Option<Duration>,
//! ) -> Result<()> {
//! // Add example header
//! req.headers.insert("x-custom-auth", "signed".parse()?);
//! Ok(())
//! }
//! }
//!
//! # async fn example() -> Result<()> {
//! # use reqsign_core::{FileRead, HttpSend};
//! # use bytes::Bytes;
//! #
//! # // Mock implementations for the example
//! # #[derive(Debug, Clone)]
//! # struct MockFileRead;
//! # impl FileRead for MockFileRead {
//! # async fn file_read(&self, _path: &str) -> Result<Vec<u8>> {
//! # Ok(vec![])
//! # }
//! # }
//! #
//! # #[derive(Debug, Clone)]
//! # struct MockHttpSend;
//! # impl HttpSend for MockHttpSend {
//! # async fn http_send(&self, _req: http::Request<Bytes>) -> Result<http::Response<Bytes>> {
//! # Ok(http::Response::builder().status(200).body(Bytes::new())?)
//! # }
//! # }
//! #
//! // Create a context with your implementations
//! let ctx = Context::new()
//! .with_file_read(MockFileRead)
//! .with_http_send(MockHttpSend)
//! .with_env(OsEnv);
//!
//! // Create a signer
//! let signer = Signer::new(ctx, MyLoader, MyBuilder);
//!
//! // Sign your requests
//! let mut parts = http::Request::builder()
//! .method("GET")
//! .uri("https://example.com")
//! .body(())
//! .unwrap()
//! .into_parts()
//! .0;
//!
//! signer.sign(&mut parts, None).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Traits
//!
//! This crate defines several important traits:
//!
//! - [`FileRead`]: For asynchronous file reading
//! - [`HttpSend`]: For sending HTTP requests
//! - [`Env`]: For environment variable access
//! - [`ProvideCredential`]: For loading credentials from various sources
//! - [`SignRequest`]: For building service-specific signing requests
//! - [`SigningCredential`]: For validating credentials
//!
//! ## Utilities
//!
//! The crate also provides utility modules:
//!
//! - [`hash`]: Cryptographic hashing utilities
//! - [`time`]: Time manipulation utilities
//! - [`utils`]: General utilities including data redaction
// Make sure all our public APIs have docs.
#![warn(missing_docs)]
/// Error types for reqsign operations
pub mod error;
mod futures_util;
pub mod hash;
#[cfg(all(not(target_arch = "wasm32"), feature = "jwt"))]
pub mod jwt;
pub mod time;
pub mod utils;
pub use error::{Error, ErrorKind, Result};
pub use futures_util::BoxedFuture;
pub use futures_util::MaybeSend;
mod context;
pub use context::CommandExecute;
pub use context::CommandExecuteDyn;
pub use context::CommandOutput;
pub use context::Context;
pub use context::Env;
pub use context::FileRead;
pub use context::FileReadDyn;
pub use context::HttpSend;
pub use context::HttpSendDyn;
pub use context::NoopCommandExecute;
pub use context::NoopEnv;
pub use context::NoopFileRead;
pub use context::NoopHttpSend;
pub use context::OsEnv;
pub use context::StaticEnv;
mod api;
pub use api::ProvideCredential;
pub use api::ProvideCredentialChain;
pub use api::ProvideCredentialDyn;
pub use api::SignRequest;
pub use api::SignRequestDyn;
pub use api::SigningCredential;
mod request;
pub use request::{SigningMethod, SigningRequest};
mod signer;
pub use signer::Signer;