Asynchronous request processing using LUA in Nginx

2,238 views
Skip to first unread message

pushpadk

unread,
Jul 17, 2014, 11:48:47 AM7/17/14
to openre...@googlegroups.com
I have one Lua script written which process Request header and produce response. I have two main doubts.

1. In my LUA script file i am getting username:password from Authorization: header but to authenticate username i have to contact to some other server. which will send response asynchronously to me.
   how can i suspend/resume request processing in LUA itself without affecting other request ?

2.  how can Nginx work process and Lua script can communicate to each other ?
 

Vladislav Manchev

unread,
Jul 17, 2014, 1:25:34 PM7/17/14
to openre...@googlegroups.com
Hi,

For #1 you could use subrequests [1][2] or ngx.thread API [3][4] to spawn() and then wait() on a thread, in both cases the main request won't return before the subrequest or ngx.thread returns.

Not sure what you mean by #2 - ngx_lua module allows you to "communicate" with the nginx core and modules by using Lua, what are you exactly trying to accomplish?

[1]: https://github.com/openresty/lua-nginx-module#ngxlocationcapture
[2]: https://github.com/openresty/lua-nginx-module#ngxlocationcapture_multi
[3]: https://github.com/openresty/lua-nginx-module#ngxthreadspawn
[4]: https://github.com/openresty/lua-nginx-module#ngxthreadwait


Best,
Vladislav


--
You received this message because you are subscribed to the Google Groups "openresty-en" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openresty-en...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pierre-Yves Gérardy

unread,
Jul 18, 2014, 4:51:24 PM7/18/14
to openre...@googlegroups.com
On Thursday, July 17, 2014 7:25:34 PM UTC+2, Vladislav Manchev wrote:
Hi,

For #1 you could use subrequests [1][2] or ngx.thread API [3][4] to spawn() and then wait() on a thread, in both cases the main request won't return before the subrequest or ngx.thread returns.

Not sure what you mean by #2 - ngx_lua module allows you to "communicate" with the nginx core and modules by using Lua, what are you exactly trying to accomplish?

[1]: https://github.com/openresty/lua-nginx-module#ngxlocationcapture
[2]: https://github.com/openresty/lua-nginx-module#ngxlocationcapture_multi

Lapis has an independent HTTP helper that uses that method to make external HTTP requests, and it could be used as an example.
You must also create a $_url nginx variable in your config file. It isn't mentioned in the documentation, but in a comment in the source.

kamal pushpad

unread,
Jul 21, 2014, 2:24:06 AM7/21/14
to openre...@googlegroups.com
HI Vladislav,

Thanks for you response. Here is my second issue.

We have one Library hosted in Nginx process  which talks to external server (Not through HTTP).  This library send username:password to external server and response contains whether user is authenticated or not.  Our response handler function is called from epoll event loop as request/response is totally asyn.

So our use case is like this , From Lua script we want to fetch username:password coming with HTTP request and somehow pass it to that library and get response back into our LUA code asynchronously. it should not affect other ongoing request.

I want an efficient way to implement this using Nginx + LUA.

thanks
kamal 


--
You received this message because you are subscribed to a topic in the Google Groups "openresty-en" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/openresty-en/8PJXExL2zIA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to openresty-en...@googlegroups.com.

Yichun Zhang (agentzh)

unread,
Jul 21, 2014, 4:20:10 PM7/21/14
to openresty-en
Hello!

On Sun, Jul 20, 2014 at 11:24 PM, kamal pushpad wrote:
> We have one Library hosted in Nginx process which talks to external server
> (Not through HTTP). This library send username:password to external server
> and response contains whether user is authenticated or not. Our response
> handler function is called from epoll event loop as request/response is
> totally asyn.
>
> So our use case is like this , From Lua script we want to fetch
> username:password coming with HTTP request

This depends on exactly how your username and password are encoded in
the HTTP requests. You did not provide enough info. If the info is
provided via the HTTP Authentication method, then you can just read
the nginx variables $remote_user and $remote_passwd provided by
ngx_coolkit (enabled in OpenResty by default) from within Lua via the
ngx.var.VARIABLE API. See

https://github.com/FRiCKLE/ngx_coolkit

https://github.com/openresty/lua-nginx-module#ngxvarvariable

I strongly suggest you read through ngx_lua's official manual
carefully to save time (both yours and ours ;) ):

