# Lua possibilities/limitations

**URL:** <https://www.ruby-forum.com/t/lua-possibilities-limitations/203116>\
**Category:** NGINX\
**Created:** [February 13, 2011, 7:14am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116 "2011-02-13T07:14:27Z")\
**Posts on this page:** 10\
**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:** [February 13, 2011, 7:14am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/1 "2011-02-13T07:14:27Z")

</div>

Hi Guys,  
I need a little help with the lua module. My ultimate aim is to import  
variables into nginx from outside source.  
Here is my code, you can probably tell what I’m trying to do:

location /proxy {  
proxy\_pass [http://127.0.0.1:8012/](http://127.0.0.1:8012/);  
}

location /main {  
set $myvar ‘’;  
set $limit\_rate 99;  
content\_by\_lua ’  
local res = ngx.location.capture(“/proxy”,{ args = { bla = “moo” } })  
if res.status == ngx.HTTP\_OK then  
for k,v in pairs(res.header) do  
if k == “X-Limit-Rate”  
then  
ngx.var.myvar  
= v  
end  
end  
return  
else  
ngx.exit(res.status)  
end  
';

set $limit\_rate $myvar;  
add\_header X-Test $myvar;  
add\_header X-Limit $limit\_rate;

}  
}

The output is quite confusing:

curl -I [http://localhost:101/main](http://localhost:101/main)  
HTTP/1.1 200 OK  
Server: nginx/0.8.54  
Date: Sun, 13 Feb 2011 03:29:00 GMT  
Content-Type: application/octet-stream  
Connection: keep-alive  
X-Test: 100  
X-Limit: 99

Am I going about this in the right way? As I say, my ultimate aim is to  
set a whole bunch of nginx vars from outside…

Many thanks  
Richard

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 14, 2011, 5:10am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/2 "2011-02-14T05:10:04Z")

</div>

On Sun, Feb 13, 2011 at 12:02 PM, Richard K.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi Guys,
> 
> I need a little help with the lua module. My ultimate aim is to import  
> variables into nginx from outside source.

Your code below is totally wrong because you do not understand nginx  
request phases well enough 🙂

1. Your content\_by\_lua always runs after any write-phase directrives  
like “set” and “if” even if you put “set $limit\_rate $myvar;” after it  
in the config file.

2. Your content\_by\_lua for the /main location does not generate any  
response bodies (using ngx.print or ngx.say in Lua). So you see the  
empty response body on the client side.

BTW, your “add\_header” directive runs in the output filter phase, so  
your X-Test header gets the value set by your Lua code, which is  
expected. But your X-Limit gets the old value because “set $limit\_rate  
$myvar” runs _before_ $myvar gets the new value in Lua and $limit\_rate  
is still the old value. (For why “set” runs after your content\_by\_lua  
code, see above).

FWIW, rewrite\_by\_lua and access\_by\_lua also run _after_ those “set”,  
“if”, “rewrite” directives provided by ngx\_rewrite.

> Am I going about this in the right way? As I say, my ultimate aim is to set  
> a whole bunch of nginx vars from outside…

For this purpose, rewrite\_by\_lua or access\_by\_lua will almost be  
sufficient. But if you want to calculate variable values using  
response headers (from ngx\_proxy or ngx\_fastcgi), then you need to  
issue subrequests in content\_by\_lua before ngx\_lua gets the  
“output\_header\_filter\_by\_lua” directive implemented 🙂

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 14, 2011, 5:16am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/3 "2011-02-14T05:16:20Z")

</div>

On Mon, Feb 14, 2011 at 12:08 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Your code below is totally wrong because you do not understand nginx  
> request phases well enough 🙂

Just want to mention that plain nginx.conf programming can be evil  
because IMHO 99.99% of the nginx users on this planet do not and I bet  
will not grok all of these details about nginx phases and various  
pitfalls regarding “if”, “add\_header”, and etc. Mixing these with or  
without Lua can be confusing. And that’s why we’re advocating pure Lua  
scripting wherever feasible. Add your headers and doing your code  
branches using pure Lua because it’s a mature and well designed  
language (as compared to the nginx.conf language).

Some mature nginx users or developers might disagree here. But that’s  
_our_ opinions and recommendations anyway 🙂

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 14, 2011, 11:36am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/4 "2011-02-14T11:36:54Z")

</div>

Hi,

…  
On 13/02/2011 06:02, Richard K. wrote:

> location /main {
> 
> set $myvar ‘’;
> 
> set $limit\_rate 99;

…

> set $limit\_rate $myvar;

As well as the points agentzh made, there is also the case here that  
$limit\_rate does a check on the values that it is set to, and it must be  
a valid size (internally this is done by having a set\_handler attached  
to the variable - something most variables don’t have).

Here, you are trying to set it to ‘’ (i.e. empty), and this is invalid,  
and it will :  
(a) throw an error in the error log, saying that it’s an ‘invalid size’  
(b) do nothing to the value, therefore leaving it at 99 rather than  
setting it to ‘’

With the config you have, most variables would result in your headers  
being  
…

X-Test: 100

X-Limit:

But you see X-Limit: 99 because of this reason.

Cheers,

Marcus.

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 15, 2011, 12:48am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/5 "2011-02-15T00:48:27Z")

</div>

Thanks for the help guys, I’m getting somewhere now, config file feels  
so script like it’s an easy trap to fall in to 🙂  
Please consider this example…

