# Upstream with multiple request reply

**URL:** <https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814>\
**Category:** NGINX\
**Created:** [January 16, 2012, 9:41pm UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814 "2012-01-16T21:41:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [January 16, 2012, 9:41pm UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/1 "2012-01-16T21:41:08Z")

</div>

Hi all,

I’m trying to write an upstream which have to do multiple request /  
reply  
with backend, for one frontend request.

Currently,

- I’m writing first request to backend in create\_request handler, write  
data into r-\>upstream-\>request\_bufs, and returning NGX\_OK
- Nginx call me on process\_header. I can read data from  
r-\>upstream-\>buffer. I can loop on process\_header if I return NGX\_AGAIN.  
But I’m not able to send more data to backend. I try to add buffer in  
r-\>upstream-\>request\_bufs, in r-\>upstream-\>request\_bufs-\>next, nothing  
work.

Anybody know how to send data to backend in the process\_header callback  
?

Regards,

Bertrand

---

<div class="post-metadata">

**Author:** ![Bertrand\_P](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e19b73/32.png) [@Bertrand\_P](https://www.ruby-forum.com/u/Bertrand_P)\
**Post date:** [January 16, 2012, 10:20pm UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/2 "2012-01-16T22:20:47Z")

</div>

Hello!

On Mon, Jan 16, 2012 at 09:40:26PM +0100, Bertrand P. wrote:

> But I’m not able to send more data to backend. I try to add buffer in  
> r-\>upstream-\>request\_bufs, in r-\>upstream-\>request\_bufs-\>next, nothing work.
> 
> Anybody know how to send data to backend in the process\_header callback ?

The upstream module is designed to handle “single request - single  
response” model, it’s not capable of sending multiple requests to  
backend.

Maxim D.

---

<div class="post-metadata">

**Author:** ![Bertrand\_P](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e19b73/32.png) [@Bertrand\_P](https://www.ruby-forum.com/u/Bertrand_P)\
**Post date:** [January 16, 2012, 10:46pm UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/3 "2012-01-16T22:46:43Z")

</div>

Hi,

Arg, it’s not a good news 🙂

Do you think I can do ngx\_http\_subrequest to do some additional request  
to  
back end ?  
How to say to nginx to wait for subrequest before calling create\_request  
?

Regards,

Bertrand

---

<div class="post-metadata">

**Author:** ![Bertrand\_P](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e19b73/32.png) [@Bertrand\_P](https://www.ruby-forum.com/u/Bertrand_P)\
**Post date:** [January 16, 2012, 11:17pm UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/4 "2012-01-16T23:17:42Z")

</div>

Hello!

On Mon, Jan 16, 2012 at 10:45:58PM +0100, Bertrand P. wrote:

> Hi,
> 
> Arg, it’s not a good news 🙂
> 
> Do you think I can do ngx\_http\_subrequest to do some additional request to  
> back end ?  
> How to say to nginx to wait for subrequest before calling create\_request ?

If you are ok with _independent_ requests to backend (that is, you  
just need to requests two happen, but don’t need to implement some  
complex protocol), than using subrequests is right way to go.

See e.g. addition filter module sources for simple subrequest  
usage example, or ssi module sources for more complex one.

Maxim D.

> > On Mon, Jan 16, 2012 at 09:40:26PM +0100, Bertrand P. wrote:
> > 
> > > r-\>upstream-\>buffer. I can loop on process\_header if I return NGX\_AGAIN.  
> > > Maxim D.
> > 
> > * * *
> > 
> > nginx mailing list  
> > [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> > [mailman.nginx.org archive](http://mailman.nginx.org/mailman/listinfo/nginx)

---

<div class="post-metadata">

**Author:** ![Bertrand\_P](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e19b73/32.png) [@Bertrand\_P](https://www.ruby-forum.com/u/Bertrand_P)\
**Post date:** [January 17, 2012, 4:15am UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/5 "2012-01-17T04:15:20Z")

</div>

Hi,

This demo maybe helpful.

> **[GitHub - bigplum/nginx-http-nphase-module](https://github.com/bigplum/nginx-http-nphase-module)**
>
> Contribute to bigplum/nginx-http-nphase-module development by creating an account on GitHub.

Posted at Nginx Forum:

> **[Re: Upstream with multiple request reply](https://forum.nginx.org/read.php?2,221329,221339#msg-221339)**
>
> Hi all, I'm trying to write an upstream which have to do multiple request / reply with backend, for one frontend request. Currently, - I'm writing first request to backend in create\_request handler, write data into r-\>upstream-\>request\_bufs,...

---

<div class="post-metadata">

**Author:** ![Bertrand\_P](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e19b73/32.png) [@Bertrand\_P](https://www.ruby-forum.com/u/Bertrand_P)\
**Post date:** [January 17, 2012, 11:29am UTC](https://www.ruby-forum.com/t/upstream-with-multiple-request-reply/215814/6 "2012-01-17T11:29:30Z")

</div>

Hi all,

Finally, I do not use subrequest, I write the following code, inspired  
from  
upstream module.  
I call ngx\_http\_upstream\_send\_another\_request from process\_header. It’s  
working fine.

Feel free to comment my code, if you think I can have problem, memory  
allocation, segfault or others.

Regards,

Bertrand

static void  
ngx\_http\_upstream\_send\_another\_request\_dummy\_handler(ngx\_http\_request\_t  
\*r,  
ngx\_http\_upstream\_t \*u)  
{  
ngx\_log\_debug0(NGX\_LOG\_DEBUG\_HTTP, r-\>connection-\>log, 0,  
“http upstream send another request dummy handler”);  
}

static ngx\_int\_t  
ngx\_http\_upstream\_send\_another\_request(ngx\_http\_request\_t \*r,  
ngx\_http\_upstream\_t \*u);

static void  
ngx\_http\_upstream\_send\_another\_request\_handler(ngx\_http\_request\_t \*r,  
ngx\_http\_upstream\_t \*u)  
{  
ngx\_log\_debug0(NGX\_LOG\_DEBUG\_HTTP, r-\>connection-\>log, 0,  
“http upstream send another request handler”);

```
ngx_http_upstream_send_another_request(r, u);

```

}

static ngx\_int\_t  
ngx\_http\_upstream\_send\_another\_request(ngx\_http\_request\_t \*r,  
ngx\_http\_upstream\_t \*u)  
{  
ngx\_int\_t rc;  
ngx\_connection\_t \*c;

```
c = u->peer.connection;

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
               "http upstream send another request");
//
// if (!u->request_sent && ngx_http_upstream_test_connect(c) != 

```

NGX\_OK)  
{  
// ngx\_http\_upstream\_next(r, u, NGX\_HTTP\_UPSTREAM\_FT\_ERROR);  
// return;  
// }

```
c->log->action = "sending request to upstream";

rc = ngx_output_chain(&u->output, u->request_sent ? NULL :

```

u-\>request\_bufs);

```
u->request_sent = 1;

if (rc == NGX_ERROR) {
    return rc;
}

if (c->write->timer_set) {
    ngx_del_timer(c->write);
}

if (rc == NGX_AGAIN) {
   ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   "ngx_output_chain return NGX_AGAIN");

    u->write_event_handler =

```

ngx\_http\_upstream\_send\_another\_request\_handler;

```
    ngx_add_timer(c->write, u->conf->send_timeout);

    if (ngx_handle_write_event(c->write, u->conf->send_lowat) !=

```

NGX\_OK) {  
return NGX\_ERROR;  
}

```
    return NGX_AGAIN;
}

/* rc == NGX_OK */

if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
    if (ngx_tcp_push(c->fd) == NGX_ERROR) {
        ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
                      ngx_tcp_push_n " failed");
        return NGX_ERROR;
    }

    c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
}

ngx_add_timer(c->read, u->conf->read_timeout);

```

// #if 1  
// if (c-\>read-\>ready) {  
//  
// /\* post aio operation _/  
//  
// /_  
// \* TODO comment  
// \* although we can post aio operation just in the end  
// \* of ngx\_http\_upstream\_connect() CHECK IT !!!  
// \* it’s better to do here because we postpone header buffer  
allocation  
// \*/  
//  
// return u-\>process\_header®;  
// }  
// #endif

```
u->write_event_handler =

```

ngx\_http\_upstream\_send\_another\_request\_dummy\_handler;

```
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
    return NGX_ERROR;
}

return NGX_AGAIN;

```

}
