src/ngx_pagespeed.cc
// When passing the body of http responses between filters Nginx uses a linked
// list of buffers ("buffer chain"), again like Apache.  This constructs one of
// those lists from a StringPiece.  This is what you use when you need to pass a
// (potentially) longer string to nginx and want it to take ownership.
When passing the body of http responses between filters Nginx uses a linked
list of buffers ("buffer chain"), again like Apache.  This constructs one of
those lists from a StringPiece.  This is what you use when you need to pass a
(potentially) longer string to nginx and want it to take ownership.
When passing the body of http responses between filters Nginx uses a linked list of buffers ( " buffer chain " ) again like Apache . This constructs one of those lists from a StringPiece . This is what you use when you need to pass a ( potentially ) longer string to nginx and want it to take ownership .
ngx_int_t string_piece_to_buffer_chain(
    ngx_pool_t* pool, StringPiece sp, ngx_chain_t** link_ptr,
    bool send_last_buf, bool send_flush) {
  *link_ptr = NULL;
  ngx_chain_t* tail_link = NULL;
  ngx_uint_t offset;
  ngx_uint_t max_buffer_size = ngx_pagesize;
  for (offset = 0 ;
       offset < sp.size() ||
           (offset == 0 && sp.size() == 0);
       offset += max_buffer_size) {
    ngx_buf_t* b = static_cast<ngx_buf_t*>(ngx_calloc_buf(pool));
    if (b == NULL) {
      return NGX_ERROR;
    }
    if (sp.size() == 0) {
      CHECK(offset == 0);                                          
      b->pos = b->start = b->end = b->last = NULL;
      b->sync = 1;
    } else {
      CHECK(sp.size() > offset);
      ngx_uint_t b_size = sp.size() - offset;
      if (b_size > max_buffer_size) {
        b_size = max_buffer_size;
      }
      b->start = b->pos = static_cast<u_char*>(ngx_palloc(pool, b_size));
      if (b->pos == NULL) {
        return NGX_ERROR;
      }
      sp.copy(reinterpret_cast<char*>(b->pos), b_size, offset);
      b->last = b->end = b->pos + b_size;
      b->temporary = 1;  
    }
    ngx_chain_t* cl = static_cast<ngx_chain_t*>(ngx_alloc_chain_link(pool));
    if (cl == NULL) {
      return NGX_ERROR;
    }
    cl->buf = b;
    cl->next = NULL;
    if (*link_ptr == NULL) {
      *link_ptr = cl;
    } else {
      CHECK(tail_link != NULL);
      tail_link->next = cl;
    }
    tail_link = cl;
  }
  CHECK(tail_link != NULL);
  if (send_flush) {
    tail_link->buf->flush = true;
  }
  if (send_last_buf) {
    tail_link->buf->last_buf = true;
  }
  return NGX_OK;
}
ngx_int_t string_piece_to_buffer_chain ( ngx_pool_t * pool , StringPiece sp , ngx_chain_t * * link_ptr , bool send_last_buf , bool send_flush ) { * link_ptr = NULL ; ngx_chain_t * tail_link = NULL ; ngx_uint_t offset ; ngx_uint_t max_buffer_size = ngx_pagesize ; for ( offset = 0 ; offset < sp . size ( ) || ( offset == 0 && sp . size ( ) == 0 ) ; offset += max_buffer_size ) { ngx_buf_t * b = static_cast < ngx_buf_t * > ( ngx_calloc_buf ( pool ) ) ; if ( b == NULL ) { return NGX_ERROR ; } if ( sp . size ( ) == 0 ) { CHECK ( offset == 0 ) ; b -> pos = b -> start = b -> end = b -> last = NULL ; b -> sync = 1 ; } else { CHECK ( sp . size ( ) > offset ) ; ngx_uint_t b_size = sp . size ( ) - offset ; if ( b_size > max_buffer_size ) { b_size = max_buffer_size ; } b -> start = b -> pos = static_cast < u_char * > ( ngx_palloc ( pool , b_size ) ) ; if ( b -> pos == NULL ) { return NGX_ERROR ; } sp . copy ( reinterpret_cast < char * > ( b -> pos ) , b_size , offset ) ; b -> last = b -> end = b -> pos + b_size ; b -> temporary = 1 ; } ngx_chain_t * cl = static_cast < ngx_chain_t * > ( ngx_alloc_chain_link ( pool ) ) ; if ( cl == NULL ) { return NGX_ERROR ; } cl -> buf = b ; cl -> next = NULL ; if ( * link_ptr == NULL ) { * link_ptr = cl ; } else { CHECK ( tail_link != NULL ) ; tail_link -> next = cl ; } tail_link = cl ; } CHECK ( tail_link != NULL ) ; if ( send_flush ) { tail_link -> buf -> flush = true ; } if ( send_last_buf ) { tail_link -> buf -> last_buf = true ; } return NGX_OK ; }
When passing the body of http responses between filters Nginx uses a linked
list of buffers ("buffer chain"), again like Apache.
When passing the body of http responses between filters Nginx uses a linked list of buffers ( " buffer chain " ) again like Apache .
// Below, *link_ptr will be NULL if we're starting the chain, and the head // chain link. // If non-null, the current last link in the chain. // How far into sp we're currently working on. // Other modules seem to default to ngx_pagesize. // If we need to send the last buffer bit and there's no data, we // should send a single empty buffer.  Otherwise we shouldn't // generate empty buffers. // Prepare a new nginx buffer to put our buffered writes into. // NOLINT // The purpose of this buffer is just to pass along last_buf. // Copy our writes over.  We're copying from sp[offset] up to // sp[offset + b_size] into b which has size b_size. // Identify this buffer as in-memory and mutable. // Prepare a chain link. // This is the first link in the returned chain. // Link us into the chain.