location /main {  
set $myvar ‘’;  
set $limit\_rate 99;  
content\_by\_lua ’  
local res = ngx.location.capture(“/proxy”,{ args = { bla = “moo” } })  
if res.status == ngx.HTTP\_OK then  
for k,v in pairs(res.header) do  
if k == “X-Limit-Rate”  
then  
ngx.var.myvar  
= v  
ngx.var.limit\_rate  
= v  
end  
end  
return  
else  
ngx.exit(res.status)  
end  
';

add\_header X-Test $myvar;  
add\_header X-Limit $limit\_rate;

}

curl -I [http://localhost:101/main](http://localhost:101/main)  
HTTP/1.1 200 OK  
Server: nginx/0.8.54  
Date: Mon, 14 Feb 2011 23:40:06 GMT  
Content-Type: application/octet-stream  
Connection: keep-alive  
X-Test: 100  
X-Limit: 99

Is there something special with $limit\_rate stopping me to set it? Is it  
a string/int issue?

Regards,  
Richard K.

From: Eugaia [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]  
Sent: 14 February 2011 10:35  
To: removed\_email\_address@domain.invalid  
Subject: Re: lua possibilities/limitations

Hi,

…  
On 13/02/2011 06:02, Richard K. wrote:  
location /main {  
set $myvar ‘’;  
set $limit\_rate 99;  
…

set $limit\_rate $myvar;  
As well as the points agentzh made, there is also the case here that  
$limit\_rate does a check on the values that it is set to, and it must be  
a valid size (internally this is done by having a set\_handler attached  
to the variable - something most variables don’t have).

Here, you are trying to set it to ‘’ (i.e. empty), and this is invalid,  
and it will :  
(a) throw an error in the error log, saying that it’s an ‘invalid size’  
(b) do nothing to the value, therefore leaving it at 99 rather than  
setting it to ‘’

With the config you have, most variables would result in your headers  
being  
…  
X-Test: 100  
X-Limit:

But you see X-Limit: 99 because of this reason.

Cheers,

Marcus.

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 15, 2011, 5:29am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/6 "2011-02-15T05:29:11Z")

</div>

On Tue, Feb 15, 2011 at 7:46 AM, Richard K.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Is there something special with $limit\_rate stopping me to set it? Is it a  
> string/int issue?

Yeah, $limit\_rate is a special variable defined in the http core module:

```
http://wiki.nginx.org/NginxHttpCoreModule#.24limit_rate

```

For now, ngx\_lua’s “ngx.var.foo = xxx” assignment does not support  
such special variables. This will change in a future release.

I’ve confirmed for you that replacing $limit\_rate with $limit gives  
the expected headers 🙂 Not sure if you really want to set $limit\_rate  
to control transfer limit rate though.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 15, 2011, 11:49am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/7 "2011-02-15T11:49:11Z")

</div>

On Tue, Feb 15, 2011 at 4:57 PM, Eugaia [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This explains a lot. 🙂 By this do you mean it doesn’t support variables  
> with set handlers, or also changeable variables with different get handlers?

The former only, I think 🙂

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [July 4, 2011, 11:31am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/8 "2011-07-04T11:31:33Z")

</div>

On Tue, Feb 15, 2011 at 12:27 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> For now, ngx\_lua’s “ngx.var.foo = xxx” assignment does not support  
> such special variables. This will change in a future release.

I’ve just committed a fix for nginx variable assignment in Lua to  
ngx\_lua’s git master HEAD. Now all the nginx variables with a  
set\_handler is properly handled (like $args and $limit\_rate).  
Furthermore, only changeable nginx variables will be honored, so  
writing to $arg\_PARAM will result in a Lua exception (ready to be  
caught by pcall/xpcall if LuaJIT 2.0 is used).

Here’s the modified version of your sample config that should work for  
you:

```
location /proxy {
    proxy_pass http://127.0.0.1:8012/;
}

location /main {
    set $limit_rate 99;
    rewrite_by_lua '
        local res = ngx.location.capture("/proxy",{ args = { bla =

```

“moo” } })  
if res.status == ngx.HTTP\_OK then  
for k,v in pairs(res.header) do  
if k == “X-Limit-Rate” then  
ngx.var.limit\_rate = v  
end  
end

```
            return
        end

        ngx.exit(res.status)
';

add_header X-Limit $limit_rate;

```

}

My modifications mainly correct the following mistake in your previous  
sample:

- content\_by\_lua always runs in the content phase while ngx\_rewrite’s  
“set” command always runs at the earlier rewrite phase. So your  
content\_by\_lua will always run _after_ your “set” commands even if you  
put it before them.

As a bonus, I also add reading support for nginx regex group capturing  
variables like $1, $2, $3, and etc, in Lua.

Happy Lua hacking!

Best,  
-agentzh

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [February 15, 2011, 9:59am UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/9 "2011-02-15T09:59:30Z")

</div>

Hi,

On 15/02/2011 06:27, agentzh wrote:

> For now, ngx\_lua’s “ngx.var.foo = xxx” assignment does not support  
> such special variables. This will change in a future release.  
> This explains a lot. 🙂 By this do you mean it doesn’t support  
> variables with set handlers, or also changeable variables with different  
> get handlers?

Marcus.

---

<div class="post-metadata">

**Author:** ![rkoskela](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/ce73a5/32.png) [@rkoskela](https://www.ruby-forum.com/u/rkoskela)\
**Post date:** [July 4, 2011, 2:06pm UTC](https://www.ruby-forum.com/t/lua-possibilities-limitations/203116/10 "2011-07-04T14:06:04Z")

</div>

Thanks!  
I have tested and this part works 🙂
