title: nginx module: capture whole response body
body: <p>Although Nginx is a really interesting piece of software, the lack of documentation is making me crazy.</p>
  
  <p><strong>Goal:</strong> capture the whole response body, which would be logged on the server.</p>
  
  <p><strong>Problem:</strong> I have always a single buffer which size is ZERO.</p>
  
  <p><strong>Approach</strong></p>
  
  <p>I would expect to be able to accomplish this requirement with a <a href="http://www.evanmiller.org/nginx-modules-guide.html#filters-body" rel="nofollow">body filter</a>, which would "wait" for <code>last_buf</code> before iterate the full buffers chain.</p>
  
  <pre><code>/**
   * @param   ngx_http_request_t     *r     HTTP request
   * @param   ngx_chain_t            *in    Buffer chain
   */
  static ngx_int_t
  create_response_snapshot(ngx_http_request_t *r, ngx_chain_t *in)
  {
      ngx_chain_t *chain = NULL;
      int chain_contains_last_buffer = 0;
      size_t buffer_size = 0;
  
      // check if body is complete
      chain = in;
      for ( ; ; )
      {
          if (chain-&gt;buf-&gt;last_buf)
          {
              chain_contains_last_buffer = 1;
          }
  
          if (NULL == chain-&gt;next)
              break;
  
          chain = chain-&gt;next;
      }
  
      if (0 == chain_contains_last_buffer)
      {
          // response is not complete
          return ngx_http_next_body_filter(r, in);
      }
  
      // Response Content-Length
      ngx_log_error(NGX_LOG_ALERT,r-&gt;connection-&gt;log,0,"Content-Length: %d",
                    r-&gt;headers_out.content_length_n);
  
      // lets iterate buffers chain
      for (chain = in; NULL != chain; chain = chain-&gt;next)
      {
          buffer_size = ngx_buf_size(chain-&gt;buf);
          ngx_log_error(NGX_LOG_ALERT,r-&gt;connection-&gt;log,0,"buffer_size#%d",buffer_size);
      }
  
      return ngx_http_next_body_filter(r, in);
  }
  </code></pre>