use std::sync::Arc;
use async_trait::async_trait;
use bytes::Bytes;
use http::StatusCode;
use uuid::Uuid;
use crate::errors::{
DialectError, ObservabilityError, RouteError, RuntimeError, SignerError, UpstreamError,
};
use crate::types::{
ObserveEvent, PerCandidateReason, PluginManifest, Principal, RequestContext, RetryDecision,
RouteDecision, ShapedRequest, ShapedRequestBuilder, SignedRequest, SigningCapability, Upstream,
UpstreamCandidate,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FilterOutput {
pub kept_upstream_ids: Vec<Uuid>,
pub reason: String,
pub per_candidate_reasons: Vec<PerCandidateReason>,
}
#[derive(Debug)]
pub enum FilterError {
Runtime {
reason: String,
},
Trap {
reason: String,
},
}
impl std::fmt::Display for FilterError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FilterError::Runtime { reason } => write!(f, "filter runtime error: {}", reason),
FilterError::Trap { reason } => write!(f, "filter trap error: {}", reason),
}
}
}
impl std::error::Error for FilterError {}
pub trait FilterPlugin: Send + Sync {
fn filter(
&self,
ctx: &RequestContext,
principal: &Principal,
candidates: &[UpstreamCandidate],
) -> Result<FilterOutput, FilterError>;
fn plugin_id(&self) -> Uuid;
fn plugin_name(&self) -> &str;
}
#[deprecated(since = "0.2.0", note = "Use FilterPlugin via wire v3")]
pub trait RouterPlugin: Send + Sync {
fn route(
&self,
ctx: &RequestContext,
principal: &Principal,
candidates: &[UpstreamCandidate],
) -> Result<RouteDecision, RouteError>;
}
pub trait UpstreamDialect: Send + Sync {
fn shape(
&self,
ctx: &RequestContext,
upstream: &Upstream,
principal: &Principal,
builder: &mut ShapedRequestBuilder,
) -> Result<ShapedRequest, DialectError>;
fn normalize_error(&self, status: StatusCode, body: &Bytes) -> Option<Bytes>;
}
#[async_trait]
pub trait Signer: Send + Sync {
async fn sign(
&self,
shaped: ShapedRequest,
capability: &mut SigningCapability,
) -> Result<SignedRequest, SignerError>;
async fn on_unauthorized(&self, err: &UpstreamError) -> RetryDecision;
}
#[async_trait]
pub trait SignerFactory: Send + Sync {
async fn build(&self, upstream: &Upstream) -> Result<Arc<dyn Signer>, SignerError>;
}
pub trait ApiKeyAwareSignerFactory: Send + Sync {
fn with_router_choice(
&self,
api_key: String,
router_chosen_upstream_name: String,
) -> Arc<dyn SignerFactory>;
}
pub trait ObservabilityHook: Send + Sync {
fn observe(&self, event: ObserveEvent) -> Result<(), ObservabilityError>;
}
pub trait PluginRuntime: Send + Sync {
#[allow(deprecated)]
fn instantiate_router(
&self,
manifest: &PluginManifest,
) -> Result<Arc<dyn RouterPlugin>, RuntimeError>;
fn instantiate_dialect(
&self,
manifest: &PluginManifest,
) -> Result<Arc<dyn UpstreamDialect>, RuntimeError>;
fn instantiate_signer_factory(
&self,
manifest: &PluginManifest,
) -> Result<Arc<dyn SignerFactory>, RuntimeError>;
fn instantiate_observability(
&self,
manifest: &PluginManifest,
) -> Result<Arc<dyn ObservabilityHook>, RuntimeError>;
}