1use chio_core_types::crypto::Keypair;
4use tower_layer::Layer;
5
6use crate::error::ChioTowerError;
7use crate::evaluator::{ChioEvaluator, ChioEvaluatorBuilder};
8use crate::service::{ChioService, DEFAULT_MAX_BODY_BYTES};
9
10#[derive(Clone)]
22pub struct ChioLayer {
23 evaluator: ChioEvaluator,
24 max_body_bytes: usize,
25}
26
27impl ChioLayer {
28 pub fn new(keypair: Keypair, policy_hash: String) -> Self {
32 Self {
33 evaluator: ChioEvaluator::new(keypair, policy_hash),
34 max_body_bytes: DEFAULT_MAX_BODY_BYTES,
35 }
36 }
37
38 pub fn new_ephemeral(keypair: Keypair, policy_hash: String) -> Self {
40 Self {
41 evaluator: ChioEvaluator::new_ephemeral(keypair, policy_hash),
42 max_body_bytes: DEFAULT_MAX_BODY_BYTES,
43 }
44 }
45
46 #[must_use]
48 pub fn builder(keypair: Keypair, policy_hash: String) -> ChioLayerBuilder {
49 ChioLayerBuilder {
50 inner: ChioEvaluator::builder(keypair, policy_hash),
51 max_body_bytes: DEFAULT_MAX_BODY_BYTES,
52 }
53 }
54
55 pub fn from_evaluator(evaluator: ChioEvaluator) -> Self {
57 Self {
58 evaluator,
59 max_body_bytes: DEFAULT_MAX_BODY_BYTES,
60 }
61 }
62
63 #[must_use]
67 pub fn with_max_body_bytes(mut self, max_body_bytes: usize) -> Self {
68 self.max_body_bytes = max_body_bytes;
69 self
70 }
71}
72
73impl<S> Layer<S> for ChioLayer {
74 type Service = ChioService<S>;
75
76 fn layer(&self, inner: S) -> Self::Service {
77 ChioService::new(inner, self.evaluator.clone()).with_max_body_bytes(self.max_body_bytes)
78 }
79}
80
81pub struct ChioLayerBuilder {
84 inner: ChioEvaluatorBuilder,
85 max_body_bytes: usize,
86}
87
88impl ChioLayerBuilder {
89 #[must_use]
90 pub fn receipt_store(mut self, store: std::sync::Arc<dyn chio_kernel::ReceiptStore>) -> Self {
91 self.inner = self.inner.receipt_store(store);
92 self
93 }
94
95 #[must_use]
96 pub fn revocation_store(
97 mut self,
98 store: std::sync::Arc<dyn chio_kernel::RevocationStore>,
99 ) -> Self {
100 self.inner = self.inner.revocation_store(store);
101 self
102 }
103
104 #[must_use]
105 pub fn allow_ephemeral(mut self, allow: bool) -> Self {
106 self.inner = self.inner.allow_ephemeral(allow);
107 self
108 }
109
110 #[must_use]
111 pub fn with_max_body_bytes(mut self, max_body_bytes: usize) -> Self {
112 self.max_body_bytes = max_body_bytes;
113 self
114 }
115
116 pub fn build(self) -> Result<ChioLayer, ChioTowerError> {
117 Ok(ChioLayer {
118 evaluator: self.inner.build()?,
119 max_body_bytes: self.max_body_bytes,
120 })
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use bytes::Bytes;
128 use http_body_util::Full;
129
130 #[test]
131 fn layer_creates_service() {
132 let keypair = Keypair::generate();
133 let layer = ChioLayer::new_ephemeral(keypair, "test-policy".to_string());
134
135 let _service = layer.layer(tower::service_fn(
137 |_req: http::Request<Full<Bytes>>| async {
138 Ok::<_, std::convert::Infallible>(http::Response::new(Full::new(Bytes::new())))
139 },
140 ));
141 }
142}