Skip to content

Commit

Permalink
Genericise the service to send any type of M
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Cattermole <[email protected]>
  • Loading branch information
adam-cattermole committed Aug 21, 2024
1 parent 9a1560b commit 98b9206
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 79 deletions.
93 changes: 90 additions & 3 deletions src/service.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,96 @@
pub(crate) mod auth;
pub(crate) mod rate_limit;

use crate::configuration::ExtensionType;

Check failure on line 4 in src/service.rs

View workflow job for this annotation

GitHub Actions / Check

unresolved import `crate::configuration::ExtensionType`

Check failure on line 4 in src/service.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unresolved import `crate::configuration::ExtensionType`

Check failure on line 4 in src/service.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unresolved import `crate::configuration::ExtensionType`

Check failure on line 4 in src/service.rs

View workflow job for this annotation

GitHub Actions / Clippy

unresolved import `crate::configuration::ExtensionType`
use crate::filter::http_context::TracingHeader;
use crate::service::auth::{AUTH_METHOD_NAME, AUTH_SERVICE_NAME};
use crate::service::rate_limit::{RATELIMIT_METHOD_NAME, RATELIMIT_SERVICE_NAME};
use protobuf::Message;
use proxy_wasm::types::Status;
use proxy_wasm::hostcalls;
use proxy_wasm::hostcalls::dispatch_grpc_call;
use proxy_wasm::types::{Bytes, MapType, Status};
use std::cell::OnceCell;
use std::time::Duration;

