liveBook · Manning

Ngx_http_send_header

As explained in Refactoring to Rust

ngx_http_send_header is an NGINX API function that sends HTTP response header data on a connection.

ngx_http_send_header sends prepared HTTP response headers on an NGINX connection. Set the status code and Content-Length before calling it when the response has a non-chunked body. section 4.6

Prepare the response in this order:

  • Borrow the request’s output headers and assign the status code. section 4.6
  • Convert the response body to bytes and set Content-Length to its byte length. section 4.6
  • Call ngx_http_send_header and treat a nonzero return value as failure. section 4.6

Sending calculator response headers

let headers = &mut request.headers_out; headers.status = status_code; let response_bytes = response_body.as_bytes(); headers.content_length_n = response_bytes.len() as off_t; let rc = ngx_http_send_header(request); if rc != 0 { return Err("failed to send headers"); } section 4.6

unsafe fn write_response(
  request: &mut ngx_http_request_t,
  response_body: &str,
  status_code: ngx_uint_t,
) -> Result<(), &'static str> {
  let headers = &mut request.headers_out;

  headers.status = status_code;

  let response_bytes = response_body.as_bytes();
  headers.content_length_n = response_bytes.len() as off_t;

  let rc = ngx_http_send_header(request);  #1
  if rc != 0 {
    return Err("failed to send headers");
  }

  let buf_p =
    ngx_pcalloc(request.pool, std::mem::size_of::<
      ngx_buf_t>() as size_t)  #2
      as *mut ngx_buf_t;
  if buf_p.is_null() {
    return Err("Failed to allocate buffer");
  }

  let buf = &mut (*buf_p);

  buf.set_last_buf(1);  #3
  buf.set_last_in_chain(1);
  buf.set_memory(1);

  let response_buffer =
    ngx_pcalloc(request.pool, response_bytes.len() as size_t);  #4
  if response_buffer.is_null() {
    return Err("Failed to allocate response buffer");
  }

  std::ptr::copy_nonoverlapping(  #5
    response_bytes.as_ptr(),
    response_buffer as *mut u8,
    response_bytes.len(),
  );

  buf.pos = response_buffer as *mut u8;
  buf.last = response_buffer.offset(
    response_bytes.len() as isize) as *mut u8;

  let mut out_chain = ngx_chain_t {
    buf,
    next: std::ptr::null_mut(),
  };

  if ngx_http_output_filter(request, &mut out_chain) != 0 {  #6
    return Err("Failed to perform http output filter chain");
  }

  Ok(())
}

View the surrounding unsafe response-writing function, including header preparation, NGINX allocation, buffer initialization, and body output. section 4.6

How Refactoring to Rust covers it

How deep it goes
Explains required status and Content-Length assignments plus return-value checking, then stops short of header internals.
Examples
Uses a Rust calculator handler that returns an evaluated result through an NGINX HTTP response.
What it assumes
Assumes familiarity with NGINX request structures and Rust pointers while demonstrating header preparation from basic response data.
What you can do after
Apply it via the NGINX C API to send correctly prepared headers from an unsafe Rust request handler.
How it connects
Connects HTTP response headers with Content-Length, request objects, NGINX memory pools, and output filter chains.

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.