From d48bcf3e0369459c325100ac6550dd5f658c06c0 Mon Sep 17 00:00:00 2001 From: Matthew Yacobucci Date: Wed, 19 Jul 2023 11:12:13 -0600 Subject: [PATCH 1/2] feat: Supporting changes for upstream example module. - functions to get mut and const module context from the ngx_http_upstream_srv_conf_t - Request from trait - Request upstream getter - Request peer init macro --- src/http/conf.rs | 30 ++++++++++++++++++++++++++++++ src/http/mod.rs | 2 ++ src/http/request.rs | 22 ++++++++++++++++++++++ src/http/upstream.rs | 15 +++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/http/upstream.rs diff --git a/src/http/conf.rs b/src/http/conf.rs index 4761bb0..a135e9f 100644 --- a/src/http/conf.rs +++ b/src/http/conf.rs @@ -31,3 +31,33 @@ pub unsafe fn ngx_http_conf_get_module_loc_conf( let http_conf_ctx = (*cf).ctx as *mut ngx_http_conf_ctx_t; *(*http_conf_ctx).loc_conf.add(module.ctx_index) as *mut ngx_http_core_loc_conf_t } + +/// # Safety +/// +/// The caller has provided a value `ngx_http_upstream_srv_conf_t. If the `us` argument is null, a +/// None Option is returned; however, if the `us` internal fields are invalid or the module index +/// is out of bounds failures may still occur. +pub unsafe fn ngx_http_conf_upstream_srv_conf_immutable( + us: *const ngx_http_upstream_srv_conf_t, + module: &ngx_module_t, +) -> Option<*const T> { + if us.is_null() { + return None; + } + Some(*(*us).srv_conf.add(module.ctx_index) as *const T) +} + +/// # Safety +/// +/// The caller has provided a value `ngx_http_upstream_srv_conf_t. If the `us` argument is null, a +/// None Option is returned; however, if the `us` internal fields are invalid or the module index +/// is out of bounds failures may still occur. +pub unsafe fn ngx_http_conf_upstream_srv_conf_mutable( + us: *const ngx_http_upstream_srv_conf_t, + module: &ngx_module_t, +) -> Option<*mut T> { + if us.is_null() { + return None; + } + Some(*(*us).srv_conf.add(module.ctx_index) as *mut T) +} diff --git a/src/http/mod.rs b/src/http/mod.rs index 230ce0b..024ad1f 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -2,8 +2,10 @@ mod conf; mod module; mod request; mod status; +mod upstream; pub use conf::*; pub use module::*; pub use request::*; pub use status::*; +pub use upstream::*; diff --git a/src/http/request.rs b/src/http/request.rs index 1594f17..be0330f 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -79,6 +79,17 @@ macro_rules! http_variable_get { #[repr(transparent)] pub struct Request(ngx_http_request_t); +impl<'a> From<&'a Request> for *const ngx_http_request_t { + fn from(request: &'a Request) -> Self { + &request.0 as *const _ + } +} +impl<'a> From<&'a mut Request> for *mut ngx_http_request_t { + fn from(request: &'a mut Request) -> Self { + &request.0 as *const _ as *mut _ + } +} + impl Request { /// Create a [`Request`] from an [`ngx_http_request_t`]. /// @@ -104,6 +115,17 @@ impl Request { unsafe { Pool::from_ngx_pool(self.0.pool) } } + /// Returns the result as an `Option` if it exists, otherwise `None`. + /// + /// The option wraps a pointer to a [`ngx_http_upstream_t`] upstream server object. + /// + /// [`ngx_http_upstream_t`]: is best described in + /// https://nginx.org/en/docs/dev/development_guide.html#http_request + /// https://nginx.org/en/docs/dev/development_guide.html#http_load_balancing + pub fn upstream(&self) -> Option<*mut ngx_http_upstream_t> { + Some(self.0.upstream) + } + /// Pointer to a [`ngx_connection_t`] client connection object. /// /// [`ngx_connection_t`]: https://nginx.org/en/docs/dev/development_guide.html#connection diff --git a/src/http/upstream.rs b/src/http/upstream.rs new file mode 100644 index 0000000..99148bb --- /dev/null +++ b/src/http/upstream.rs @@ -0,0 +1,15 @@ +/// Define a static upstream peer initializer +/// +/// Initializes the upstream 'get', 'free', and 'session' callbacks and gives the module writer an +/// opportunity to set custom data. +/// Load Balancing: +#[macro_export] +macro_rules! http_upstream_peer_init { + ( $name: ident, $handler: expr ) => { + #[no_mangle] + extern "C" fn $name(r: *mut ngx_http_request_t, us: *mut ngx_http_upstream_srv_conf_t) -> ngx_int_t { + let status: Status = $handler(unsafe { &mut Request::from_ngx_http_request(r) }, us); + status.0 + } + }; +} From e202d032b768dcba686e91dcb2185d221aedb514 Mon Sep 17 00:00:00 2001 From: Matthew Yacobucci Date: Wed, 19 Jul 2023 14:34:17 -0600 Subject: [PATCH 2/2] Code review notes Name macro to reflect underlying NGINX type --- src/http/request.rs | 6 +++++- src/http/upstream.rs | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/http/request.rs b/src/http/request.rs index be0330f..7d12532 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -117,12 +117,16 @@ impl Request { /// Returns the result as an `Option` if it exists, otherwise `None`. /// - /// The option wraps a pointer to a [`ngx_http_upstream_t`] upstream server object. + /// The option wraps an ngx_http_upstream_t instance, it will be none when the underlying NGINX request + /// does not have a pointer to a [`ngx_http_upstream_t`] upstream structure. /// /// [`ngx_http_upstream_t`]: is best described in /// https://nginx.org/en/docs/dev/development_guide.html#http_request /// https://nginx.org/en/docs/dev/development_guide.html#http_load_balancing pub fn upstream(&self) -> Option<*mut ngx_http_upstream_t> { + if self.0.upstream.is_null() { + return None; + } Some(self.0.upstream) } diff --git a/src/http/upstream.rs b/src/http/upstream.rs index 99148bb..8ba7c6c 100644 --- a/src/http/upstream.rs +++ b/src/http/upstream.rs @@ -2,9 +2,15 @@ /// /// Initializes the upstream 'get', 'free', and 'session' callbacks and gives the module writer an /// opportunity to set custom data. +/// +/// This macro will define the NGINX callback type: +/// `typedef ngx_int_t (*ngx_http_upstream_init_peer_pt)(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us)`, +/// we keep this macro name in-sync with its underlying NGINX type, this callback is required to +/// initialize your peer. +/// /// Load Balancing: #[macro_export] -macro_rules! http_upstream_peer_init { +macro_rules! http_upstream_init_peer_pt { ( $name: ident, $handler: expr ) => { #[no_mangle] extern "C" fn $name(r: *mut ngx_http_request_t, us: *mut ngx_http_upstream_srv_conf_t) -> ngx_int_t {