diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6156321..5228c2e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,7 +37,7 @@ jobs: key: ${{ runner.os }}-deps-${{ hashFiles('**/nginx-sys/build.rs') }} restore-keys: ${{ runner.os }}-deps- - name: run tests - run: cargo test --verbose + run: cargo test --verbose --workspace examples-linux: name: Examples (Linux) @@ -70,7 +70,7 @@ jobs: key: ${{ runner.os }}-deps-${{ hashFiles('**/nginx-sys/build.rs') }} restore-keys: ${{ runner.os }}-deps- - name: compile examples - run: cargo build --release --package examples --examples --verbose + run: cargo build --release --package examples --examples --all-features --verbose test-macos: name: Test (MacOS) @@ -111,7 +111,7 @@ jobs: - name: build run: cargo build --verbose - name: run tests - run: cargo test --verbose + run: cargo test --verbose --workspace fmt: name: Rustfmt @@ -124,7 +124,7 @@ jobs: - name: rustfmt version run: rustfmt --version - name: cargo fmt - run: cargo fmt --all --verbose --check || true + run: cargo fmt --all --verbose --check clippy: name: Clippy @@ -159,4 +159,4 @@ jobs: with: components: rustfmt, clippy - name: run clippy - run: cargo clippy -- -D warnings \ No newline at end of file + run: cargo clippy --workspace --all-targets -- -D warnings \ No newline at end of file diff --git a/README.md b/README.md index 1bbda40..3c26763 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,12 @@ NGINX modules can be built against a particular version of NGINX. The following For example, this is how you would compile the [examples](examples) using a specific version of NGINX and enabling debugging: -``` +```sh NGX_DEBUG=true NGX_VERSION=1.23.0 cargo build --package=examples --examples --release ``` To build Linux-only modules, use the "linux" feature: -``` +```sh cargo build --package=examples --examples --features=linux --release ``` @@ -51,13 +51,13 @@ The following environment variables can be used to change locations of cache dir In order to use the optional GNU make build process on MacOS, you will need to install additional tools. This can be done via [homebrew](https://brew.sh/) with the following command: -``` +```sh brew install make openssl grep ``` Additionally, you may need to set up LLVM and clang. Typically, this is done as follows: -``` +```sh # make sure xcode tools are installed xcode-select --install # instal llvm @@ -81,10 +81,8 @@ If you require a customized NGINX configuration, you can build a module against To do that, you need to set the `NGX_OBJS` variable to an _absolute_ path of the NGINX build directory (`--builddir`, defaults to the `objs` in the source directory). Only the `./configure` step of the NGINX build is mandatory because bindings don't depend on any of the artifacts generated by `make`. - -``` +```sh NGX_OBJS=$PWD/../nginx/objs cargo build --package=examples --examples - ``` Furthermore, this approach can be leveraged to build a module as a part of the NGINX build process by adding the `--add-module`/`--add-dynamic-module` options to the configure script. diff --git a/examples/awssig.rs b/examples/awssig.rs index e235d2e..dcc1974 100644 --- a/examples/awssig.rs +++ b/examples/awssig.rs @@ -310,12 +310,9 @@ http_request_handler!(awssigv4_header_handler, |request: &mut Request| { // Copy only headers that will be used to sign the request let mut headers = HeaderMap::new(); for (name, value) in request.headers_in_iterator() { - match name.to_lowercase().as_str() { - "host" => { - headers.insert(http::header::HOST, value.parse().unwrap()); - } - &_ => {} - }; + if name.to_lowercase() == "host" { + headers.insert(http::header::HOST, value.parse().unwrap()); + } } headers.insert("X-Amz-Date", datetime_now.parse().unwrap()); ngx_log_debug_http!(request, "headers {:?}", headers); diff --git a/nginx-sys/src/lib.rs b/nginx-sys/src/lib.rs index d56a3aa..db9a05e 100644 --- a/nginx-sys/src/lib.rs +++ b/nginx-sys/src/lib.rs @@ -24,8 +24,7 @@ //! ```rust,no_run //! use nginx_sys::nginx_version; //! -//! let version = unsafe { nginx_version() }; -//! println!("Nginx version: {}", version); +//! println!("Nginx version: {}", nginx_version); //! ``` //! #![warn(missing_docs)] @@ -77,7 +76,7 @@ pub unsafe fn bytes_to_uchar(pool: *mut ngx_pool_t, data: &[u8]) -> Option<*mut /// A raw pointer (`*mut u_char`) to the allocated memory containing the converted string data. /// /// # Example -/// ```rust +/// ```rust,ignore /// let pool: *mut ngx_pool_t = ...; // Obtain a pointer to the nginx memory pool /// let data: &str = "example"; // The string to convert /// let ptr = str_to_uchar(pool, data); @@ -237,11 +236,15 @@ impl TryFrom for &str { /// /// # Example /// ```rust -/// let table: *mut ngx_table_elt_t = ...; // Obtain a pointer to the nginx table entry -/// let pool: *mut ngx_pool_t = ...; // Obtain a pointer to the nginx memory pool +/// # use nginx_sys::*; +/// # unsafe fn example(pool: *mut ngx_pool_t, headers: *mut ngx_list_t) { +/// // Obtain a pointer to the nginx table entry +/// let table: *mut ngx_table_elt_t = ngx_list_push(headers).cast(); +/// assert!(!table.is_null()); /// let key: &str = "key"; // The key to add /// let value: &str = "value"; // The value to add /// let result = add_to_ngx_table(table, pool, key, value); +/// # } /// ``` pub unsafe fn add_to_ngx_table( table: *mut ngx_table_elt_t, diff --git a/src/core/buffer.rs b/src/core/buffer.rs index baccd8b..9086238 100644 --- a/src/core/buffer.rs +++ b/src/core/buffer.rs @@ -3,6 +3,8 @@ use std::slice; use crate::ffi::*; /// The `Buffer` trait provides methods for working with an nginx buffer (`ngx_buf_t`). +/// +/// See pub trait Buffer { /// Returns a raw pointer to the underlying `ngx_buf_t` of the buffer. fn as_ngx_buf(&self) -> *const ngx_buf_t; diff --git a/src/core/pool.rs b/src/core/pool.rs index 2e6c7dd..4099065 100644 --- a/src/core/pool.rs +++ b/src/core/pool.rs @@ -4,7 +4,9 @@ use std::{mem, ptr}; use crate::core::buffer::{Buffer, MemoryBuffer, TemporaryBuffer}; use crate::ffi::*; -/// Wrapper struct for an `ngx_pool_t` pointer, providing methods for working with memory pools. +/// Wrapper struct for an [`ngx_pool_t`] pointer, providing methods for working with memory pools. +/// +/// See pub struct Pool(*mut ngx_pool_t); impl Pool { diff --git a/src/http/module.rs b/src/http/module.rs index e372a35..6a0f587 100644 --- a/src/http/module.rs +++ b/src/http/module.rs @@ -45,7 +45,7 @@ impl Merge for () { /// These functions allocate structures, initialize them, and merge through the configuration /// layers. /// -/// See https://nginx.org/en/docs/dev/development_guide.html#adding_new_modules for details. +/// See for details. pub trait HTTPModule { /// Configuration in the `http` block. type MainConf: Merge + Default; diff --git a/src/http/request.rs b/src/http/request.rs index 04e19b6..d25d614 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -88,7 +88,9 @@ macro_rules! http_variable_get { }; } -/// Wrapper struct for an `ngx_http_request_t` pointer, , providing methods for working with HTTP requests. +/// Wrapper struct for an [`ngx_http_request_t`] pointer, providing methods for working with HTTP requests. +/// +/// See #[repr(transparent)] pub struct Request(ngx_http_request_t); @@ -107,8 +109,6 @@ impl<'a> From<&'a mut Request> for *mut ngx_http_request_t { impl Request { /// Create a [`Request`] from an [`ngx_http_request_t`]. /// - /// [`ngx_http_request_t`]: https://nginx.org/en/docs/dev/development_guide.html#http_request - /// /// # Safety /// /// The caller has provided a valid non-null pointer to a valid `ngx_http_request_t` @@ -134,9 +134,8 @@ impl Request { /// 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 + /// [`ngx_http_upstream_t`] is best described in + /// pub fn upstream(&self) -> Option<*mut ngx_http_upstream_t> { if self.0.upstream.is_null() { return None; @@ -218,7 +217,7 @@ impl Request { /// Sets the value as the module's context. /// - /// See https://nginx.org/en/docs/dev/development_guide.html#http_request + /// See pub fn set_module_ctx(&self, value: *mut c_void, module: &ngx_module_t) { unsafe { *self.0.ctx.add(module.ctx_index) = value; @@ -267,7 +266,7 @@ impl Request { /// Add header to the `headers_in` object. /// - /// See https://nginx.org/en/docs/dev/development_guide.html#http_request + /// See pub fn add_header_in(&mut self, key: &str, value: &str) -> Option<()> { let table: *mut ngx_table_elt_t = unsafe { ngx_list_push(&mut self.0.headers_in.headers) as _ }; unsafe { add_to_ngx_table(table, self.0.pool, key, value) } @@ -275,7 +274,7 @@ impl Request { /// Add header to the `headers_out` object. /// - /// See https://nginx.org/en/docs/dev/development_guide.html#http_request + /// See pub fn add_header_out(&mut self, key: &str, value: &str) -> Option<()> { let table: *mut ngx_table_elt_t = unsafe { ngx_list_push(&mut self.0.headers_out.headers) as _ }; unsafe { add_to_ngx_table(table, self.0.pool, key, value) } @@ -425,7 +424,7 @@ impl fmt::Debug for Request { } } -/// Iterator for `ngx_list_t` types. +/// Iterator for [`ngx_list_t`] types. /// /// Implementes the std::iter::Iterator trait. pub struct NgxListIterator { @@ -435,10 +434,11 @@ pub struct NgxListIterator { i: ngx_uint_t, } -// create new http request iterator +/// Creates new HTTP header iterator +/// /// # Safety /// -/// The caller has provided a valid `ngx_str_t` which can be dereferenced validly. +/// The caller has provided a valid [`ngx_str_t`] which can be dereferenced validly. pub unsafe fn list_iterator(list: *const ngx_list_t) -> NgxListIterator { let part: *const ngx_list_part_t = &(*list).part; diff --git a/src/lib.rs b/src/lib.rs index 08e1767..726bdb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ //! Bindings to NGINX +//! //! This project provides Rust SDK interfaces to the [NGINX](https://nginx.com) proxy allowing the creation of NGINX //! dynamic modules completely in Rust. //! @@ -14,23 +15,75 @@ //! * `NGX_DEBUG` (default to false) - if set to true, then will compile NGINX `--with-debug` option //! //! For example, this is how you would compile the [examples](https://github.com/nginxinc/ngx-rust/tree/master/examples) using a specific version of NGINX and enabling -//! debugging: `NGX_DEBUG=true NGX_VERSION=1.23.0 cargo build --package=examples --examples --release` +//! debugging: +//! ```sh +//! NGX_DEBUG=true NGX_VERSION=1.23.0 cargo build --package=examples --examples --release +//! ``` //! -//! To build Linux-only modules, use the "linux" feature: `cargo build --package=examples --examples --features=linux --release` +//! To build Linux-only modules, use the "linux" feature: +//! ```sh +//! cargo build --package=examples --examples --features=linux --release +//! ``` //! //! After compilation, the modules can be found in the path `target/release/examples/` ( with the `.so` file extension for //! Linux or `.dylib` for MacOS). //! -//! Additionally, the folder `.cache/nginx/{NGX_VERSION}/{OS}/` will contain the compiled version of NGINX used to build -//! the SDK. You can start NGINX directly from this directory if you want to test the module or add it to `$PATH` +//! Additionally, the folder `.cache/nginx/{NGX_VERSION}/{TARGET}` (`{TARGET}` means rustc's target triple string) +//! will contain the compiled version of NGINX used to build the SDK. +//! You can start NGINX directly from this directory if you want to test the module or add it to `$PATH` //! ```not_rust //! $ export NGX_VERSION=1.23.3 //! $ cargo build --package=examples --examples --features=linux --release -//! $ export PATH=$PATH:`pwd`/.cache/nginx/$NGX_VERSION/macos-x86_64/sbin +//! $ export PATH=$PATH:$PWD/.cache/nginx/$NGX_VERSION/x86_64-unknown-linux-gnu/sbin //! $ nginx -V //! $ ls -la ./target/release/examples/ //! # now you can use dynamic modules with the NGINX //! ``` +//! +//! The following environment variables can be used to change locations of cache directory and NGINX directory: +//! +//! * `CACHE_DIR` (default `[nginx-sys's root directory]/.cache`) - the directory containing cache files, means PGP keys, tarballs, PGP signatures, and unpacked source codes. It also contains compiled NGINX in default configuration. +//! * `NGINX_INSTALL_ROOT_DIR` (default `{CACHE_DIR}/nginx`) - the directory containing the series of compiled NGINX in its subdirectories +//! * `NGINX_INSTALL_DIR` (default `{NGINX_INSTALL_BASE_DIR}/{NGX_VERSION}/{TARGET}`) - the directory containing the NGINX compiled in the build +//! +//! ### Mac OS dependencies +//! +//! In order to use the optional GNU make build process on MacOS, you will need to install additional tools. This can be +//! done via [homebrew](https://brew.sh/) with the following command: +//! ```sh +//! brew install make openssl grep +//! ``` +//! +//! Additionally, you may need to set up LLVM and clang. Typically, this is done as follows: +//! +//! ```sh +//! # make sure xcode tools are installed +//! xcode-select --install +//! # instal llvm +//! brew install --with-toolchain llvm +//! ``` +//! +//! ### Linux dependencies +//! +//! See the [Dockerfile] for dependencies as an example of required packages on Debian Linux. +//! +//! [Dockerfile]: https://github.com/nginxinc/ngx-rust/blob/master/Dockerfile +//! +//! ### Build with external NGINX source tree +//! +//! If you require a customized NGINX configuration, you can build a module against an existing pre-configured source tree. +//! To do that, you need to set the `NGX_OBJS` variable to an _absolute_ path of the NGINX build directory (`--builddir`, defaults to the `objs` in the source directory). +//! Only the `./configure` step of the NGINX build is mandatory because bindings don't depend on any of the artifacts generated by `make`. +//! +//! ```sh +//! NGX_OBJS=$PWD/../nginx/objs cargo build --package=examples --examples +//! ``` +//! +//! Furthermore, this approach can be leveraged to build a module as a part of the NGINX build process by adding the `--add-module`/`--add-dynamic-module` options to the configure script. +//! See the following example integration scripts: [`examples/config`] and [`examples/config.make`]. +//! +//! [`examples/config`]: https://github.com/nginxinc/ngx-rust/blob/master/examples/config +//! [`examples/config.make`]: https://github.com/nginxinc/ngx-rust/blob/master/examples/config.make #![warn(missing_docs)] /// The core module. diff --git a/src/log.rs b/src/log.rs index 0311446..a0f0397 100644 --- a/src/log.rs +++ b/src/log.rs @@ -38,64 +38,13 @@ macro_rules! ngx_log_debug_http { } } -/// Debug masks for use with ngx_log_debug_mask, these represent the only accepted values for the -/// mask. -#[derive(Debug)] -pub enum DebugMask { - /// Aligns to the NGX_LOG_DEBUG_CORE mask. - Core, - /// Aligns to the NGX_LOG_DEBUG_ALLOC mask. - Alloc, - /// Aligns to the NGX_LOG_DEBUG_MUTEX mask. - Mutex, - /// Aligns to the NGX_LOG_DEBUG_EVENT mask. - Event, - /// Aligns to the NGX_LOG_DEBUG_HTTP mask. - Http, - /// Aligns to the NGX_LOG_DEBUG_MAIL mask. - Mail, - /// Aligns to the NGX_LOG_DEBUG_STREAM mask. - Stream, -} - -impl TryFrom for DebugMask { - type Error = u32; - - fn try_from(value: u32) -> Result { - match value { - crate::ffi::NGX_LOG_DEBUG_CORE => Ok(DebugMask::Core), - crate::ffi::NGX_LOG_DEBUG_ALLOC => Ok(DebugMask::Alloc), - crate::ffi::NGX_LOG_DEBUG_MUTEX => Ok(DebugMask::Mutex), - crate::ffi::NGX_LOG_DEBUG_EVENT => Ok(DebugMask::Event), - crate::ffi::NGX_LOG_DEBUG_HTTP => Ok(DebugMask::Http), - crate::ffi::NGX_LOG_DEBUG_MAIL => Ok(DebugMask::Mail), - crate::ffi::NGX_LOG_DEBUG_STREAM => Ok(DebugMask::Stream), - _ => Err(0), - } - } -} - -impl From for u32 { - fn from(value: DebugMask) -> Self { - match value { - DebugMask::Core => crate::ffi::NGX_LOG_DEBUG_CORE, - DebugMask::Alloc => crate::ffi::NGX_LOG_DEBUG_ALLOC, - DebugMask::Mutex => crate::ffi::NGX_LOG_DEBUG_MUTEX, - DebugMask::Event => crate::ffi::NGX_LOG_DEBUG_EVENT, - DebugMask::Http => crate::ffi::NGX_LOG_DEBUG_HTTP, - DebugMask::Mail => crate::ffi::NGX_LOG_DEBUG_MAIL, - DebugMask::Stream => crate::ffi::NGX_LOG_DEBUG_STREAM, - } - } -} - /// Log with requested debug mask. /// -/// **NOTE:** This macro supports `DebugMask::Http` (`NGX_LOG_DEBUG_HTTP`), however, if you have -/// access to a Request object via an http handler it can be more convenient and readable to use the -/// `ngx_log_debug_http` macro instead. +/// **NOTE:** This macro supports [`DebugMask::Http`] (`NGX_LOG_DEBUG_HTTP`), however, if you have +/// access to a Request object via an http handler it can be more convenient and readable to use +/// the [`ngx_log_debug_http`] macro instead. /// -/// See https://nginx.org/en/docs/dev/development_guide.html#logging for details and available +/// See for details and available /// masks. #[macro_export] macro_rules! ngx_log_debug_mask { @@ -178,6 +127,57 @@ macro_rules! ngx_log_debug_mask { }); } +/// Debug masks for use with [`ngx_log_debug_mask`], these represent the only accepted values for +/// the mask. +#[derive(Debug)] +pub enum DebugMask { + /// Aligns to the NGX_LOG_DEBUG_CORE mask. + Core, + /// Aligns to the NGX_LOG_DEBUG_ALLOC mask. + Alloc, + /// Aligns to the NGX_LOG_DEBUG_MUTEX mask. + Mutex, + /// Aligns to the NGX_LOG_DEBUG_EVENT mask. + Event, + /// Aligns to the NGX_LOG_DEBUG_HTTP mask. + Http, + /// Aligns to the NGX_LOG_DEBUG_MAIL mask. + Mail, + /// Aligns to the NGX_LOG_DEBUG_STREAM mask. + Stream, +} + +impl TryFrom for DebugMask { + type Error = u32; + + fn try_from(value: u32) -> Result { + match value { + crate::ffi::NGX_LOG_DEBUG_CORE => Ok(DebugMask::Core), + crate::ffi::NGX_LOG_DEBUG_ALLOC => Ok(DebugMask::Alloc), + crate::ffi::NGX_LOG_DEBUG_MUTEX => Ok(DebugMask::Mutex), + crate::ffi::NGX_LOG_DEBUG_EVENT => Ok(DebugMask::Event), + crate::ffi::NGX_LOG_DEBUG_HTTP => Ok(DebugMask::Http), + crate::ffi::NGX_LOG_DEBUG_MAIL => Ok(DebugMask::Mail), + crate::ffi::NGX_LOG_DEBUG_STREAM => Ok(DebugMask::Stream), + _ => Err(0), + } + } +} + +impl From for u32 { + fn from(value: DebugMask) -> Self { + match value { + DebugMask::Core => crate::ffi::NGX_LOG_DEBUG_CORE, + DebugMask::Alloc => crate::ffi::NGX_LOG_DEBUG_ALLOC, + DebugMask::Mutex => crate::ffi::NGX_LOG_DEBUG_MUTEX, + DebugMask::Event => crate::ffi::NGX_LOG_DEBUG_EVENT, + DebugMask::Http => crate::ffi::NGX_LOG_DEBUG_HTTP, + DebugMask::Mail => crate::ffi::NGX_LOG_DEBUG_MAIL, + DebugMask::Stream => crate::ffi::NGX_LOG_DEBUG_STREAM, + } + } +} + #[cfg(test)] mod tests {