https://github.com/openresty/lua-nginx-module#readme

> and somehow pass it to that
> library and get response back into our LUA code asynchronously. it should
> not affect other ongoing request.
>

The term "asynchronously" can be very confusing without a relative
object. I think you actually mean "nonblocking IO" here.

From your vague description, I think you may find the subrequest API
provided by ngx_lua helpful for talking to other nginx C modules from
within Lua:

https://github.com/openresty/lua-nginx-module#ngxlocationcapture

> I want an efficient way to implement this using Nginx + LUA.
>

A potentially more efficient (and more flexible) way is to rewrite
your C/C++ library's functionality with Lua atop ngx_lua's cosocket
API. See those lua-resty-* libraries like lua-resty-mysql and
lua-resty-redis for such real-world examples.

Regards,
-agentzh

Vladislav Manchev

unread,
Jul 21, 2014, 4:22:52 PM7/21/14
to openre...@googlegroups.com
One request can never block other requests so nothing to worry about.

You'll only need to (probably) block the current request while getting the result from your library, as it seems that the current request depends on this result.

If you don't want to block the current request then you could use subrequests, of course.

Maybe provide some code so we can help out?


Best,
Vladislav


kamal pushpad

unread,
Jul 23, 2014, 2:14:42 PM7/23/14
to openre...@googlegroups.com
HI ,

Thanks for your valuable response.  Here is my problem description.


I want to use LUA scripts for cookie and other request header processing. Everything is working fine except user authentication.


For user authentication i need to pass username and password to some Library.

1. This LIB is written in C by somebody else. We have to just use it.
2. LIB uses IPC internally to communicate to other process for authenticating user.
3. LIB gives us FD , which we will register in Nginx's main epoll . This way it will call our registered function where we will check if user is valid or not.

For processing request header I have LUA script.

1. I am able to process Authorization header and get username and password from request In lua.
2. Not all request require user authentication as other request might get authenticated using cookies.

Now provided i have this LIB for user authentication and LUA script , how do i  efficiently integrate them.


One solution using subrequest.

1. From Lua i will send subrrequest which will  carry username and password.
2. This subrequest  will be handled  by another nginx module which we will write.  let say AUTH module.
3. upon receiving subrequest  ,AUTH module will pass username and password to our LIB
4. Once response is received from LIB , AUTH module will send response which we will be able to get in our LUA script.
5.  since subrequest is Non-blocking , it will affect the other request.

Is above approach correct ?
Is there any other alternative available that i can use ?

If you need more info , please let me know.
 

Thanks
kamal  


Yichun Zhang (agentzh)

unread,
Jul 23, 2014, 3:06:56 PM7/23/14
to openresty-en
Hello!

On Wed, Jul 23, 2014 at 11:14 AM, kamal pushpad wrote:
> 1. This LIB is written in C by somebody else. We have to just use it.
> 2. LIB uses IPC internally to communicate to other process for
> authenticating user.

Be careful about the IPC part here. Are you sure it is doing
nonblocking IO there?

> For processing request header I have LUA script.
>

BTW, it is Lua not LUA. See http://www.lua.org/about.html#name

> One solution using subrequest.
>
> 1. From Lua i will send subrrequest which will carry username and password.
> 2. This subrequest will be handled by another nginx module which we will
> write. let say AUTH module.
> 3. upon receiving subrequest ,AUTH module will pass username and password
> to our LIB
> 4. Once response is received from LIB , AUTH module will send response which
> we will be able to get in our LUA script.
> 5. since subrequest is Non-blocking , it will affect the other request.
>

Subrequests inherit their parent requests' request headers by default.
And this approach should work.

> Is there any other alternative available that i can use ?
>

Another (better) option is to rewriting your "C LIB" with Lua
cosockets, as I've already mentioned.

Regards,
-agentzh

kamal pushpad

unread,
Jul 28, 2014, 11:59:37 AM7/28/14
to openre...@googlegroups.com
HI ,

I am implementing my change using surequest method. But i am facing one issue.

My Lua code is as below.
Whichever request goes through Lua script , it creates subrequest "/auth_req" for further response.

.......
 for any request ...

local res = ngx.location.capture("/auth_req")     --  code from  file.lu
               if res.status == 200 then
                    ngx.say(res.body)
               end

........

In my nginx.conf  File. 

