The meaning of ngx_http_request_t.out ?

Maxim Dounin mdounin at mdounin.ru
Wed Aug 28 11:40:01 UTC 2013


Hello!

On Wed, Aug 28, 2013 at 05:54:39PM +0800, 邓尧 wrote:

> On Tue, Aug 27, 2013 at 10:21 PM, Maxim Dounin <mdounin at mdounin.ru> wrote:
> 
> > Hello!
> >
> > On Tue, Aug 27, 2013 at 11:21:38AM +0800, 邓尧 wrote:
> >
> > > Hi,
> > > I'm writing an nginx module, it does something similar to the sub module.
> > > After some research I succeeded in handling the ngx_chain_t pointer
> > passed
> > > to my body filter. My module seems to work well for static files.
> > > When my module is handling PHP responses (fastcgi), sometimes the
> > > ngx_chain_t pointer is NULL. I simply call the next body filter in such
> > > situation like the sub module body filter. However function
> > > ngx_http_write_filter() will fail, because r->out isn't NULL
> > > and the buf's in r->out are of zero size.
> > > My questions are: what's the meaning of r->out? how should I modify it in
> > > my body filter ? Could I simply return NGX_OK in my body filter without
> > > calling the next body filter if the ngx_chain_t pointer is NULL ?
> >
> > The r->out is write filter's private data, you shouldn't touch it
> > in your module.  And it shouldn't contain zero size non-special
> > buffers, if it does - there is a bug somewhere (most likely in
> > your filter).
> 
> What are the most likely reasons for a buffer in r->out to be zero sized
> and non-special ? I do believe the bug is somewhere in my body filter, but
> I checked many times, cannot find it. My body filter's work flow is like
> the following:
> 1. create a private empty chain, ctx->out.
> 2. search the input chain for patterns
> 3. if a matched pattern is found, append three ngx_buf_t structures (one
> for the substitution string, two for the data surrounding the matched
> pattern) to ctx->out, the one used for the substitution string is zerorized
> then only three members are set: pos, last, memory. The other two are
> memcpy()ed from the original buffer then:
>     * pos, last, file_pos, file_last are modified accordingly
>     * last_buf, last_in_chain are cleared (last_buf & last_in_chain of the
> final chain are still set)
>     * shadow is set to NULL
> 4. if no pattern is found, append the ngx_buf_t structure to ctx->out, then
> clear last_buf & last_in_chain.
> 5. when a pattern is across two buffers, well, it's ignored, should be no
> problem.
> 6. feed ctx->out to the next body filter
> 7. return the code from the above function call after some cleaning up.

I suspect your code reuses/modifies buffers passed to next body 
filter before they are sent.  Note you should keep track of 
buffers passed to next filters and don't reuse them before they 
are fully sent (usually ngx_chain_update_chains() function is used 
for dirty work).

Alternatively, if you modify ngx_buf_t structures your code got 
from previous body filters - your modifications may confuse 
tracking code and buffers may be reused there (again, before they 
are sent).

-- 
Maxim Dounin
http://nginx.org/en/donation.html



More information about the nginx-devel mailing list