cc_lb_plugin_api/
traits.rs1use std::sync::Arc;
4
5use async_trait::async_trait;
6use bytes::Bytes;
7use http::StatusCode;
8use uuid::Uuid;
9
10use crate::errors::{
11 DialectError, ObservabilityError, RouteError, RuntimeError, SignerError, UpstreamError,
12};
13use crate::types::{
14 ObserveEvent, PerCandidateReason, PluginManifest, Principal, RequestContext, RetryDecision,
15 RouteDecision, ShapedRequest, ShapedRequestBuilder, SignedRequest, SigningCapability, Upstream,
16 UpstreamCandidate,
17};
18
19#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct FilterOutput {
22 pub kept_upstream_ids: Vec<Uuid>,
24 pub reason: String,
26 pub per_candidate_reasons: Vec<PerCandidateReason>,
28}
29
30#[derive(Debug)]
32pub enum FilterError {
33 Runtime {
35 reason: String,
37 },
38 Trap {
40 reason: String,
42 },
43}
44
45impl std::fmt::Display for FilterError {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 match self {
48 FilterError::Runtime { reason } => write!(f, "filter runtime error: {}", reason),
49 FilterError::Trap { reason } => write!(f, "filter trap error: {}", reason),
50 }
51 }
52}
53
54impl std::error::Error for FilterError {}
55
56pub trait FilterPlugin: Send + Sync {
63 fn filter(
68 &self,
69 ctx: &RequestContext,
70 principal: &Principal,
71 candidates: &[UpstreamCandidate],
72 ) -> Result<FilterOutput, FilterError>;
73
74 fn plugin_id(&self) -> Uuid;
76
77 fn plugin_name(&self) -> &str;
79}
80
81#[deprecated(since = "0.2.0", note = "Use FilterPlugin via wire v3")]
83pub trait RouterPlugin: Send + Sync {
84 fn route(
90 &self,
91 ctx: &RequestContext,
92 principal: &Principal,
93 candidates: &[UpstreamCandidate],
94 ) -> Result<RouteDecision, RouteError>;
95}
96
97pub trait UpstreamDialect: Send + Sync {
99 fn shape(
101 &self,
102 ctx: &RequestContext,
103 upstream: &Upstream,
104 principal: &Principal,
105 builder: &mut ShapedRequestBuilder,
106 ) -> Result<ShapedRequest, DialectError>;
107
108 fn normalize_error(&self, status: StatusCode, body: &Bytes) -> Option<Bytes>;
110}
111
112#[async_trait]
114pub trait Signer: Send + Sync {
115 async fn sign(
117 &self,
118 shaped: ShapedRequest,
119 capability: &mut SigningCapability,
120 ) -> Result<SignedRequest, SignerError>;
121
122 async fn on_unauthorized(&self, err: &UpstreamError) -> RetryDecision;
124}
125
126#[async_trait]
128pub trait SignerFactory: Send + Sync {
129 async fn build(&self, upstream: &Upstream) -> Result<Arc<dyn Signer>, SignerError>;
131}
132
133pub trait ApiKeyAwareSignerFactory: Send + Sync {
135 fn with_router_choice(
137 &self,
138 api_key: String,
139 router_chosen_upstream_name: String,
140 ) -> Arc<dyn SignerFactory>;
141}
142
143pub trait ObservabilityHook: Send + Sync {
145 fn observe(&self, event: ObserveEvent) -> Result<(), ObservabilityError>;
147}
148
149pub trait PluginRuntime: Send + Sync {
151 #[allow(deprecated)]
153 fn instantiate_router(
154 &self,
155 manifest: &PluginManifest,
156 ) -> Result<Arc<dyn RouterPlugin>, RuntimeError>;
157
158 fn instantiate_dialect(
160 &self,
161 manifest: &PluginManifest,
162 ) -> Result<Arc<dyn UpstreamDialect>, RuntimeError>;
163
164 fn instantiate_signer_factory(
166 &self,
167 manifest: &PluginManifest,
168 ) -> Result<Arc<dyn SignerFactory>, RuntimeError>;
169
170 fn instantiate_observability(
172 &self,
173 manifest: &PluginManifest,
174 ) -> Result<Arc<dyn ObservabilityHook>, RuntimeError>;
175}