Setting variables from upstreams?

338 views
Skip to first unread message

Calin Don

unread,
Mar 13, 2013, 1:53:48 PM3/13/13
to openre...@googlegroups.com
Hi,

I'm trying to set some variables from a redis server. 

Currently I'm doing it by using rewrite_by_lua and rewrite_by_lua_no_postpone set to 'on' since set_by_lua does not give access to upstreams (cosocket is disable as well as capture location).

The code is like this (status codes are just for exemplification):

rewrite_by_lua_no_postpone on;
server {
set $foo '1';
rewrite_by_lua 'ngx.var.foo = "2"';
if ($foo = '1') { return 404; }
if ($foo = '2') { return 503; }
}

And if I access an URL it returns 404 instead of 503.

If I rewrite the code like this:

rewrite_by_lua_no_postpone on;
server {
set $foo '1';
rewrite_by_lua 'ngx.var.foo = "2"';

location / {
if ($foo = '1') { return 404; }
if ($foo = '2') { return 503; }
}
}

It returns 503 as expected.

Can someone point the proper way of setting a variable from upstream which is "usable" (in if/rewrite/return context) at server block level?

agentzh

unread,
Mar 13, 2013, 2:54:06 PM3/13/13
to openre...@googlegroups.com
Hello!

On Wed, Mar 13, 2013 at 10:53 AM, Calin Don wrote:
>
> rewrite_by_lua_no_postpone on;
> server {
> set $foo '1';
> rewrite_by_lua 'ngx.var.foo = "2"';
> if ($foo = '1') { return 404; }
> if ($foo = '2') { return 503; }
> }
>
> And if I access an URL it returns 404 instead of 503.
>

The actual running order is like this:

ngx_rewrite's directives used in server blocks run at the "server
rewrite" phase in the Nginx core while rewrite_by_lua used in the
server blocks are just inherited by all the location blocks within the
current server {} and run in the "rewrite" phase.

For more details about Nginx's running phases, please refer to my
Nginx tutorials here:

http://openresty.org/download/agentzh-nginx-tutorials-en.html

So in this code snippet, your directives run in this order:

set $foo '1';
if ($foo = '1') { return 404; }
if ($foo = '2') { return 503; }
rewrite_by_lua 'ngx.var.foo = "2"';

No wonder you're getting 404 instead of 503 because your Lua code
actually runs after your "if" directives.

> If I rewrite the code like this:
>
> rewrite_by_lua_no_postpone on;
> server {
> set $foo '1';
> rewrite_by_lua 'ngx.var.foo = "2"';
>
> location / {
> if ($foo = '1') { return 404; }
> if ($foo = '2') { return 503; }
> }
> }
>
> It returns 503 as expected.
>

Here, your "set" directive used in the outer scope runs in the "server
rewrite" phase while your "if" directives and "rewrite_by_lua" run at
the "rewrite" phase, which is always running after the "server
rewrite" phase (though not directly after).

Because you turn on rewrite_by_lua_no_postpone, then in the "rewrite"
phase, your "rewrite_by_lua" directive always run before *all* the
ngx_rewrite module's directives.

Unlike the set_by_lua directive which is effectively injected into
ngx_rewrite's command sequence behind the scene, the "rewrite_by_lua"
directive cannot mix with ngx_rewrite's directives freely. When you
mix them, rewrite_by_lua always run before all the ngx_rewrite
directives when rewrite_by_lua_no_postpone is on, and after all the
ngx_rewrite directives otherwise.

> Can someone point the proper way of setting a variable from upstream which
> is "usable" (in if/rewrite/return context) at server block level?
>

It is (highly) recommended to stick with pure Lua to do all the
rewrites, internal redirections, and Nginx variable assignments
operations instead of mixing Lua with ngx_rewrite's directives. I
believe almost all the functionalities provided by ngx_rewrite are
implemented in ngx_lua's Lua API. Feel free to prove me wrong ;)

Best regards,
-agentzh

Călin Don

unread,
Mar 13, 2013, 3:25:59 PM3/13/13
to openre...@googlegroups.com
Thanks for your help. I'll try to migrate everything to lua. The reason I'm trying to mix is that I have some legacy stuff which require that some nginx variables are set.


--
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/groups/opt_out.



ser...@openbridge.com

unread,
Sep 25, 2013, 4:13:40 PM9/25/13
to openre...@googlegroups.com
Awesome answer, thank you
Reply all
Reply to author
Forward
0 new messages