forest/rpc/
validation_layer.rs1use futures::future::Either;
5use jsonrpsee::MethodResponse;
6use jsonrpsee::core::middleware::{Batch, BatchEntry, BatchEntryErr, Notification};
7use jsonrpsee::server::middleware::rpc::RpcServiceT;
8use jsonrpsee::types::ErrorObject;
9use tower::Layer;
10
11use super::json_validator;
12
13const INVALID_REQUEST: i32 = -32600;
15
16#[derive(Clone, Default)]
18pub(super) struct JsonValidationLayer;
19
20impl<S> Layer<S> for JsonValidationLayer {
21 type Service = Validation<S>;
22
23 fn layer(&self, service: S) -> Self::Service {
24 Validation { service }
25 }
26}
27
28#[derive(Clone)]
29pub(super) struct Validation<S> {
30 service: S,
31}
32
33impl<S> Validation<S> {
34 fn validation_enabled() -> bool {
35 json_validator::is_strict_mode()
36 }
37
38 fn validate_params(params_str: &str) -> Result<(), String> {
39 json_validator::validate_json_for_duplicates(params_str)
40 }
41}
42
43impl<S> RpcServiceT for Validation<S>
44where
45 S: RpcServiceT<MethodResponse = MethodResponse, NotificationResponse = MethodResponse>
46 + Send
47 + Sync
48 + Clone
49 + 'static,
50{
51 type MethodResponse = S::MethodResponse;
52 type NotificationResponse = S::NotificationResponse;
53 type BatchResponse = S::BatchResponse;
54
55 fn call<'a>(
56 &self,
57 req: jsonrpsee::types::Request<'a>,
58 ) -> impl Future<Output = Self::MethodResponse> + Send + 'a {
59 if !Self::validation_enabled() {
60 return Either::Left(self.service.call(req));
61 }
62
63 if let Err(e) =
64 json_validator::validate_json_for_duplicates(req.params().as_str().unwrap_or("[]"))
65 {
66 let err = ErrorObject::owned(INVALID_REQUEST, e, None::<()>);
67 return Either::Right(async move { MethodResponse::error(req.id(), err) });
68 }
69
70 Either::Left(self.service.call(req))
71 }
72
73 fn batch<'a>(
74 &self,
75 mut batch: Batch<'a>,
76 ) -> impl Future<Output = Self::BatchResponse> + Send + 'a {
77 let service = self.service.clone();
78
79 async move {
80 if !Self::validation_enabled() {
81 return service.batch(batch).await;
82 }
83
84 for entry in batch.iter_mut() {
85 if let Ok(batch_entry) = entry {
86 let params_str = match batch_entry.params() {
87 Some(p) => p.as_ref().get(),
88 None => continue,
89 };
90
91 if let Err(e) = Self::validate_params(params_str) {
92 match batch_entry {
93 BatchEntry::Call(req) => {
94 let err = ErrorObject::owned(INVALID_REQUEST, e, None::<()>);
95 let err_entry = BatchEntryErr::new(req.id().clone(), err);
96 *entry = Err(err_entry);
97 }
98 BatchEntry::Notification(_notif) => {
99 let err = ErrorObject::owned(INVALID_REQUEST, e, None::<()>);
100 let err_entry = BatchEntryErr::new(jsonrpsee::types::Id::Null, err);
101 *entry = Err(err_entry);
102 }
103 }
104 }
105 }
106 }
107
108 service.batch(batch).await
109 }
110 }
111
112 fn notification<'a>(
113 &self,
114 n: Notification<'a>,
115 ) -> impl Future<Output = Self::NotificationResponse> + Send + 'a {
116 let service = self.service.clone();
117
118 async move {
119 if !Self::validation_enabled() {
120 return service.notification(n).await;
121 }
122
123 let params_str = match n.params() {
124 Some(p) => p.as_ref().get(),
125 None => return service.notification(n).await,
126 };
127
128 if let Err(e) = Self::validate_params(params_str) {
129 let err = ErrorObject::owned(INVALID_REQUEST, e, None::<()>);
130 return MethodResponse::error(jsonrpsee::types::Id::Null, err);
131 }
132
133 service.notification(n).await
134 }
135 }
136}