liveBook · Manning

Payload

As explained in Refactoring to Rust

An HTTP request body is the data payload carried in an HTTP request separately from its headers and request line.

An HTTP POST payload is the data carried in the request body. An NGINX handler receives a request pointer, but that does not mean the body has already been loaded. It must ask NGINX to read the body before Rust can use its contents. section 4.4

To read a payload in a Rust NGINX handler:

  • Call `ngx_http_read_client_request_body` with the request pointer and a callback. The callback runs when the body has been read. section 4.4
  • In the callback, reject a null request pointer. Check that the request body, its buffer chain, and the buffer are initialized before dereferencing them. section 4.4 section 4.4.2
  • Use the buffer’s start and end pointers to determine its length, then form a byte slice. If the payload is expected to be text, validate those bytes with `std::str::from_utf8` before returning a string slice tied to the request’s lifetime. section 4.4 section 4.4.2

A POST payload in practice

`curl -X POST -d '3 4 * 2 -' http://localhost:8080/calculate` sends `3 4 * 2 -` as the request body. The handler can log `Read request body: "3 4 * 2 -"`. At this stage, it does not write an HTTP response, so the curl command keeps waiting. section 4.4.2

unsafe fn request_body_as_str<'a>(
  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)
}

The helper shows the boundary between NGINX-owned buffer pointers and a Rust string slice, including initialization checks and UTF-8 validation. section 4.4

How Refactoring to Rust covers it

How deep it goes
Works through callback-based loading, pointer checks, buffer slicing, and UTF-8 validation; stops before writing an HTTP response.
Examples
Uses a curl POST carrying `3 4 * 2 -` and a handler that logs the extracted body.
What it assumes
Builds on request buffers and C pointers while showing the Rust checks needed to read them.
What you can do after
Build it from scratch: read an NGINX request body into a checked Rust string slice for a handler.
How it connects
Connects HTTP POST to NGINX callbacks, Rust FFI, raw pointers, lifetimes, and UTF-8 validation.

Also explained in

Compare how 8 books explain payload →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Refactoring to Rust. The section links point to the parts of the book it draws on.