diff --git a/Cargo.lock b/Cargo.lock
index 25ee3863..8276a90a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -444,7 +444,7 @@ dependencies = [
 
 [[package]]
 name = "nginx-sys"
-version = "0.1.0"
+version = "0.2.0"
 dependencies = [
  "bindgen",
  "duct",
@@ -456,7 +456,7 @@ dependencies = [
 
 [[package]]
 name = "ngx"
-version = "0.3.0-beta"
+version = "0.4.0-beta"
 dependencies = [
  "nginx-sys",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 6eac1e04..67217490 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,7 +6,7 @@ members = [
 
 [package]
 name = "ngx"
-version = "0.3.0-beta"
+version = "0.4.0-beta"
 edition = "2021"
 autoexamples = false
 categories = ["api-bindings", "network-programming"]
@@ -19,7 +19,7 @@ keywords = ["nginx", "module", "sys"]
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-nginx-sys = { path = "nginx-sys", version = "0.1"}
+nginx-sys = { path = "nginx-sys", version = "0.2"}
 
 [badges]
 maintenance = { status = "experimental" }
diff --git a/nginx-sys/Cargo.toml b/nginx-sys/Cargo.toml
index cca1d023..ec4df4b7 100644
--- a/nginx-sys/Cargo.toml
+++ b/nginx-sys/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "nginx-sys"
-version = "0.1.0"
+version = "0.2.0"
 edition = "2021"
 categories = ["external-ffi-bindings"]
 description = "FFI bindings to NGINX"
diff --git a/nginx-sys/src/lib.rs b/nginx-sys/src/lib.rs
index df463c8b..9b4fcefd 100644
--- a/nginx-sys/src/lib.rs
+++ b/nginx-sys/src/lib.rs
@@ -68,11 +68,9 @@ pub use bindings::*;
 /// let data: &str = "example"; // The string to convert
 /// let ptr = str_to_uchar(pool, data);
 /// ```
-pub fn str_to_uchar(pool: *mut ngx_pool_t, data: &str) -> *mut u_char {
-    let ptr: *mut u_char = unsafe { ngx_palloc(pool, data.len() as _) as _ };
-    unsafe {
-        copy_nonoverlapping(data.as_ptr(), ptr, data.len());
-    }
+pub unsafe fn str_to_uchar(pool: *mut ngx_pool_t, data: &str) -> *mut u_char {
+    let ptr: *mut u_char = ngx_palloc(pool, data.len() as _) as _;
+    copy_nonoverlapping(data.as_ptr(), ptr, data.len());
     ptr
 }
 
@@ -99,9 +97,14 @@ impl ngx_str_t {
     /// * `pool` - A pointer to the nginx memory pool (`ngx_pool_t`).
     /// * `data` - The `String` from which to create the nginx string.
     ///
+    /// # Safety
+    /// This function is marked as unsafe because it accepts a raw pointer argument. There is no
+    /// way to know if `pool` is pointing to valid memory. The caller must provide a valid pool to
+    /// avoid indeterminate behavior.
+    ///
     /// # Returns
     /// An `ngx_str_t` instance representing the given `String`.
-    pub fn from_string(pool: *mut ngx_pool_t, data: String) -> Self {
+    pub unsafe fn from_string(pool: *mut ngx_pool_t, data: String) -> Self {
         ngx_str_t {
             data: str_to_uchar(pool, data.as_str()),
             len: data.len() as _,
@@ -115,9 +118,14 @@ impl ngx_str_t {
     /// * `pool` - A pointer to the nginx memory pool (`ngx_pool_t`).
     /// * `data` - The string slice from which to create the nginx string.
     ///
+    /// # Safety
+    /// This function is marked as unsafe because it accepts a raw pointer argument. There is no
+    /// way to know if `pool` is pointing to valid memory. The caller must provide a valid pool to
+    /// avoid indeterminate behavior.
+    ///
     /// # Returns
     /// An `ngx_str_t` instance representing the given string slice.
-    pub fn from_str(pool: *mut ngx_pool_t, data: &str) -> Self {
+    pub unsafe fn from_str(pool: *mut ngx_pool_t, data: &str) -> Self {
         ngx_str_t {
             data: str_to_uchar(pool, data),
             len: data.len() as _,
@@ -180,11 +188,16 @@ impl TryFrom<ngx_str_t> for &str {
 /// let value: &str = "value"; // The value to add
 /// let result = add_to_ngx_table(table, pool, key, value);
 /// ```
-pub fn add_to_ngx_table(table: *mut ngx_table_elt_t, pool: *mut ngx_pool_t, key: &str, value: &str) -> Option<()> {
+pub unsafe fn add_to_ngx_table(
+    table: *mut ngx_table_elt_t,
+    pool: *mut ngx_pool_t,
+    key: &str,
+    value: &str,
+) -> Option<()> {
     if table.is_null() {
         return None;
     }
-    unsafe { table.as_mut() }.map(|table| {
+    table.as_mut().map(|table| {
         table.hash = 1;
         table.key.len = key.len() as _;
         table.key.data = str_to_uchar(pool, key);
diff --git a/src/http/request.rs b/src/http/request.rs
index ba0e03f3..1594f17f 100644
--- a/src/http/request.rs
+++ b/src/http/request.rs
@@ -199,7 +199,7 @@ impl Request {
     /// See https://nginx.org/en/docs/dev/development_guide.html#http_request
     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 _ };
-        add_to_ngx_table(table, self.0.pool, key, value)
+        unsafe { add_to_ngx_table(table, self.0.pool, key, value) }
     }
 
     /// Add header to the `headers_out` object.
@@ -207,7 +207,7 @@ impl Request {
     /// See https://nginx.org/en/docs/dev/development_guide.html#http_request
     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 _ };
-        add_to_ngx_table(table, self.0.pool, key, value)
+        unsafe { add_to_ngx_table(table, self.0.pool, key, value) }
     }
 
     /// Set response body [Content-Length].
@@ -259,7 +259,7 @@ impl Request {
     /// Perform internal redirect to a location
     pub fn internal_redirect(&self, location: &str) -> Status {
         assert!(!location.is_empty(), "uri location is empty");
-        let uri_ptr = &mut ngx_str_t::from_str(self.0.pool, location) as *mut _;
+        let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.0.pool, location) as *mut _ };
 
         // FIXME: check status of ngx_http_named_location or ngx_http_internal_redirect
         if location.starts_with('@') {
@@ -285,7 +285,7 @@ impl Request {
         module: &ngx_module_t,
         post_callback: unsafe extern "C" fn(*mut ngx_http_request_t, *mut c_void, ngx_int_t) -> ngx_int_t,
     ) -> Status {
-        let uri_ptr = &mut ngx_str_t::from_str(self.0.pool, uri) as *mut _;
+        let uri_ptr = unsafe { &mut ngx_str_t::from_str(self.0.pool, uri) as *mut _ };
         // -------------
         // allocate memory and set values for ngx_http_post_subrequest_t
         let sub_ptr = self.pool().alloc(std::mem::size_of::<ngx_http_post_subrequest_t>());