location /any_other_request/  {
           ...........
           access_by_lua_file  file.lu
        }


location  /auth_req {
               hello_world;
        }


I have written my own module which handles URI "/auth_req".  hello_world is directive for my module.


Module code is as below. When first time my handler gets called it does not have response so i change write event handler and start timer for it.
When timer expires my write event handler gets called and it serves header + response.

<<<<< First way >>>>>>>

static void ngx_http_test_wev_handler(ngx_http_request_t *r)
{
  ngx_buf_t    *b;
  ngx_chain_t   out;
 
  r->headers_out.content_type.len = sizeof("text/plain") - 1;
  r->headers_out.content_type.data = (u_char *) "text/plain";

  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

  out.buf = b;
  out.next = NULL;

  b->pos = ngx_hello_world;
  b->last = ngx_hello_world + sizeof(ngx_hello_world);
  b->memory = 1;
  b->last_buf = 1;

  r->headers_out.status = NGX_HTTP_OK;
  r->headers_out.content_length_n = sizeof(ngx_hello_world);
  ngx_http_send_header(r);
  ngx_http_output_filter(r, &out);
  ngx_http_finalize_request(r, rc);
}


static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
{
  ngx_int_t    status;
  ngx_event_t *wev;

  r->write_event_handler = ngx_http_test_wev_handler;
  wev = r->connection->write;
  ngx_add_timer(wev, 2000);
  r->count++;
  return NGX_DONE;
}
<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>

If i directly access /auth_req then it get proper response.  but if access any other URL which goes through my Lua script then it never give response and close connection.


But below code works perfectly fine if  i am serving the header and response in main handler function instead of creating timer event.

<<<<< second  way >>>>>>>


static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
{
  ngx_buf_t    *b;
  ngx_chain_t   out;

  r->headers_out.content_type.len = sizeof("text/plain") - 1;
  r->headers_out.content_type.data = (u_char *) "text/plain";

  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

  out.buf = b;
  out.next = NULL;

  b->pos = ngx_hello_world;
  b->last = ngx_hello_world + sizeof(ngx_hello_world);
  b->memory = 1;
  b->last_buf = 1;

  r->headers_out.status = NGX_HTTP_OK;
  r->headers_out.content_length_n = sizeof(ngx_hello_world);
  ngx_http_send_header(r);

  return ngx_http_output_filter(r, &out);
}
<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>

So i am not sure what i am missing in first way   ?????  do i have do something different in first way as it works fine in second way.

Thanks
kamal




Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jul 28, 2014, 1:42:07 PM7/28/14
to openresty-en
Hello!

On Mon, Jul 28, 2014 at 8:59 AM, kamal pushpad wrote:
> <<<<< First way >>>>>>>
>
> static void ngx_http_test_wev_handler(ngx_http_request_t *r)
[...]
> b->last_buf = 1;
>

Unconditionally setting of last_buf here is wrong. You should test if
the current request is a subrequest because in that case you should
set b->last_in_chain instead.

> r->headers_out.status = NGX_HTTP_OK;
> r->headers_out.content_length_n = sizeof(ngx_hello_world);
> ngx_http_send_header(r);
> ngx_http_output_filter(r, &out);
> ngx_http_finalize_request(r, rc);

I don't see how you define and initialize this "rc" variable. Actually
the value of "rc" here is the key for the correctness of this timer
handler. It *must* be NGX_OK in this context and for your purpose. Any
other values are just wrong and can lead to request hang.

> static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
[...]
> r->write_event_handler = ngx_http_test_wev_handler;
> wev = r->connection->write;
> ngx_add_timer(wev, 2000);

Abusing the write event timer here is logically wrong. This event
timer should only be used for protecting against writing timeouts.
Better create your own dedicated ngx_event_t for your own
special-purpose timer.

> If i directly access /auth_req then it get proper response. but if access
> any other URL which goes through my Lua script then it never give response
> and close connection.
>

This is usually a sign of out-of-sync r->main->count reference count
in your module code. It should also manifest itself when being used in
a main request. You may not notice the issue with main requests when
using well-behaved HTTP clients like "curl" or modern web browsers
because these clients will actively close the connection even when the
server side never does. And that's why I always use
Test::Nginx::Socket to drive all the test suites of my nginx C
modules:

http://search.cpan.org/perldoc?Test%3A%3ANginx%3A%3ASocket

