It looks like I've figured out. When I set b->last_buf to 0 for all the buffers and to 1 for just actual last buffer, everything is ok.
But then another question happens. Even if all the buffers have b->flush set to 1, I see my response only in one single chunk, after all the subrequests finished. How to actually flush the response buffer by buffer? -- Marat On Sun, Mar 24, 2013 at 9:12 PM, Marat Dakota <[email protected]> wrote: > Hi, > > I'm writing a handler module. It makes subrequests and uses body > filter for subrequests. > > Here is simplified handler code: > > static ngx_int_t > ngx_http_my_handler(ngx_http_request_t *r) { > > // ... Sending headers. > > ngx_chain_t *out; > ngx_buf_t *b; > > out = ngx_alloc_chain_link(r->pool); > b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); > > if (out == NULL || b == NULL) { > return NGX_HTTP_INTERNAL_SERVER_ERROR; > } > > b->pos = "aaa"; > b->last = "aaa" + 3; > b->memory = 1; > b->last_buf = 1; > > out->buf = b; > out->next = NULL; > > // ngx_http_my_subrequest() creates ngx_str_t from second argument > and calls ngx_http_subrequest(). > if (ngx_http_my_subrequest(r, "/uri1") != NGX_OK) { > return NGX_ERROR; > } > > if (ngx_http_my_subrequest(r, "/uri2") != NGX_OK) { > return NGX_ERROR; > } > > return ngx_http_output_filter(r, out); > } > > > Here is subrequest body filter: > > static ngx_int_t > ngx_http_my_body_filter(ngx_http_request_t *r, ngx_chain_t *in) > { > // ... Do something with subrequest's body in "in" argument. > > ngx_chain_t *out; > ngx_buf_t *b; > ngx_chain_t *cl; > > out = ngx_alloc_chain_link(r->pool); > b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); > > if (out == NULL || b == NULL) { > return NGX_HTTP_INTERNAL_SERVER_ERROR; > } > > // HERE BE DRAGONS. > > b->pos = "bbb"; > b->last = "bbb" + 3; > b->memory = 1; > b->last_buf = 1; > > out->buf = b; > out->next = NULL; > > // Discard subrequest's body. > for (cl = in; cl; cl = cl->next) { > cl->buf->pos = cl->buf->last; > cl->buf->file_pos = cl->buf->file_last; > } > > // We just put "bbb" to main response for each call of this body filter. > return ngx_http_output_filter(r->main, out); > } > > And everything works just fine. For example, if > ngx_http_my_body_filter is called twice for each (/uri1 and /uri2) > subrequest started from ngx_http_my_handler, the result will be > "aaabbbbbbbbbbbb". > > But if I replace "HERE BE DRAGONS" with a call to > ngx_http_my_subrequest(r->main, "/uri3"), let's suppose this > subrequest is being started only in second call of > ngx_http_my_body_filter for /uri1 subrequest started from > ngx_http_my_handler. The result will be "aaabbb", not > "aaabbbbbbbbbbbbbbbbbb" as I expect (and logs say all three > subrequests are processed ok). > > I guess my problem is about some magic with buffers and chains, but I > can't figure out what to fix and where. > > I would be thankful for any help. > > -- > Marat _______________________________________________ nginx-devel mailing list [email protected] http://mailman.nginx.org/mailman/listinfo/nginx-devel
