Unsafe Rust permits operations the compiler cannot fully verify for memory safety. It does not remove Rust’s safety rules; it makes the programmer responsible for upholding them where compiler checking stops. This is useful when integrating with dynamically allocated memory from C or other code outside Rust. section 3.0 section 3.1
Unsafe blocks and functions enable five categories of otherwise forbidden operation:
- Dereference raw pointers. section 3.1
- Call functions marked unsafe. section 3.1
- Implement unsafe traits, mutate static values, and access union fields. section 3.1
Reading a C-managed request body
An NGINX callback receives a raw request pointer across the C FFI boundary. The unsafe handler checks for a null pointer, converts it to a reference, validates request-body buffers, creates a byte slice with std::slice::from_raw_parts, and parses UTF-8. The surrounding code returns errors instead of assuming that foreign memory is initialized as expected. section 4.4
Listing 4.8 Request handler that can read off the request body
include!(concat!(env!("OUT_DIR"), "/nginx.rs"));
#[no_mangle]
pub unsafe extern "C" fn ngx_http_calculator_handler( #1
r: *mut ngx_http_request_t,
) -> ngx_int_t {
let rc = ngx_http_read_client_request_body(
r, Some(read_body_handler)); #2
if rc != 0 {
return rc;
}
0
}
unsafe extern "C" fn read_body_handler(
r: *mut ngx_http_request_t) { #3
if r.is_null() {
eprintln!("got null request in body handler");
return;
}
let request = &*r;
let body = match request_body_as_str(request) {
Ok(body) => body,
Err(e) => {
eprintln!("failed to parse body: {}", e);
return;
}
};
eprintln!("Read request body: {:?}", body); #4
}
unsafe fn request_body_as_str<'a>( #5
request: &'a ngx_http_request_t,
) -> Result<&'a str, &'static str> {
if request.request_body.is_null()
|| (*request.request_body).bufs.is_null()
|| (*(*request.request_body).bufs).buf.is_null()
{
return Err("Request body buffers
were not initialized as expected");
}
let buf = (*(*request.request_body).bufs).buf;
let start = (*buf).pos;
let len = (*buf).last.offset_from(start) as usize;
let body_bytes = std::slice::from_raw_parts(start, len);
let body_str = std::str::from_utf8(body_bytes)
.map_err(|_| "Body contains invalid UTF-8")?;
Ok(body_str)
}
Inspect the complete request-body handler, including C-compatible signatures, null checks, pointer dereferencing, buffer validation, and UTF-8 conversion. section 4.4



