# How can a content handler block on certain events before sending a response?

**URL:** <https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508>\
**Category:** NGINX\
**Created:** [November 23, 2010, 12:34am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508 "2010-11-23T00:34:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![okkezSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/85f322/32.png) [@okkezSS](https://www.ruby-forum.com/u/okkezSS)\
**Post date:** [November 23, 2010, 12:34am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508/1 "2010-11-23T00:34:31Z")

</div>

I’m writing an Nginx module and I’d like to better understand how Nginx  
content handlers work and how the Nginx main loop works.

As far as I know, Nginx content handler functions are supposed to create  
a chain link of buffers containing the response data, and then call  
ngx\_http\_output\_filter(r, &the\_chain\_link) which will then take care of  
passing this data to the next output filter and eventually sending the  
data to the HTTP client.

How does one deal with situations in which the content handler function  
cannot immediately generate a response? For example, suppose my content  
handler must first fetch some data from MySQL. Since Nginx is an evented  
server, I imagine that I need to do something like this:

1. Connect to MySQL and send a request to it.
2. Register the MySQL client file descriptor on the Nginx main loop.
3. The Nginx main loop notifies me when the MySQL fd becomes readable.
4. I read the MySQL response, generate HTTP response data, and call  
ngx\_http\_output\_filter().

But how do I do step 2? Which function do I need to call? What should I  
return in my content handler function after having executed step 2?  
NGX\_AGAIN?

---

<div class="post-metadata">

**Author:** ![foobarwidget](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/71c47a/32.png) [@foobarwidget](https://www.ruby-forum.com/u/foobarwidget)\
**Post date:** [November 23, 2010, 1:49am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508/2 "2010-11-23T01:49:53Z")

</div>

Hello!

On Tue, Nov 23, 2010 at 12:34:31AM +0100, Hongli L. wrote:

> cannot immediately generate a response? For example, suppose my content  
> NGX\_AGAIN?  
> From content handler you should return NGX\_DONE to indicate you  
> are going to send response later. Note that after returing NGX\_DONE  
> you are responsible for finalizing request as well, this should be  
> done via ngx\_http\_finalize\_request() call.

For an idea how to handle connection, data sending and receiving  
please follow upstream module (src/http/ngx\_http\_upstream.c) and  
handlers which use it (e.g. memcached module,  
src/http/modules/ngx\_http\_memcached\_module.c).

Working with events isn’t something trivial, but basically you’ll  
have to connect via ngx\_event\_connect\_peer(), set up appropriate  
read/write handlers in resulting connection structure and call  
ngx\_handle\_(read|write)\_event() as appropriate.

Maxim D.

---

<div class="post-metadata">

**Author:** ![foobarwidget](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/71c47a/32.png) [@foobarwidget](https://www.ruby-forum.com/u/foobarwidget)\
**Post date:** [November 23, 2010, 4:28am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508/3 "2010-11-23T04:28:10Z")

</div>

Hi,

> For example, suppose my content handler must first fetch some data from  
> MySQL.

Just take a look at ngx\_drizzle 😉

Best regards,  
Piotr S. \< [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) \>

---

<div class="post-metadata">

**Author:** ![foobarwidget](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/71c47a/32.png) [@foobarwidget](https://www.ruby-forum.com/u/foobarwidget)\
**Post date:** [November 24, 2010, 12:43am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508/4 "2010-11-24T00:43:46Z")

</div>

Maxim D. wrote in post #963250:

> Working with events isn’t something trivial, but basically you’ll  
> have to connect via ngx\_event\_connect\_peer(), set up appropriate  
> read/write handlers in resulting connection structure and call  
> ngx\_handle\_(read|write)\_event() as appropriate.

I need to use ngx\_add\_event for registering a read/write watcher, right?  
So I need to allocate an ngx\_event\_s struct, set its ‘handler’ member to  
my handler function, and call ngx\_add\_event(&evt, NGX\_READ\_EVENT, 0)? Do  
I need to set any other members for it to work? Do I need to zero the  
structure if I don’t set anything else?

What are appropriate times to call ngx\_handle\_read/write\_event? What do  
those functions do? Isn’t the main loop supposed to call event handler  
functions for me?

---

<div class="post-metadata">

**Author:** ![foobarwidget](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/71c47a/32.png) [@foobarwidget](https://www.ruby-forum.com/u/foobarwidget)\
**Post date:** [November 24, 2010, 2:13am UTC](https://www.ruby-forum.com/t/how-can-a-content-handler-block-on-certain-events-before-sending-a-response/199508/5 "2010-11-24T02:13:10Z")

</div>

Hello!

On Wed, Nov 24, 2010 at 12:43:46AM +0100, Hongli L. wrote:

> Maxim D. wrote in post #963250:
> 
> > Working with events isn’t something trivial, but basically you’ll  
> > have to connect via ngx\_event\_connect\_peer(), set up appropriate  
> > read/write handlers in resulting connection structure and call  
> > ngx\_handle\_(read|write)\_event() as appropriate.
> 
> I need to use ngx\_add\_event for registering a read/write watcher, right?

No. Depending on event method used there are different things  
required, e.g. with epoll and rtsig you have to call  
ngx\_add\_conn() to add connection to the event loop first. And  
calling ngx\_add\_event() isn’t needed (unless you are trying to do  
something non-standard or optimize specific case),  
ngx\_handle\_(read|write)\_event() will do it for you.

Use ngx\_event\_connect\_peer(), it will handle these details for  
you.

> So I need to allocate an ngx\_event\_s struct, set its ‘handler’ member to  
> my handler function, and call ngx\_add\_event(&evt, NGX\_READ\_EVENT, 0)? Do  
> I need to set any other members for it to work? Do I need to zero the  
> structure if I don’t set anything else?

See above, use ngx\_event\_connect\_peer().

You may do the same steps by hand but this anyway will require  
almost the same code, connection structure and so on.

> What are appropriate times to call ngx\_handle\_read/write\_event? What do  
> those functions do? Isn’t the main loop supposed to call event handler  
> functions for me?

You should call ngx\_handle\_(read|write)\_event() when you’ve done  
processing event (to re-enable this particular event in event  
loop, or to disable it if level-triggered event method used and  
event is still ready) or when you are going to wait for another  
event (to activate particular event in the even loop).

Don’t hesitate to look into event/ngx\_event.c. These functions  
basically call ngx\_add\_event/ngx\_del\_event based on various  
conditions depending on event method used.

Maxim D.
