Skip to content

Commit 989f04f

Browse files
committed
[refactor] Extracting logic to Service trait and RateLimitService
Signed-off-by: dd di cesare <[email protected]>
1 parent c19464b commit 989f04f

File tree

4 files changed

+94
-21
lines changed

4 files changed

+94
-21
lines changed

src/filter/http_context.rs

+7-21
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
use crate::configuration::{FailureMode, FilterConfig};
2-
use crate::envoy::{RateLimitRequest, RateLimitResponse, RateLimitResponse_Code};
2+
use crate::envoy::{RateLimitResponse, RateLimitResponse_Code};
33
use crate::filter::http_context::TracingHeader::{Baggage, Traceparent, Tracestate};
44
use crate::policy::Policy;
5+
use crate::service::rate_limit::RateLimitService;
6+
use crate::service::Service;
57
use log::{debug, warn};
68
use protobuf::Message;
79
use proxy_wasm::traits::{Context, HttpContext};
810
use proxy_wasm::types::{Action, Bytes};
911
use std::rc::Rc;
10-
use std::time::Duration;
11-
12-
const RATELIMIT_SERVICE_NAME: &str = "envoy.service.ratelimit.v3.RateLimitService";
13-
const RATELIMIT_METHOD_NAME: &str = "ShouldRateLimit";
1412

1513
// tracing headers
1614
pub enum TracingHeader {
@@ -63,28 +61,16 @@ impl Filter {
6361
);
6462
return Action::Continue;
6563
}
66-
67-
let mut rl_req = RateLimitRequest::new();
68-
rl_req.set_domain(rlp.domain.clone());
69-
rl_req.set_hits_addend(1);
70-
rl_req.set_descriptors(descriptors);
71-
72-
let rl_req_serialized = Message::write_to_bytes(&rl_req).unwrap(); // TODO(rahulanand16nov): Error Handling
73-
7464
let rl_tracing_headers = self
7565
.tracing_headers
7666
.iter()
7767
.map(|(header, value)| (header.as_str(), value.as_slice()))
7868
.collect();
7969

80-
match self.dispatch_grpc_call(
81-
rlp.service.as_str(),
82-
RATELIMIT_SERVICE_NAME,
83-
RATELIMIT_METHOD_NAME,
84-
rl_tracing_headers,
85-
Some(&rl_req_serialized),
86-
Duration::from_secs(5),
87-
) {
70+
let rls = RateLimitService::new(rlp.service.as_str(), rl_tracing_headers);
71+
let message = RateLimitService::message(rlp.domain.clone(), descriptors);
72+
73+
match rls.send(message) {
8874
Ok(call_id) => {
8975
debug!(
9076
"#{} initiated gRPC call (id# {}) to Limitador",

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod filter;
55
mod glob;
66
mod policy;
77
mod policy_index;
8+
mod service;
89

910
#[cfg(test)]
1011
mod tests {

src/service.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub(crate) mod rate_limit;
2+
3+
use protobuf::reflect::ProtobufValue;
4+
use protobuf::{Message, RepeatedField};
5+
use proxy_wasm::types::Status;
6+
7+
pub trait Service<M: Message, V: ProtobufValue> {
8+
fn message(domain: String, descriptors: RepeatedField<V>) -> M;
9+
fn send(&self, message: M) -> Result<u32, Status>;
10+
}

src/service/rate_limit.rs

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::envoy::{RateLimitDescriptor, RateLimitRequest};
2+
use crate::service::Service;
3+
use protobuf::{Message, RepeatedField};
4+
use proxy_wasm::hostcalls::dispatch_grpc_call;
5+
use proxy_wasm::types::Status;
6+
use std::time::Duration;
7+
8+
const RATELIMIT_SERVICE_NAME: &str = "envoy.service.ratelimit.v3.RateLimitService";
9+
const RATELIMIT_METHOD_NAME: &str = "ShouldRateLimit";
10+
11+
pub struct RateLimitService<'a> {
12+
endpoint: String,
13+
metadata: Vec<(&'a str, &'a [u8])>,
14+
}
15+
16+
impl<'a> RateLimitService<'a> {
17+
pub fn new(endpoint: &str, metadata: Vec<(&'a str, &'a [u8])>) -> RateLimitService<'a> {
18+
Self {
19+
endpoint: String::from(endpoint),
20+
metadata,
21+
}
22+
}
23+
}
24+
25+
impl Service<RateLimitRequest, RateLimitDescriptor> for RateLimitService<'_> {
26+
fn message(
27+
domain: String,
28+
descriptors: RepeatedField<RateLimitDescriptor>,
29+
) -> RateLimitRequest {
30+
RateLimitRequest {
31+
domain,
32+
descriptors,
33+
hits_addend: 1,
34+
unknown_fields: Default::default(),
35+
cached_size: Default::default(),
36+
}
37+
}
38+
fn send(&self, message: RateLimitRequest) -> Result<u32, Status> {
39+
let msg = Message::write_to_bytes(&message).unwrap(); // TODO(didierofrivia): Error Handling
40+
dispatch_grpc_call(
41+
self.endpoint.as_str(),
42+
RATELIMIT_SERVICE_NAME,
43+
RATELIMIT_METHOD_NAME,
44+
self.metadata.clone(),
45+
Some(&msg),
46+
Duration::from_secs(5),
47+
)
48+
}
49+
}
50+
51+
#[cfg(test)]
52+
mod tests {
53+
use protobuf::{CachedSize, RepeatedField, UnknownFields};
54+
use crate::envoy::{RateLimitDescriptor, RateLimitDescriptor_Entry};
55+
use crate::service::rate_limit::RateLimitService;
56+
use crate::service::Service;
57+
58+
#[test]
59+
fn builds_message() {
60+
let domain = "rlp1";
61+
let mut field = RateLimitDescriptor::new();
62+
let mut entry = RateLimitDescriptor_Entry::new();
63+
entry.set_key("key1".to_string());
64+
entry.set_value("value1".to_string());
65+
field.set_entries(RepeatedField::from_vec(vec![entry]));
66+
let descriptors = RepeatedField::from_vec(vec![field]);
67+
68+
let msg = RateLimitService::message(domain.to_string(), descriptors.clone());
69+
70+
assert_eq!(msg.hits_addend, 1);
71+
assert_eq!(msg.domain, domain.to_string());
72+
assert_eq!(msg.descriptors , descriptors);
73+
assert_eq!(msg.unknown_fields , UnknownFields::default());
74+
assert_eq!(msg.cached_size , CachedSize::default());
75+
}
76+
}

0 commit comments

Comments
 (0)