Subrequests from body filters

Marat Dakota dakota at brokenpipe.ru
Sun Mar 24 21:15:25 UTC 2013


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 <dakota at brokenpipe.ru> 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



More information about the nginx-devel mailing list