You'd better use it too to save your time (and my time).

Also, enabling the nginx debug logging helps tracking the
r->main->count reference in the whole lifetime of your request:

http://nginx.org/en/docs/debugging_log.html

Just watch the messages with the little thing "c:xxx" (where xxx is a
number, which is r->main->count). They are usually generated by
ngx_http_finalize_request.

> But below code works perfectly fine if i am serving the header and response
> in main handler function instead of creating timer event.
>
> <<<<< second way >>>>>>>
>

This simplest "way" is much less likely to get wrong :) (Though it
still could and may already contain issues.)

> So i am not sure what i am missing in first way ????? do i have do
> something different in first way as it works fine in second way.
>

NGINX C programming is hard, especially for beginners. That's why I
created ngx_lua in the first place and why I recommended you use
ngx_lua exclusively for your requirements. Otherwise you'll have to
spend a lot of time on your nginx C modules (and so will I if I want
to support you along the way :))

Regards,
-agentzh

kamal pushpad

unread,
Jul 28, 2014, 3:25:00 PM7/28/14
to openre...@googlegroups.com
Hi ,

First of all i don't want to write  new module in C but as of now i don't have any choice.
As per you last suggestion you told me to rewrite my LIB ( use to authenticate the user) using Lua . But this LIB is provided by somebody else and used by other process as well.
SO it is no where possible to rewrite it using LUA. we have to use it as it.

Apart from this i don't know if there is any other way possible to communicate between Lua script and LIB written in C. I know that we can call function from LIB written in C from Lua code.   Please suggest any good pointer for same.



If not possible then i have to write my own C module to handle subrequest.
can you point to any link or code example  where i can see how to handle subrequest in my C module ????

Else i have lots of doubts.

1. how to check if it is subrequest ?
 if (r->subrequests) {
      b->last_in_chain = 1;
  } else {
      b->last_buf = 1;
  }

2.  Also i don't know to handle  "r->main->count" while handling subrequest ?

 

  Really appreciate your valuable response. 


Thanks
kamal
  



Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jul 28, 2014, 3:54:37 PM7/28/14
to openresty-en
Hello!

On Mon, Jul 28, 2014 at 12:24 PM, kamal pushpad wrote:
> First of all i don't want to write new module in C but as of now i don't
> have any choice.
> As per you last suggestion you told me to rewrite my LIB ( use to
> authenticate the user) using Lua . But this LIB is provided by somebody else
> and used by other process as well.
> SO it is no where possible to rewrite it using LUA. we have to use it as it.
>

BTW, it is Lua rather than LUA (which is not an acronym). See
http://www.lua.org/about.html#name

> Apart from this i don't know if there is any other way possible to
> communicate between Lua script and LIB written in C. I know that we can call
> function from LIB written in C from Lua code. Please suggest any good
> pointer for same.
>

Check out how ngx_drizzle and ngx_postgres modules do this:

https://github.com/openresty/drizzle-nginx-module

https://github.com/FRiCKLE/ngx_postgres

The short story is that it is a bit hard :) And that was also the
motivation of creating the cosocket API in ngx_lua in the first place
;)

> If not possible then i have to write my own C module to handle subrequest.
> can you point to any link or code example where i can see how to handle
> subrequest in my C module ????
>

Usually you don't have to specially handle subrequests in your module.
The only difference is to set b->last_in_chain instead of b->last_buf
if your handler is in the context of a subrequest.

> 1. how to check if it is subrequest ?
> if (r->subrequests) {
> b->last_in_chain = 1;
> } else {
> b->last_buf = 1;
> }
>

To test if the current request is a subrequest, use the condition

if (r != r->main) { /* being a subrequest */
}

You can check out the source of the standard ngx_http_send_special()
function in the nginx core. (You can ignore the r->post_action
condition there, which is a dirty hack).

> 2. Also i don't know to handle "r->main->count" while handling subrequest
> ?
>

Use "r->main->count++" to increment it and ngx_http_finalize_request
to decrement it (with NGX_DONE or NGX_OK, which the latter also tries
to terminate the request).

For the content handler, there is an implicit
ngx_http_finalize_request call (see ngx_http_core_content_phase() in
the nginx core). So when you return NGX_DONE from your content handler
will just decrement r->main->count immediately after the return, and
that's also why you need to increment it explicitly in your content
handler before "return NGX_DONE" to keep the reference counting above
zero (and thus to keep the current request session alive).

