reifydb_sub_server/
interceptor.rs1use std::{collections::HashMap, future::Future, panic::AssertUnwindSafe, pin::Pin, sync::Arc};
5
6use futures_util::FutureExt;
7use reifydb_core::{actors::server::Operation, metric::ExecutionMetrics};
8use reifydb_type::{params::Params, value::identity::IdentityId};
9use tracing::error;
10
11use crate::execute::ExecuteError;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
15pub enum Protocol {
16 #[default]
17 Http,
18 WebSocket,
19 Grpc,
20}
21
22#[derive(Debug, Clone, Default)]
32pub struct RequestMetadata {
33 headers: HashMap<String, String>,
34 protocol: Protocol,
35}
36
37impl RequestMetadata {
38 pub fn new(protocol: Protocol) -> Self {
40 Self {
41 headers: HashMap::new(),
42 protocol,
43 }
44 }
45
46 pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
48 self.headers.insert(key.into().to_ascii_lowercase(), value.into());
49 }
50
51 pub fn get(&self, key: &str) -> Option<&str> {
53 self.headers.get(&key.to_ascii_lowercase()).map(|s| s.as_str())
54 }
55
56 pub fn protocol(&self) -> Protocol {
58 self.protocol
59 }
60
61 pub fn headers(&self) -> &HashMap<String, String> {
63 &self.headers
64 }
65}
66
67pub struct RequestContext {
72 pub identity: IdentityId,
74 pub operation: Operation,
76 pub rql: String,
78 pub params: Params,
80 pub metadata: RequestMetadata,
82}
83
84pub struct ResponseContext {
86 pub identity: IdentityId,
88 pub operation: Operation,
90 pub rql: String,
92 pub metrics: ExecutionMetrics,
94 pub params: Params,
96 pub metadata: RequestMetadata,
98 pub result: Result<usize, String>,
100}
101
102pub trait RequestInterceptor: Send + Sync + 'static {
110 fn pre_execute<'a>(
116 &'a self,
117 ctx: &'a mut RequestContext,
118 ) -> Pin<Box<dyn Future<Output = Result<(), ExecuteError>> + Send + 'a>>;
119
120 fn post_execute<'a>(&'a self, ctx: &'a ResponseContext) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
125}
126
127#[derive(Clone)]
129pub struct RequestInterceptorChain {
130 interceptors: Arc<Vec<Arc<dyn RequestInterceptor>>>,
131}
132
133impl RequestInterceptorChain {
134 pub fn new(interceptors: Vec<Arc<dyn RequestInterceptor>>) -> Self {
135 Self {
136 interceptors: Arc::new(interceptors),
137 }
138 }
139
140 pub fn empty() -> Self {
141 Self {
142 interceptors: Arc::new(Vec::new()),
143 }
144 }
145
146 pub fn is_empty(&self) -> bool {
147 self.interceptors.is_empty()
148 }
149
150 pub async fn pre_execute(&self, ctx: &mut RequestContext) -> Result<(), ExecuteError> {
153 for interceptor in self.interceptors.iter() {
154 interceptor.pre_execute(ctx).await?;
155 }
156 Ok(())
157 }
158
159 pub async fn post_execute(&self, ctx: &ResponseContext) {
164 for interceptor in self.interceptors.iter().rev() {
165 if let Err(panic) = AssertUnwindSafe(interceptor.post_execute(ctx)).catch_unwind().await {
166 let msg = panic
167 .downcast_ref::<&str>()
168 .copied()
169 .or_else(|| panic.downcast_ref::<String>().map(|s| s.as_str()))
170 .unwrap_or("unknown panic");
171 error!("post_execute interceptor panicked: {}", msg);
172 }
173 }
174 }
175}
176
177impl Default for RequestInterceptorChain {
178 fn default() -> Self {
179 Self::empty()
180 }
181}