Skip to content

Commit

Permalink
validate extension for config
Browse files Browse the repository at this point in the history
  • Loading branch information
ermalkaleci committed Apr 11, 2024
1 parent 88765fd commit 2a06f13
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 33 deletions.
5 changes: 0 additions & 5 deletions .validateignore

This file was deleted.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ jsonrpc-pubsub = { version = "18.0.0" }
name = "bench"
harness = false

[features]
validate = []

[target.'cfg(tokio_unstable)'.dependencies]
console-subscriber = "0.2.0"

Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,21 @@ cargo bench --bench bench ws_round_trip

This middleware will intercept all method request/responses and compare the result directly with healthy endpoint responses.
This is useful for debugging to make sure the returned values are as expected.
You can use this by compiling with `validate` feature and enable validate middleware on your config file.
You can enable validate middleware on your config file.
```yml
middlewares:
methods:
- validate
```
NOTE: Keep in mind that if you place `validate` middleware before `inject_params` you may get false positive errors because the request will not be the same.

Use `.validateingore` file to list all the methods you want to ignore.
Ignored methods can be defined in extension config:
```yml
extensions:
validate:
ignore_methods:
- system_health
- system_name
- system_version
- author_pendingExtrinsics
```
2 changes: 2 additions & 0 deletions src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod merge_subscription;
pub mod rate_limit;
pub mod server;
pub mod telemetry;
pub mod validate;

#[async_trait]
pub trait Extension: Sized {
Expand Down Expand Up @@ -138,4 +139,5 @@ define_all_extensions! {
server: server::SubwayServerBuilder,
event_bus: event_bus::EventBus,
rate_limit: rate_limit::RateLimitBuilder,
validate: validate::Validate,
}
33 changes: 33 additions & 0 deletions src/extensions/validate/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use async_trait::async_trait;
use serde::Deserialize;

use super::{Extension, ExtensionRegistry};

#[derive(Default)]
pub struct Validate {
pub config: ValidateConfig,
}

#[derive(Deserialize, Default, Debug, Clone)]
pub struct ValidateConfig {
pub ignore_methods: Vec<String>,
}

#[async_trait]
impl Extension for Validate {
type Config = ValidateConfig;

async fn from_config(config: &Self::Config, _registry: &ExtensionRegistry) -> Result<Self, anyhow::Error> {
Ok(Self::new(config.clone()))
}
}

impl Validate {
pub fn new(config: ValidateConfig) -> Self {
Self { config }
}

pub fn ignore(&self, method: &String) -> bool {
self.config.ignore_methods.contains(method)
}
}
1 change: 0 additions & 1 deletion src/middlewares/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub async fn create_method_middleware(
"block_tag" => block_tag::BlockTagMiddleware::build(method, extensions).await,
"inject_params" => inject_params::InjectParamsMiddleware::build(method, extensions).await,
"delay" => delay::DelayMiddleware::build(method, extensions).await,
#[cfg(feature = "validate")]
"validate" => validate::ValidateMiddleware::build(method, extensions).await,
#[cfg(test)]
"crazy" => testing::CrazyMiddleware::build(method, extensions).await,
Expand Down
2 changes: 0 additions & 2 deletions src/middlewares/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ pub mod delay;
pub mod inject_params;
pub mod response;
pub mod upstream;

#[cfg(feature = "validate")]
pub mod validate;

#[cfg(test)]
Expand Down
27 changes: 7 additions & 20 deletions src/middlewares/methods/validate.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use async_trait::async_trait;
use std::sync::Arc;
use std::{fs::File, io::Read};

use crate::utils::errors;
use crate::{
extensions::client::Client,
extensions::{client::Client, validate::Validate},
middlewares::{CallRequest, CallResult, Middleware, MiddlewareBuilder, NextFn, RpcMethod},
utils::{TypeRegistry, TypeRegistryRef},
};

pub struct ValidateMiddleware {
validate: Arc<Validate>,
client: Arc<Client>,
ignore_methods: Vec<String>,
}

impl ValidateMiddleware {
pub fn new(client: Arc<Client>, ignore_methods: Vec<String>) -> Self {
Self { client, ignore_methods }
pub fn new(validate: Arc<Validate>, client: Arc<Client>) -> Self {
Self { validate, client }
}
}

Expand All @@ -26,26 +25,14 @@ impl MiddlewareBuilder<RpcMethod, CallRequest, CallResult> for ValidateMiddlewar
_method: &RpcMethod,
extensions: &TypeRegistryRef,
) -> Option<Box<dyn Middleware<CallRequest, CallResult>>> {
// read ignored methods from file
let mut ignore_methods = vec![];
if let Ok(mut file) = File::open(".validateignore") {
if let Err(err) = file.read_to_end(&mut ignore_methods) {
tracing::error!("Read .validateignore failed: {err:?}");
}
}
let ignore_methods = String::from_utf8(ignore_methods)
.unwrap_or_default()
.split('\n')
.map(|x| x.trim().to_string())
.filter(|x| !x.starts_with('#') && !x.starts_with("//")) // filter comments
.collect();
let validate = extensions.read().await.get::<Validate>().unwrap_or_default();

let client = extensions
.read()
.await
.get::<Client>()
.expect("Client extension not found");
Some(Box::new(ValidateMiddleware::new(client, ignore_methods)))
Some(Box::new(ValidateMiddleware::new(validate, client)))
}
}

Expand All @@ -61,7 +48,7 @@ impl Middleware<CallRequest, CallResult> for ValidateMiddleware {
let result = next(request.clone(), context).await;
let actual = result.clone();

if self.ignore_methods.contains(&request.method) {
if self.validate.ignore(&request.method) {
return result;
}

Expand Down

0 comments on commit 2a06f13

Please sign in to comment.