Regards,
-agentzh

kamal pushpad

unread,
Jul 28, 2014, 4:53:55 PM7/28/14
to openre...@googlegroups.com
Hi,


I have made the changes but still same issue.  it gives empty response.


static void ngx_http_test_wev_handler(ngx_http_request_t *r)
{
  ngx_buf_t    *b;
  ngx_chain_t   out;
 
  r->headers_out.content_type.len = sizeof("text/plain") - 1;
  r->headers_out.content_type.data = (u_char *) "text/plain";

  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

  out.buf = b;
  out.next = NULL;

  b->pos = ngx_hello_world;
  b->last = ngx_hello_world + sizeof(ngx_hello_world);
  b->memory = 1;
  b->last_buf = 1;

  if (r == r->main) {
     b->last_buf = 1;
  } else {
     b->last_in_chain = 1;
  }

  r->headers_out.status = NGX_HTTP_OK;
  r->headers_out.content_length_n = len;
  rc = ngx_http_send_header(r);
  ngx_http_output_filter(r, &out);
  ngx_http_finalize_request(r, NGX_DONE);

}


static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
{
  ngx_int_t    status;
  ngx_event_t *wev;

  r->write_event_handler = ngx_http_test_wev_handler;
  wev = r->connection->write;
  ngx_add_timer(wev, 2000);
  r->main->count++;          ////r->count++;
  return NGX_DONE;
}



Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jul 28, 2014, 5:55:06 PM7/28/14
to openresty-en
Hello!

On Mon, Jul 28, 2014 at 1:53 PM, kamal pushpad wrote:
> I have made the changes but still same issue. it gives empty response.
> static void ngx_http_test_wev_handler(ngx_http_request_t *r)
> {
[...]
> rc = ngx_http_send_header(r);
> ngx_http_output_filter(r, &out);
> ngx_http_finalize_request(r, NGX_DONE);
>

Alas. You did not read my previous email carefully enough. To quote:
"it *must* be NGX_OK in this context and for your purpose." Why are
you using NGX_DONE here?

Also, to quote another related suggestion in my previous mail:
"enabling the nginx debug logging helps tracking the
r->main->count reference in the whole lifetime of your request:

http://nginx.org/en/docs/debugging_log.html

Just watch the messages with the little thing "c:xxx" (where xxx is a
number, which is r->main->count). They are usually generated by
ngx_http_finalize_request."

When in doubt, always check out your nginx's debug logs. If you still
have no ideas, show me your original debug logs dump (better put
somewhere on the web, like gist.github.com and just share the link on
the mailing list).

Please do not let me repeat...I don't have that much time. Thank you.

Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jul 28, 2014, 6:00:32 PM7/28/14
to openresty-en
Hello!

Also, please ensure you have carefully read Evan Miller's nginx guides:

http://www.evanmiller.org/nginx-modules-guide.html

http://www.evanmiller.org/nginx-modules-guide-advanced.html

Some of the things in the guides are kinda out of date. But most of
the basics still apply to the latest nginx cores pretty well.

While debugging, first ensure your module works without ngx_lua. And
as I've suggested, use Test::Nginx::Socket to exercise your code.
There are various different testing modes supported there. Please read
Test::Nginx::Socket's documentation. (Oh, I'm repeating myself again.
Alas.)

Best regards,
-agentzh

kamal vimal

unread,
Aug 6, 2014, 1:56:42 PM8/6/14
to openre...@googlegroups.com
HI Yichun,

I have checked all the Emiller's guide and other online tutorials and but i didn't get any clue what is wrong with my code.
Also searched a lot but did not get any similar scenario.  I am not even sure if it supposed to work like this.

Now after sending request it is hanging forever.  no response is coming.

Really appreciate your help.

Brief summary => when i am sending any request , it leads to another subrequest which is handling by below code.


#### Working code #########

static ngx_int_t ngx_http_session_mgmt_handler(ngx_http_request_t *r)

{
  ngx_buf_t    *b;
  ngx_chain_t   out;

  r->headers_out.content_type.len = sizeof("text/plain") - 1;
  r->headers_out.content_type.data = (u_char *) "text/plain";

  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

  out.buf = b;
  out.next = NULL;

  b->pos = ngx_hello_world;
  b->last = ngx_hello_world + sizeof(ngx_hello_world);
  b->memory = 1;
  b->last_buf = 1;

  r->headers_out.status = NGX_HTTP_OK;

  r->headers_out.content_length_n = sizeof(ngx_hello_world);
  ngx_http_send_header(r);

  return ngx_http_output_filter(r, &out);
}