pub trait Service<M: Message> {
fn send(&self, message: M) -> Result<u32, Status>;
pub struct GrpcServiceHandler {
endpoint: String,
service_name: String,
method_name: String,
tracing_headers: Vec<(TracingHeader, Bytes)>,
}

impl GrpcServiceHandler {
fn new_base(
endpoint: String,
service_name: &str,
method_name: &str,
tracing_headers: Vec<(TracingHeader, Bytes)>,
) -> Self {
Self {
endpoint: endpoint.to_owned(),
service_name: service_name.to_owned(),
method_name: method_name.to_owned(),
tracing_headers,
}
}

pub fn new(
extension_type: ExtensionType,
endpoint: String,
tracing_headers: Vec<(TracingHeader, Bytes)>,
) -> Self {
match extension_type {
ExtensionType::Auth => Self::new_base(
endpoint,
AUTH_SERVICE_NAME,
AUTH_METHOD_NAME,
tracing_headers,
),
ExtensionType::RateLimit => Self::new_base(
endpoint,
RATELIMIT_SERVICE_NAME,
RATELIMIT_METHOD_NAME,
tracing_headers,
),
}
}

pub fn send<M: Message>(&self, message: M) -> Result<u32, Status> {
let msg = Message::write_to_bytes(&message).unwrap();
let metadata = self
.tracing_headers
.iter()
.map(|(header, value)| (header.as_str(), value.as_slice()))
.collect();

dispatch_grpc_call(
self.endpoint.as_str(),
self.service_name.as_str(),
self.method_name.as_str(),
metadata,
Some(&msg),
Duration::from_secs(5),
)
}
}

pub struct TracingHeaderResolver {
tracing_headers: OnceCell<Vec<(TracingHeader, Bytes)>>,
}

impl TracingHeaderResolver {
pub fn get(&self) -> &Vec<(TracingHeader, Bytes)> {
self.tracing_headers.get_or_init(|| {
let mut headers = Vec::new();
for header in TracingHeader::all() {

Check failure on line 85 in src/service.rs

View workflow job for this annotation

GitHub Actions / Check

associated function `all` is private

Check failure on line 85 in src/service.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

associated function `all` is private

Check failure on line 85 in src/service.rs

View workflow job for this annotation

GitHub Actions / Test Suite

associated function `all` is private

Check failure on line 85 in src/service.rs

View workflow job for this annotation

GitHub Actions / Clippy

associated function `all` is private
if let Some(value) =
hostcalls::get_map_value_bytes(MapType::HttpRequestHeaders, header.as_str())
.unwrap()
{
headers.push((header, value));
}
}
headers
})
}
}
43 changes: 5 additions & 38 deletions src/service/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,20 @@ use crate::envoy::{
Address, AttributeContext, AttributeContext_HttpRequest, AttributeContext_Peer,
AttributeContext_Request, CheckRequest, Metadata, SocketAddress,
};
use crate::filter::http_context::TracingHeader;
use crate::service::Service;
use chrono::{DateTime, FixedOffset, Timelike};
use protobuf::well_known_types::Timestamp;
use protobuf::Message;

Check warning on line 8 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `protobuf::Message`

Check warning on line 8 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unused import: `protobuf::Message`

Check warning on line 8 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused import: `protobuf::Message`

Check failure on line 8 in src/service/auth.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `protobuf::Message`
use proxy_wasm::hostcalls;
use proxy_wasm::hostcalls::dispatch_grpc_call;
use proxy_wasm::types::{Bytes, MapType, Status};
use proxy_wasm::types::MapType;
use std::collections::HashMap;
use std::time::Duration;

const AUTH_SERVICE_NAME: &str = "envoy.service.auth.v3.Authorization";
const AUTH_METHOD_NAME: &str = "Check";
pub const AUTH_DATA_ITEM: &str = "host";
pub const AUTH_SERVICE_NAME: &str = "envoy.service.auth.v3.Authorization";
pub const AUTH_METHOD_NAME: &str = "Check";

pub struct AuthService {
endpoint: String,
tracing_headers: Vec<(TracingHeader, Bytes)>,
}
pub struct AuthService;

impl AuthService {
pub fn new(endpoint: &str, metadata: Vec<(TracingHeader, Bytes)>) -> Self {
Self {
endpoint: String::from(endpoint),
tracing_headers: metadata,
}
}

pub fn message(ce_host: String) -> CheckRequest {
AuthService::build_check_req(ce_host)
}
Expand Down Expand Up @@ -93,23 +80,3 @@ impl AuthService {
peer
}
}

impl Service<CheckRequest> for AuthService {
fn send(&self, message: CheckRequest) -> Result<u32, Status> {
let msg = Message::write_to_bytes(&message).unwrap(); // TODO(adam-cattermole): Error Handling
let metadata = self
.tracing_headers
.iter()
.map(|(header, value)| (header.as_str(), value.as_slice()))
.collect();

dispatch_grpc_call(
self.endpoint.as_str(),
AUTH_SERVICE_NAME,
AUTH_METHOD_NAME,
metadata,
Some(&msg),
Duration::from_secs(5),
)
}
}
43 changes: 5 additions & 38 deletions src/service/rate_limit.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
use crate::envoy::{RateLimitDescriptor, RateLimitRequest};
use crate::filter::http_context::TracingHeader;
use crate::service::Service;
use protobuf::{Message, RepeatedField};

Check warning on line 2 in src/service/rate_limit.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `Message`

Check warning on line 2 in src/service/rate_limit.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unused import: `Message`

Check warning on line 2 in src/service/rate_limit.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused import: `Message`

Check failure on line 2 in src/service/rate_limit.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `Message`
use proxy_wasm::hostcalls::dispatch_grpc_call;
use proxy_wasm::types::{Bytes, Status};
use std::time::Duration;

const RATELIMIT_SERVICE_NAME: &str = "envoy.service.ratelimit.v3.RateLimitService";
const RATELIMIT_METHOD_NAME: &str = "ShouldRateLimit";
pub struct RateLimitService {
endpoint: String,
tracing_headers: Vec<(TracingHeader, Bytes)>,
}
pub const RATELIMIT_DATA_ITEM: &str = "domain";
pub const RATELIMIT_SERVICE_NAME: &str = "envoy.service.ratelimit.v3.RateLimitService";
pub const RATELIMIT_METHOD_NAME: &str = "ShouldRateLimit";

impl RateLimitService {
pub fn new(endpoint: &str, metadata: Vec<(TracingHeader, Bytes)>) -> Self {
Self {
endpoint: String::from(endpoint),
tracing_headers: metadata,
}
}
pub struct RateLimitService;

impl RateLimitService {
pub fn message(
domain: String,
descriptors: RepeatedField<RateLimitDescriptor>,
Expand All @@ -35,26 +22,6 @@ impl RateLimitService {
}
}

impl Service<RateLimitRequest> for RateLimitService {
fn send(&self, message: RateLimitRequest) -> Result<u32, Status> {
let msg = Message::write_to_bytes(&message).unwrap(); // TODO(didierofrivia): Error Handling
let metadata = self
.tracing_headers
.iter()
.map(|(header, value)| (header.as_str(), value.as_slice()))
.collect();

dispatch_grpc_call(
self.endpoint.as_str(),
RATELIMIT_SERVICE_NAME,
RATELIMIT_METHOD_NAME,
metadata,
Some(&msg),
Duration::from_secs(5),
)
}
}

#[cfg(test)]
mod tests {
use crate::envoy::{RateLimitDescriptor, RateLimitDescriptor_Entry, RateLimitRequest};
Expand Down

0 comments on commit 98b9206

Please sign in to comment.