From 28ba351bb4498de40edb93707df2bf7d9040cb4b Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Fri, 21 Aug 2020 14:06:12 +0200 Subject: [PATCH 1/8] Move context creation to fn of RootContext instead of callback Signed-off-by: Daniel Grimm --- examples/http_auth_random.rs | 15 ++++++++++- examples/http_body.rs | 16 +++++++++++- examples/http_headers.rs | 18 +++++++++++-- src/dispatcher.rs | 50 ++++++++++-------------------------- src/lib.rs | 8 ------ src/traits.rs | 22 ++++++++++++++++ src/types.rs | 6 +++++ 7 files changed, 86 insertions(+), 49 deletions(-) diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index b9e747c6..40001897 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -20,10 +20,23 @@ use std::time::Duration; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); - proxy_wasm::set_http_context(|_, _| -> Box { Box::new(HttpAuthRandom) }); + proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpAuthRandomRoot) }); } struct HttpAuthRandom; +struct HttpAuthRandomRoot; + +impl RootContext for HttpAuthRandomRoot { + fn get_type(&self) -> ContextType { + ContextType::HttpContext + } + + fn create_http_context(&self, _root_context_id: u32, _context_id: u32) -> Box { + Box::new(HttpAuthRandom) + } +} + +impl Context for HttpAuthRandomRoot {} impl HttpContext for HttpAuthRandom { fn on_http_request_headers(&mut self, _: usize) -> Action { diff --git a/examples/http_body.rs b/examples/http_body.rs index 5db8ed8f..add8086d 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -18,10 +18,24 @@ use proxy_wasm::types::*; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); - proxy_wasm::set_http_context(|_, _| -> Box { Box::new(HttpBody) }); + proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpBodyRoot) }); } struct HttpBody; +struct HttpBodyRoot; + +impl RootContext for HttpBodyRoot { + fn get_type(&self) -> ContextType { + ContextType::HttpContext + } + + fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + Box::new(HttpBody) + } +} + +impl Context for HttpBodyRoot {} + impl Context for HttpBody {} diff --git a/examples/http_headers.rs b/examples/http_headers.rs index 14b32861..f3dc1666 100644 --- a/examples/http_headers.rs +++ b/examples/http_headers.rs @@ -19,11 +19,25 @@ use proxy_wasm::types::*; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); - proxy_wasm::set_http_context(|context_id, _| -> Box { - Box::new(HttpHeaders { context_id }) + proxy_wasm::set_root_context(|_| -> Box { + Box::new(HttpHeadersRoot) }); } +struct HttpHeadersRoot; + +impl Context for HttpHeadersRoot {} + +impl RootContext for HttpHeadersRoot { + fn get_type(&self) -> ContextType { + ContextType::HttpContext + } + + fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + Box::new(HttpHeaders{context_id: _context_id}) + } +} + struct HttpHeaders { context_id: u32, } diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 897f95d8..22142e37 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -26,14 +26,6 @@ pub(crate) fn set_root_context(callback: NewRootContext) { DISPATCHER.with(|dispatcher| dispatcher.set_root_context(callback)); } -pub(crate) fn set_stream_context(callback: NewStreamContext) { - DISPATCHER.with(|dispatcher| dispatcher.set_stream_context(callback)); -} - -pub(crate) fn set_http_context(callback: NewHttpContext) { - DISPATCHER.with(|dispatcher| dispatcher.set_http_context(callback)); -} - pub(crate) fn register_callout(token_id: u32) { DISPATCHER.with(|dispatcher| dispatcher.register_callout(token_id)); } @@ -46,9 +38,7 @@ impl RootContext for NoopRoot {} struct Dispatcher { new_root: Cell>, roots: RefCell>>, - new_stream: Cell>, streams: RefCell>>, - new_http_stream: Cell>, http_streams: RefCell>>, active_id: Cell, callouts: RefCell>, @@ -59,9 +49,7 @@ impl Dispatcher { Dispatcher { new_root: Cell::new(None), roots: RefCell::new(HashMap::new()), - new_stream: Cell::new(None), streams: RefCell::new(HashMap::new()), - new_http_stream: Cell::new(None), http_streams: RefCell::new(HashMap::new()), active_id: Cell::new(0), callouts: RefCell::new(HashMap::new()), @@ -72,14 +60,6 @@ impl Dispatcher { self.new_root.set(Some(callback)); } - fn set_stream_context(&self, callback: NewStreamContext) { - self.new_stream.set(Some(callback)); - } - - fn set_http_context(&self, callback: NewHttpContext) { - self.new_http_stream.set(Some(callback)); - } - fn create_root_context(&self, context_id: u32) { let new_context = match self.new_root.get() { Some(f) => f(context_id), @@ -96,12 +76,9 @@ impl Dispatcher { } fn create_stream_context(&self, context_id: u32, root_context_id: u32) { - if !self.roots.borrow().contains_key(&root_context_id) { - panic!("invalid root_context_id") - } - let new_context = match self.new_stream.get() { - Some(f) => f(context_id, root_context_id), - None => panic!("missing constructor"), + let new_context = match self.roots.borrow().get(&root_context_id) { + Some(root_context) => root_context.create_stream_context(context_id, root_context_id), + None => panic!("invalid root_context_id"), }; if self .streams @@ -114,12 +91,9 @@ impl Dispatcher { } fn create_http_context(&self, context_id: u32, root_context_id: u32) { - if !self.roots.borrow().contains_key(&root_context_id) { - panic!("invalid root_context_id") - } - let new_context = match self.new_http_stream.get() { - Some(f) => f(context_id, root_context_id), - None => panic!("missing constructor"), + let new_context = match self.roots.borrow().get(&root_context_id) { + Some(root_context) => root_context.create_http_context(context_id, root_context_id), + None => panic!("invalid root_context_id"), }; if self .http_streams @@ -144,11 +118,13 @@ impl Dispatcher { fn on_create_context(&self, context_id: u32, root_context_id: u32) { if root_context_id == 0 { - self.create_root_context(context_id) - } else if self.new_http_stream.get().is_some() { - self.create_http_context(context_id, root_context_id); - } else if self.new_stream.get().is_some() { - self.create_stream_context(context_id, root_context_id); + self.create_root_context(context_id); + } else if let Some(root_context) = self.roots.borrow().get(&root_context_id) { + match root_context.get_type() { + ContextType::HttpContext => self.create_http_context(context_id, root_context_id), + ContextType::StreamContext => self.create_stream_context(context_id, root_context_id), + ContextType::RootContext => panic!("missing constructors"), + } } else { panic!("missing constructors") } diff --git a/src/lib.rs b/src/lib.rs index cee98b72..ff55cbac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,13 +28,5 @@ pub fn set_root_context(callback: types::NewRootContext) { dispatcher::set_root_context(callback); } -pub fn set_stream_context(callback: types::NewStreamContext) { - dispatcher::set_stream_context(callback); -} - -pub fn set_http_context(callback: types::NewHttpContext) { - dispatcher::set_http_context(callback); -} - #[no_mangle] pub extern "C" fn proxy_abi_version_0_1_0() {} diff --git a/src/traits.rs b/src/traits.rs index 10b24514..4804e6d3 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -121,6 +121,18 @@ pub trait RootContext: Context { fn on_queue_ready(&mut self, _queue_id: u32) {} fn on_log(&mut self) {} + + fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + Box::new(EmptyHttpContext) + } + + fn create_stream_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + Box::new(EmptyStreamContext) + } + + fn get_type(&self) -> ContextType { + ContextType::RootContext + } } pub trait StreamContext: Context { @@ -159,6 +171,16 @@ pub trait StreamContext: Context { fn on_log(&mut self) {} } +struct EmptyHttpContext; + +impl HttpContext for EmptyHttpContext {} +impl Context for EmptyHttpContext {} + +struct EmptyStreamContext; + +impl StreamContext for EmptyStreamContext {} +impl Context for EmptyStreamContext {} + pub trait HttpContext: Context { fn on_http_request_headers(&mut self, _num_headers: usize) -> Action { Action::Continue diff --git a/src/types.rs b/src/types.rs index a951f78f..aa24e393 100644 --- a/src/types.rs +++ b/src/types.rs @@ -85,3 +85,9 @@ pub enum MetricType { } pub type Bytes = Vec; + +pub enum ContextType { + RootContext = 0, + HttpContext = 1, + StreamContext = 2, +} From 94ecd030ff8f2b89ee4c202891b2b3903fbf7dd6 Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Fri, 21 Aug 2020 14:55:24 +0200 Subject: [PATCH 2/8] Make rustfmt happy Signed-off-by: Daniel Grimm --- examples/http_body.rs | 1 - examples/http_headers.rs | 8 ++++---- src/dispatcher.rs | 4 +++- src/traits.rs | 6 +++++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/http_body.rs b/examples/http_body.rs index add8086d..98334867 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -36,7 +36,6 @@ impl RootContext for HttpBodyRoot { impl Context for HttpBodyRoot {} - impl Context for HttpBody {} impl HttpContext for HttpBody { diff --git a/examples/http_headers.rs b/examples/http_headers.rs index f3dc1666..8a4a7b57 100644 --- a/examples/http_headers.rs +++ b/examples/http_headers.rs @@ -19,9 +19,7 @@ use proxy_wasm::types::*; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); - proxy_wasm::set_root_context(|_| -> Box { - Box::new(HttpHeadersRoot) - }); + proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpHeadersRoot) }); } struct HttpHeadersRoot; @@ -34,7 +32,9 @@ impl RootContext for HttpHeadersRoot { } fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { - Box::new(HttpHeaders{context_id: _context_id}) + Box::new(HttpHeaders { + context_id: _context_id, + }) } } diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 22142e37..d702e5a3 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -122,7 +122,9 @@ impl Dispatcher { } else if let Some(root_context) = self.roots.borrow().get(&root_context_id) { match root_context.get_type() { ContextType::HttpContext => self.create_http_context(context_id, root_context_id), - ContextType::StreamContext => self.create_stream_context(context_id, root_context_id), + ContextType::StreamContext => { + self.create_stream_context(context_id, root_context_id) + } ContextType::RootContext => panic!("missing constructors"), } } else { diff --git a/src/traits.rs b/src/traits.rs index 4804e6d3..fd5bd552 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -126,7 +126,11 @@ pub trait RootContext: Context { Box::new(EmptyHttpContext) } - fn create_stream_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + fn create_stream_context( + &self, + _context_id: u32, + _root_context_id: u32, + ) -> Box { Box::new(EmptyStreamContext) } From 1cad70959fe5eef304e556c3bb31bff2a8ce5860 Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Mon, 16 Nov 2020 16:19:19 +0100 Subject: [PATCH 3/8] Addressing review comments - Remove root_context_id from RootContext's create_http_stream and create_http_context calls - Move EmptyHttpContext after HttpContext declaration - Reorder trait impl's in examples to be consistent Signed-off-by: Daniel Grimm --- examples/http_auth_random.rs | 40 ++++++++++++++++++------------------ examples/http_body.rs | 6 +++--- examples/http_headers.rs | 2 +- src/dispatcher.rs | 30 +++++++++++++-------------- src/traits.rs | 18 +++++++--------- 5 files changed, 46 insertions(+), 50 deletions(-) diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index 40001897..b4e617d8 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -26,17 +26,35 @@ pub fn _start() { struct HttpAuthRandom; struct HttpAuthRandomRoot; +impl Context for HttpAuthRandomRoot {} + impl RootContext for HttpAuthRandomRoot { fn get_type(&self) -> ContextType { ContextType::HttpContext } - fn create_http_context(&self, _root_context_id: u32, _context_id: u32) -> Box { + fn create_http_context(&self, _context_id: u32) -> Box { Box::new(HttpAuthRandom) } } -impl Context for HttpAuthRandomRoot {} +impl Context for HttpAuthRandom { + fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) { + if let Some(body) = self.get_http_call_response_body(0, body_size) { + if !body.is_empty() && body[0] % 2 == 0 { + trace!("Access granted."); + self.resume_http_request(); + return; + } + } + trace!("Access forbidden."); + self.send_http_response( + 403, + vec![("Powered-By", "proxy-wasm")], + Some(b"Access forbidden.\n"), + ); + } +} impl HttpContext for HttpAuthRandom { fn on_http_request_headers(&mut self, _: usize) -> Action { @@ -60,21 +78,3 @@ impl HttpContext for HttpAuthRandom { Action::Continue } } - -impl Context for HttpAuthRandom { - fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) { - if let Some(body) = self.get_http_call_response_body(0, body_size) { - if !body.is_empty() && body[0] % 2 == 0 { - trace!("Access granted."); - self.resume_http_request(); - return; - } - } - trace!("Access forbidden."); - self.send_http_response( - 403, - vec![("Powered-By", "proxy-wasm")], - Some(b"Access forbidden.\n"), - ); - } -} diff --git a/examples/http_body.rs b/examples/http_body.rs index 98334867..7e70b236 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -24,18 +24,18 @@ pub fn _start() { struct HttpBody; struct HttpBodyRoot; +impl Context for HttpBodyRoot {} + impl RootContext for HttpBodyRoot { fn get_type(&self) -> ContextType { ContextType::HttpContext } - fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + fn create_http_context(&self, _context_id: u32) -> Box { Box::new(HttpBody) } } -impl Context for HttpBodyRoot {} - impl Context for HttpBody {} impl HttpContext for HttpBody { diff --git a/examples/http_headers.rs b/examples/http_headers.rs index 8a4a7b57..17918d91 100644 --- a/examples/http_headers.rs +++ b/examples/http_headers.rs @@ -31,7 +31,7 @@ impl RootContext for HttpHeadersRoot { ContextType::HttpContext } - fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + fn create_http_context(&self, _context_id: u32) -> Box { Box::new(HttpHeaders { context_id: _context_id, }) diff --git a/src/dispatcher.rs b/src/dispatcher.rs index d702e5a3..1ffd2db1 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -60,6 +60,17 @@ impl Dispatcher { self.new_root.set(Some(callback)); } + fn register_callout(&self, token_id: u32) { + if self + .callouts + .borrow_mut() + .insert(token_id, self.active_id.get()) + .is_some() + { + panic!("duplicate token_id") + } + } + fn create_root_context(&self, context_id: u32) { let new_context = match self.new_root.get() { Some(f) => f(context_id), @@ -77,7 +88,7 @@ impl Dispatcher { fn create_stream_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { - Some(root_context) => root_context.create_stream_context(context_id, root_context_id), + Some(root_context) => root_context.create_stream_context(context_id), None => panic!("invalid root_context_id"), }; if self @@ -92,7 +103,7 @@ impl Dispatcher { fn create_http_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { - Some(root_context) => root_context.create_http_context(context_id, root_context_id), + Some(root_context) => root_context.create_http_context(context_id), None => panic!("invalid root_context_id"), }; if self @@ -105,17 +116,6 @@ impl Dispatcher { } } - fn register_callout(&self, token_id: u32) { - if self - .callouts - .borrow_mut() - .insert(token_id, self.active_id.get()) - .is_some() - { - panic!("duplicate token_id") - } - } - fn on_create_context(&self, context_id: u32, root_context_id: u32) { if root_context_id == 0 { self.create_root_context(context_id); @@ -125,10 +125,10 @@ impl Dispatcher { ContextType::StreamContext => { self.create_stream_context(context_id, root_context_id) } - ContextType::RootContext => panic!("missing constructors"), + ContextType::RootContext => panic!("missing ContextType on root_context"), } } else { - panic!("missing constructors") + panic!("invalid root_context_id"); } } diff --git a/src/traits.rs b/src/traits.rs index fd5bd552..70b9fa26 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -122,15 +122,11 @@ pub trait RootContext: Context { fn on_log(&mut self) {} - fn create_http_context(&self, _context_id: u32, _root_context_id: u32) -> Box { + fn create_http_context(&self, _context_id: u32) -> Box { Box::new(EmptyHttpContext) } - fn create_stream_context( - &self, - _context_id: u32, - _root_context_id: u32, - ) -> Box { + fn create_stream_context(&self, _context_id: u32) -> Box { Box::new(EmptyStreamContext) } @@ -175,11 +171,6 @@ pub trait StreamContext: Context { fn on_log(&mut self) {} } -struct EmptyHttpContext; - -impl HttpContext for EmptyHttpContext {} -impl Context for EmptyHttpContext {} - struct EmptyStreamContext; impl StreamContext for EmptyStreamContext {} @@ -329,3 +320,8 @@ pub trait HttpContext: Context { fn on_log(&mut self) {} } + +struct EmptyHttpContext; + +impl HttpContext for EmptyHttpContext {} +impl Context for EmptyHttpContext {} From 6488b8afacbb6b55c426281cf6f544c0bb92919e Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Wed, 18 Nov 2020 16:28:38 +0100 Subject: [PATCH 4/8] React to review comments - consistent ordering of struct defs in examples - attributes for ContextType enum Signed-off-by: Daniel Grimm --- examples/http_auth_random.rs | 3 ++- examples/http_body.rs | 3 ++- src/types.rs | 14 ++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index b4e617d8..2f82a560 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -23,7 +23,6 @@ pub fn _start() { proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpAuthRandomRoot) }); } -struct HttpAuthRandom; struct HttpAuthRandomRoot; impl Context for HttpAuthRandomRoot {} @@ -38,6 +37,8 @@ impl RootContext for HttpAuthRandomRoot { } } +struct HttpAuthRandom; + impl Context for HttpAuthRandom { fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) { if let Some(body) = self.get_http_call_response_body(0, body_size) { diff --git a/examples/http_body.rs b/examples/http_body.rs index 7e70b236..982c179c 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -21,7 +21,6 @@ pub fn _start() { proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpBodyRoot) }); } -struct HttpBody; struct HttpBodyRoot; impl Context for HttpBodyRoot {} @@ -36,6 +35,8 @@ impl RootContext for HttpBodyRoot { } } +struct HttpBody; + impl Context for HttpBody {} impl HttpContext for HttpBody { diff --git a/src/types.rs b/src/types.rs index aa24e393..69fcf1f6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -47,6 +47,14 @@ pub enum Status { InternalFailure = 10, } +#[repr(u32)] +#[derive(Debug)] +pub enum ContextType { + RootContext = 0, + HttpContext = 1, + StreamContext = 2, +} + #[repr(u32)] #[derive(Debug)] pub enum BufferType { @@ -85,9 +93,3 @@ pub enum MetricType { } pub type Bytes = Vec; - -pub enum ContextType { - RootContext = 0, - HttpContext = 1, - StreamContext = 2, -} From 79e8621af7cdbe71a76feb27dffd91c5a72f762b Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Wed, 18 Nov 2020 16:38:22 +0100 Subject: [PATCH 5/8] Add examples/http_config.rs Signed-off-by: Daniel Grimm --- Cargo.toml | 5 +++ examples/http_config.rs | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 examples/http_config.rs diff --git a/Cargo.toml b/Cargo.toml index 2e5b8d7e..c3e4ac7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,3 +60,8 @@ crate-type = ["cdylib"] name = "http_body" path = "examples/http_body.rs" crate-type = ["cdylib"] + +[[example]] +name = "http_config" +path = "examples/http_config.rs" +crate-type = ["cdylib"] diff --git a/examples/http_config.rs b/examples/http_config.rs new file mode 100644 index 00000000..a76e8a82 --- /dev/null +++ b/examples/http_config.rs @@ -0,0 +1,73 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::str; +use proxy_wasm::traits::*; +use proxy_wasm::types::*; + +#[no_mangle] +pub fn _start() { + proxy_wasm::set_log_level(LogLevel::Trace); + proxy_wasm::set_root_context(|_| -> Box { + Box::new(HttpConfigHeaderRootContext{ + header_content: "".to_string(), + }) + }); +} + +struct HttpConfigHeader{ + header_content: String +} + +impl Context for HttpConfigHeader {} + +impl HttpContext for HttpConfigHeader { + + fn on_http_response_headers(&mut self, _num_headers: usize) -> Action { + self.add_http_response_header("custom-header", self.header_content.as_str()); + + Action::Continue + } +} + +struct HttpConfigHeaderRootContext { + header_content: String +} + +impl Context for HttpConfigHeaderRootContext {} + +impl RootContext for HttpConfigHeaderRootContext { + + fn on_vm_start(&mut self, _vm_configuration_size: usize) -> bool { + true + } + + fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { + if let Some(config_bytes) = self.get_configuration() { + self.header_content = str::from_utf8(config_bytes.as_ref()).unwrap().to_owned() + } + true + } + + fn create_http_context(&self, _context_id: u32) -> Box { + Box::new(HttpConfigHeader{ + header_content: self.header_content.clone(), + }) + } + + fn get_type(&self) -> ContextType { + ContextType::HttpContext + } + +} From 5f0302c5df4a13112ada4bf2767611b7e5ca4a52 Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Fri, 20 Nov 2020 10:12:01 +0100 Subject: [PATCH 6/8] Add backwards compatibility, use Option<> where appropriate Signed-off-by: Daniel Grimm --- examples/http_auth_random.rs | 16 +----------- examples/http_body.rs | 8 +++--- examples/http_config.rs | 14 ++++------ examples/http_headers.rs | 10 ++++---- src/dispatcher.rs | 50 ++++++++++++++++++++++++++++++------ src/lib.rs | 8 ++++++ src/traits.rs | 22 +++++----------- src/types.rs | 5 ++-- 8 files changed, 73 insertions(+), 60 deletions(-) diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index 2f82a560..2f6bc4b0 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -20,21 +20,7 @@ use std::time::Duration; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); - proxy_wasm::set_root_context(|_| -> Box { Box::new(HttpAuthRandomRoot) }); -} - -struct HttpAuthRandomRoot; - -impl Context for HttpAuthRandomRoot {} - -impl RootContext for HttpAuthRandomRoot { - fn get_type(&self) -> ContextType { - ContextType::HttpContext - } - - fn create_http_context(&self, _context_id: u32) -> Box { - Box::new(HttpAuthRandom) - } + proxy_wasm::set_http_context(|_, _| -> Box { Box::new(HttpAuthRandom) }); } struct HttpAuthRandom; diff --git a/examples/http_body.rs b/examples/http_body.rs index 982c179c..da1bda55 100644 --- a/examples/http_body.rs +++ b/examples/http_body.rs @@ -26,12 +26,12 @@ struct HttpBodyRoot; impl Context for HttpBodyRoot {} impl RootContext for HttpBodyRoot { - fn get_type(&self) -> ContextType { - ContextType::HttpContext + fn get_type(&self) -> Option { + Some(ContextType::HttpContext) } - fn create_http_context(&self, _context_id: u32) -> Box { - Box::new(HttpBody) + fn create_http_context(&self, _context_id: u32) -> Option> { + Some(Box::new(HttpBody)) } } diff --git a/examples/http_config.rs b/examples/http_config.rs index a76e8a82..f2aaeef7 100644 --- a/examples/http_config.rs +++ b/examples/http_config.rs @@ -49,10 +49,6 @@ impl Context for HttpConfigHeaderRootContext {} impl RootContext for HttpConfigHeaderRootContext { - fn on_vm_start(&mut self, _vm_configuration_size: usize) -> bool { - true - } - fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { if let Some(config_bytes) = self.get_configuration() { self.header_content = str::from_utf8(config_bytes.as_ref()).unwrap().to_owned() @@ -60,14 +56,14 @@ impl RootContext for HttpConfigHeaderRootContext { true } - fn create_http_context(&self, _context_id: u32) -> Box { - Box::new(HttpConfigHeader{ + fn create_http_context(&self, _context_id: u32) -> Option> { + Some(Box::new(HttpConfigHeader{ header_content: self.header_content.clone(), - }) + })) } - fn get_type(&self) -> ContextType { - ContextType::HttpContext + fn get_type(&self) -> Option { + Some(ContextType::HttpContext) } } diff --git a/examples/http_headers.rs b/examples/http_headers.rs index 17918d91..615fdcc6 100644 --- a/examples/http_headers.rs +++ b/examples/http_headers.rs @@ -27,14 +27,14 @@ struct HttpHeadersRoot; impl Context for HttpHeadersRoot {} impl RootContext for HttpHeadersRoot { - fn get_type(&self) -> ContextType { - ContextType::HttpContext + fn get_type(&self) -> Option { + Some(ContextType::HttpContext) } - fn create_http_context(&self, _context_id: u32) -> Box { - Box::new(HttpHeaders { + fn create_http_context(&self, _context_id: u32) -> Option> { + Some(Box::new(HttpHeaders { context_id: _context_id, - }) + })) } } diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 1ffd2db1..07b22b55 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -26,6 +26,14 @@ pub(crate) fn set_root_context(callback: NewRootContext) { DISPATCHER.with(|dispatcher| dispatcher.set_root_context(callback)); } +pub(crate) fn set_stream_context(callback: NewStreamContext) { + DISPATCHER.with(|dispatcher| dispatcher.set_stream_context(callback)); +} + +pub(crate) fn set_http_context(callback: NewHttpContext) { + DISPATCHER.with(|dispatcher| dispatcher.set_http_context(callback)); +} + pub(crate) fn register_callout(token_id: u32) { DISPATCHER.with(|dispatcher| dispatcher.register_callout(token_id)); } @@ -38,7 +46,9 @@ impl RootContext for NoopRoot {} struct Dispatcher { new_root: Cell>, roots: RefCell>>, + new_stream: Cell>, streams: RefCell>>, + new_http_stream: Cell>, http_streams: RefCell>>, active_id: Cell, callouts: RefCell>, @@ -49,7 +59,9 @@ impl Dispatcher { Dispatcher { new_root: Cell::new(None), roots: RefCell::new(HashMap::new()), + new_stream: Cell::new(None), streams: RefCell::new(HashMap::new()), + new_http_stream: Cell::new(None), http_streams: RefCell::new(HashMap::new()), active_id: Cell::new(0), callouts: RefCell::new(HashMap::new()), @@ -60,6 +72,14 @@ impl Dispatcher { self.new_root.set(Some(callback)); } + fn set_stream_context(&self, callback: NewStreamContext) { + self.new_stream.set(Some(callback)); + } + + fn set_http_context(&self, callback: NewHttpContext) { + self.new_http_stream.set(Some(callback)); + } + fn register_callout(&self, token_id: u32) { if self .callouts @@ -88,7 +108,13 @@ impl Dispatcher { fn create_stream_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { - Some(root_context) => root_context.create_stream_context(context_id), + Some(root_context) => match self.new_stream.get() { + Some(f) => f(context_id, root_context_id), + None => match root_context.create_stream_context(context_id) { + Some(stream_context) => stream_context, + None => panic!("create_stream_context returned None"), + }, + }, None => panic!("invalid root_context_id"), }; if self @@ -103,7 +129,13 @@ impl Dispatcher { fn create_http_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { - Some(root_context) => root_context.create_http_context(context_id), + Some(root_context) => match self.new_http_stream.get() { + Some(f) => f(context_id, root_context_id), + None => match root_context.create_http_context(context_id) { + Some(stream_context) => stream_context, + None => panic!("create_http_context returned None"), + }, + }, None => panic!("invalid root_context_id"), }; if self @@ -119,16 +151,18 @@ impl Dispatcher { fn on_create_context(&self, context_id: u32, root_context_id: u32) { if root_context_id == 0 { self.create_root_context(context_id); + } else if self.new_http_stream.get().is_some() { + self.create_http_context(context_id, root_context_id); + } else if self.new_stream.get().is_some() { + self.create_stream_context(context_id, root_context_id); } else if let Some(root_context) = self.roots.borrow().get(&root_context_id) { match root_context.get_type() { - ContextType::HttpContext => self.create_http_context(context_id, root_context_id), - ContextType::StreamContext => { - self.create_stream_context(context_id, root_context_id) - } - ContextType::RootContext => panic!("missing ContextType on root_context"), + Some(ContextType::HttpContext) => self.create_http_context(context_id, root_context_id), + Some(ContextType::StreamContext) => self.create_stream_context(context_id, root_context_id), + None => panic!("missing ContextType on root_context"), } } else { - panic!("invalid root_context_id"); + panic!("invalid root_context_id and missing constructors"); } } diff --git a/src/lib.rs b/src/lib.rs index ff55cbac..cee98b72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,5 +28,13 @@ pub fn set_root_context(callback: types::NewRootContext) { dispatcher::set_root_context(callback); } +pub fn set_stream_context(callback: types::NewStreamContext) { + dispatcher::set_stream_context(callback); +} + +pub fn set_http_context(callback: types::NewHttpContext) { + dispatcher::set_http_context(callback); +} + #[no_mangle] pub extern "C" fn proxy_abi_version_0_1_0() {} diff --git a/src/traits.rs b/src/traits.rs index 70b9fa26..5b7fc4be 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -122,16 +122,16 @@ pub trait RootContext: Context { fn on_log(&mut self) {} - fn create_http_context(&self, _context_id: u32) -> Box { - Box::new(EmptyHttpContext) + fn create_http_context(&self, _context_id: u32) -> Option> { + None } - fn create_stream_context(&self, _context_id: u32) -> Box { - Box::new(EmptyStreamContext) + fn create_stream_context(&self, _context_id: u32) -> Option> { + None } - fn get_type(&self) -> ContextType { - ContextType::RootContext + fn get_type(&self) -> Option { + None } } @@ -171,11 +171,6 @@ pub trait StreamContext: Context { fn on_log(&mut self) {} } -struct EmptyStreamContext; - -impl StreamContext for EmptyStreamContext {} -impl Context for EmptyStreamContext {} - pub trait HttpContext: Context { fn on_http_request_headers(&mut self, _num_headers: usize) -> Action { Action::Continue @@ -320,8 +315,3 @@ pub trait HttpContext: Context { fn on_log(&mut self) {} } - -struct EmptyHttpContext; - -impl HttpContext for EmptyHttpContext {} -impl Context for EmptyHttpContext {} diff --git a/src/types.rs b/src/types.rs index 69fcf1f6..855a414b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -50,9 +50,8 @@ pub enum Status { #[repr(u32)] #[derive(Debug)] pub enum ContextType { - RootContext = 0, - HttpContext = 1, - StreamContext = 2, + HttpContext = 0, + StreamContext = 1, } #[repr(u32)] From 9756371aa37bf66a801aa608b29a05deec7565a3 Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Fri, 20 Nov 2020 10:32:04 +0100 Subject: [PATCH 7/8] rustfmt Signed-off-by: Daniel Grimm --- examples/http_config.rs | 15 ++++++--------- src/dispatcher.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/http_config.rs b/examples/http_config.rs index f2aaeef7..1536d7a0 100644 --- a/examples/http_config.rs +++ b/examples/http_config.rs @@ -12,28 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::str; use proxy_wasm::traits::*; use proxy_wasm::types::*; +use std::str; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { - Box::new(HttpConfigHeaderRootContext{ + Box::new(HttpConfigHeaderRootContext { header_content: "".to_string(), }) }); } -struct HttpConfigHeader{ - header_content: String +struct HttpConfigHeader { + header_content: String, } impl Context for HttpConfigHeader {} impl HttpContext for HttpConfigHeader { - fn on_http_response_headers(&mut self, _num_headers: usize) -> Action { self.add_http_response_header("custom-header", self.header_content.as_str()); @@ -42,13 +41,12 @@ impl HttpContext for HttpConfigHeader { } struct HttpConfigHeaderRootContext { - header_content: String + header_content: String, } impl Context for HttpConfigHeaderRootContext {} impl RootContext for HttpConfigHeaderRootContext { - fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { if let Some(config_bytes) = self.get_configuration() { self.header_content = str::from_utf8(config_bytes.as_ref()).unwrap().to_owned() @@ -57,7 +55,7 @@ impl RootContext for HttpConfigHeaderRootContext { } fn create_http_context(&self, _context_id: u32) -> Option> { - Some(Box::new(HttpConfigHeader{ + Some(Box::new(HttpConfigHeader { header_content: self.header_content.clone(), })) } @@ -65,5 +63,4 @@ impl RootContext for HttpConfigHeaderRootContext { fn get_type(&self) -> Option { Some(ContextType::HttpContext) } - } diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 07b22b55..4c84733c 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -157,8 +157,12 @@ impl Dispatcher { self.create_stream_context(context_id, root_context_id); } else if let Some(root_context) = self.roots.borrow().get(&root_context_id) { match root_context.get_type() { - Some(ContextType::HttpContext) => self.create_http_context(context_id, root_context_id), - Some(ContextType::StreamContext) => self.create_stream_context(context_id, root_context_id), + Some(ContextType::HttpContext) => { + self.create_http_context(context_id, root_context_id) + } + Some(ContextType::StreamContext) => { + self.create_stream_context(context_id, root_context_id) + } None => panic!("missing ContextType on root_context"), } } else { From 46cf56399744a32bdcc77cee5f95f0a14028b60a Mon Sep 17 00:00:00 2001 From: Daniel Grimm Date: Fri, 20 Nov 2020 14:40:48 +0100 Subject: [PATCH 8/8] Revert unnecessary change in http_auth_random.rs, use String Signed-off-by: Daniel Grimm --- examples/http_auth_random.rs | 36 ++++++++++++++++++------------------ examples/http_config.rs | 14 ++++++-------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/examples/http_auth_random.rs b/examples/http_auth_random.rs index 2f6bc4b0..b9e747c6 100644 --- a/examples/http_auth_random.rs +++ b/examples/http_auth_random.rs @@ -25,24 +25,6 @@ pub fn _start() { struct HttpAuthRandom; -impl Context for HttpAuthRandom { - fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) { - if let Some(body) = self.get_http_call_response_body(0, body_size) { - if !body.is_empty() && body[0] % 2 == 0 { - trace!("Access granted."); - self.resume_http_request(); - return; - } - } - trace!("Access forbidden."); - self.send_http_response( - 403, - vec![("Powered-By", "proxy-wasm")], - Some(b"Access forbidden.\n"), - ); - } -} - impl HttpContext for HttpAuthRandom { fn on_http_request_headers(&mut self, _: usize) -> Action { self.dispatch_http_call( @@ -65,3 +47,21 @@ impl HttpContext for HttpAuthRandom { Action::Continue } } + +impl Context for HttpAuthRandom { + fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) { + if let Some(body) = self.get_http_call_response_body(0, body_size) { + if !body.is_empty() && body[0] % 2 == 0 { + trace!("Access granted."); + self.resume_http_request(); + return; + } + } + trace!("Access forbidden."); + self.send_http_response( + 403, + vec![("Powered-By", "proxy-wasm")], + Some(b"Access forbidden.\n"), + ); + } +} diff --git a/examples/http_config.rs b/examples/http_config.rs index 1536d7a0..fc297a08 100644 --- a/examples/http_config.rs +++ b/examples/http_config.rs @@ -14,14 +14,13 @@ use proxy_wasm::traits::*; use proxy_wasm::types::*; -use std::str; #[no_mangle] pub fn _start() { proxy_wasm::set_log_level(LogLevel::Trace); proxy_wasm::set_root_context(|_| -> Box { - Box::new(HttpConfigHeaderRootContext { - header_content: "".to_string(), + Box::new(HttpConfigHeaderRoot { + header_content: String::new(), }) }); } @@ -35,21 +34,20 @@ impl Context for HttpConfigHeader {} impl HttpContext for HttpConfigHeader { fn on_http_response_headers(&mut self, _num_headers: usize) -> Action { self.add_http_response_header("custom-header", self.header_content.as_str()); - Action::Continue } } -struct HttpConfigHeaderRootContext { +struct HttpConfigHeaderRoot { header_content: String, } -impl Context for HttpConfigHeaderRootContext {} +impl Context for HttpConfigHeaderRoot {} -impl RootContext for HttpConfigHeaderRootContext { +impl RootContext for HttpConfigHeaderRoot { fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { if let Some(config_bytes) = self.get_configuration() { - self.header_content = str::from_utf8(config_bytes.as_ref()).unwrap().to_owned() + self.header_content = String::from_utf8(config_bytes).unwrap() } true }