################## Non working code ################

static ngx_int_t ngx_http_session_mgmt_handler(ngx_http_request_t *r)
{
  /* ngx_event_t    wev; is global var  */
  wev.handler = ngx_http_smgmt_wev_handler;
  wev.data    = r;
  wev.log     = r->connection->log;
  ngx_add_timer(&wev, 2000);
  r->main->count++;
  return NGX_DONE;
}


static void ngx_http_smgmt_wev_handler(ngx_event_t *ev)
{
  ngx_buf_t    *b;
  ngx_chain_t   out;
  ngx_http_request_t  *r;
  int rc;

  r = ev->data;

  r->headers_out.content_type.len = sizeof("text/plain") - 1;
  r->headers_out.content_type.data = (u_char *) "text/plain";

  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
  if (b == NULL) {
       return;

  }
  b->pos = ngx_hello_world;
  b->last = ngx_hello_world + sizeof(ngx_hello_world);
  b->memory = 1;

  b->last_buf = (r == r->main) ? 1: 0;
  b->last_in_chain = 1;

  out.buf = b;
  out.next = NULL;

  r->headers_out.status = NGX_HTTP_OK;
  r->headers_out.content_length_n = sizeof(ngx_hello_world);
  rc = ngx_http_send_header(r);
  rc = ngx_http_output_filter(r, &out);
  ngx_http_finalize_request(r, rc);
}
##############################################

Thanks
kamal


-agentzh

Yichun Zhang (agentzh)

unread,
Aug 6, 2014, 2:43:40 PM8/6/14
to openresty-en
Hello!

On Wed, Aug 6, 2014 at 10:56 AM, kamal vimal wrote:
> r->headers_out.content_type.len = sizeof("text/plain") - 1;
> r->headers_out.content_type.data = (u_char *) "text/plain";
>
> b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
>

You're not handling the case of NULL return values here.

> r->headers_out.content_length_n = sizeof(ngx_hello_world);
> ngx_http_send_header(r);
>

And you're not handling the return value of ngx_http_send_header(r)
here in case of errors.

> static ngx_int_t ngx_http_session_mgmt_handler(ngx_http_request_t *r)
> {
> /* ngx_event_t wev; is global var */

Use of global C variables in the context of nginx is generally a bad
idea. And particularly wrong in this context because you won't be able
to handle concurrent requests at all. Hook it up in your own module's
(per-request) ctx structure instead. I believe this "ctx" thing is
covered in Evan Miller's guides.

> rc = ngx_http_send_header(r);
> rc = ngx_http_output_filter(r, &out);

Again, you're not handling NGX_ERROR return values from these 2 calls.

> ngx_http_finalize_request(r, rc);

I think you should use the following piece of code here (at the end of
your "ngx_http_smgmt_wev_handler" function body) instead:

ngx_http_finalize_request(r, NGX_OK);
ngx_http_run_posted_requests(c);

For this sleep timer exercise you're doing, I suggest you look at how
ngx_echo module implements its "echo_sleep" directive:

https://github.com/openresty/echo-nginx-module#echo_sleep

You're reinventing the wheel here anyway. And your example can be
expressed as below:

location = /sub {
echo_sleep 2; # sleep for 2 sec
echo -n "hello world";
}

location = /main {
content_by_lua '
local res = ngx.location.capture("/sub")
ngx.say("subrequest status: ", res.status)
ngx.say("subrequest body: ", res.body)
';
}

Accessing /main gives the following output after 2 sec:

subrequest status: 200
subrequest body: hello world

Try this example out on your side and study how things go under the
hood with gdb or whatever debugging tools you're comfortable with.

And yeah, my ngx_echo module is a live demo for basic nginx C module
programming. A more advanced one is the ngx_lua module.

Best regards,
-agentzh

kamal vimal

unread,
Aug 20, 2014, 12:48:25 PM8/20/14
to openre...@googlegroups.com
Thanks a lot for helping.  Everything is working fine now.

Regards kamal



Best regards,
-agentzh

Reply all
Reply to author
Forward
0 new messages