Skip to content

Commit cebb46d

Browse files
Merge pull request #66 from Kuadrant/refactoring-2
Refactoring for external auth. Vol II
2 parents c19464b + 3011881 commit cebb46d

File tree

4 files changed

+131
-27
lines changed

4 files changed

+131
-27
lines changed

src/filter/http_context.rs

+9-27
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
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
14+
#[derive(Clone)]
1615
pub enum TracingHeader {
1716
Traceparent,
1817
Tracestate,
@@ -24,7 +23,7 @@ impl TracingHeader {
2423
[Traceparent, Tracestate, Baggage]
2524
}
2625

27-
fn as_str(&self) -> &'static str {
26+
pub fn as_str(&self) -> &'static str {
2827
match self {
2928
Traceparent => "traceparent",
3029
Tracestate => "tracestate",
@@ -64,27 +63,10 @@ impl Filter {
6463
return Action::Continue;
6564
}
6665

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-
74-
let rl_tracing_headers = self
75-
.tracing_headers
76-
.iter()
77-
.map(|(header, value)| (header.as_str(), value.as_slice()))
78-
.collect();
79-
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-
) {
66+
let rls = RateLimitService::new(rlp.service.as_str(), self.tracing_headers.clone());
67+
let message = RateLimitService::message(rlp.domain.clone(), descriptors);
68+
69+
match rls.send(message) {
8870
Ok(call_id) => {
8971
debug!(
9072
"#{} 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

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

src/service/rate_limit.rs

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use crate::envoy::{RateLimitDescriptor, RateLimitRequest};
2+
use crate::filter::http_context::TracingHeader;
3+
use crate::service::Service;
4+
use protobuf::{Message, RepeatedField};
5+
use proxy_wasm::hostcalls::dispatch_grpc_call;
6+
use proxy_wasm::types::{Bytes, Status};
7+
use std::time::Duration;
8+
9+
const RATELIMIT_SERVICE_NAME: &str = "envoy.service.ratelimit.v3.RateLimitService";
10+
const RATELIMIT_METHOD_NAME: &str = "ShouldRateLimit";
11+
pub struct RateLimitService {
12+
endpoint: String,
13+
tracing_headers: Vec<(TracingHeader, Bytes)>,
14+
}
15+
16+
impl RateLimitService {
17+
pub fn new(endpoint: &str, metadata: Vec<(TracingHeader, Bytes)>) -> RateLimitService {
18+
Self {
19+
endpoint: String::from(endpoint),
20+
tracing_headers: metadata,
21+
}
22+
}
23+
pub fn message(
24+
domain: String,
25+
descriptors: RepeatedField<RateLimitDescriptor>,
26+
) -> RateLimitRequest {
27+
RateLimitRequest {
28+
domain,
29+
descriptors,
30+
hits_addend: 1,
31+
unknown_fields: Default::default(),
32+
cached_size: Default::default(),
33+
}
34+
}
35+
}
36+
37+
fn grpc_call(
38+
upstream_name: &str,
39+
initial_metadata: Vec<(&str, &[u8])>,
40+
message: RateLimitRequest,
41+
) -> Result<u32, Status> {
42+
let msg = Message::write_to_bytes(&message).unwrap(); // TODO(didierofrivia): Error Handling
43+
dispatch_grpc_call(
44+
upstream_name,
45+
RATELIMIT_SERVICE_NAME,
46+
RATELIMIT_METHOD_NAME,
47+
initial_metadata,
48+
Some(&msg),
49+
Duration::from_secs(5),
50+
)
51+
}
52+
53+
impl Service<RateLimitRequest> for RateLimitService {
54+
fn send(&self, message: RateLimitRequest) -> Result<u32, Status> {
55+
grpc_call(
56+
self.endpoint.as_str(),
57+
self.tracing_headers
58+
.iter()
59+
.map(|(header, value)| (header.as_str(), value.as_slice()))
60+
.collect(),
61+
message,
62+
)
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use crate::envoy::{RateLimitDescriptor, RateLimitDescriptor_Entry, RateLimitRequest};
69+
use crate::service::rate_limit::RateLimitService;
70+
//use crate::service::Service;
71+
use protobuf::{CachedSize, RepeatedField, UnknownFields};
72+
//use proxy_wasm::types::Status;
73+
//use crate::filter::http_context::{Filter};
74+
75+
fn build_message() -> RateLimitRequest {
76+
let domain = "rlp1";
77+
let mut field = RateLimitDescriptor::new();
78+
let mut entry = RateLimitDescriptor_Entry::new();
79+
entry.set_key("key1".to_string());
80+
entry.set_value("value1".to_string());
81+
field.set_entries(RepeatedField::from_vec(vec![entry]));
82+
let descriptors = RepeatedField::from_vec(vec![field]);
83+
84+
RateLimitService::message(domain.to_string(), descriptors.clone())
85+
}
86+
#[test]
87+
fn builds_correct_message() {
88+
let msg = build_message();
89+
90+
assert_eq!(msg.hits_addend, 1);
91+
assert_eq!(msg.domain, "rlp1".to_string());
92+
assert_eq!(msg.descriptors.first().unwrap().entries[0].key, "key1");
93+
assert_eq!(msg.descriptors.first().unwrap().entries[0].value, "value1");
94+
assert_eq!(msg.unknown_fields, UnknownFields::default());
95+
assert_eq!(msg.cached_size, CachedSize::default());
96+
}
97+
/*#[test]
98+
fn sends_message() {
99+
let msg = build_message();
100+
let metadata = vec![("header-1", "value-1".as_bytes())];
101+
let rls = RateLimitService::new("limitador-cluster", metadata);
102+
103+
// TODO(didierofrivia): When we have a grpc response type, assert the async response
104+
}
105+
106+
fn grpc_call(
107+
_upstream_name: &str,
108+
_initial_metadata: Vec<(&str, &[u8])>,
109+
_message: RateLimitRequest,
110+
) -> Result<u32, Status> {
111+
Ok(1)
112+
} */
113+
}

0 commit comments

Comments
 (0)