API disabled in the context of set_by_lua*
StemonZhang opened this issue · comments
Lua is like the bridge between Nginx and Server.
I wanted to get data from MySQL , then redirect the request based on the data.
So I use the set_by_lua API.
Like this:
location /hello {
set_by_lua $res '
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed ti instantiate mysql: ", err)
return
end
db:set_timeout(1000)
local ok, err, errno, sqlstate = db:connect{
host = "",
port = 3306,
database = "",
user = "",
password = ""
}
if not ok then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate) ;
return
end
ngx.say("connected to mysql.")
res, err, errno, sqlstate = db:query("select XXX from YYY order by ZZZ desc limit 1")
if not res then
ngx.say("bad result: ", err, ":", errno, ":", sqlstate, ".")
return
end
'; }
But when I access the IP address, it's failed.
I checked the error.log, it said that:
failed to run set_by_lua_: /usr/local/lib/lua/resty/mysql.lua:449: API disabled in the context of set_by_lua_
stack traceback:
[C]: in function 'tcp'
/usr/local/lib/lua/resty/mysql.lua:449: in function 'new'
[string "set_by_lua"]:3: in function <[string "set_by_lua"]:1>, client:, server: , request: "GET /hello HTTP/1.1", host: ""
It's a big surprise!
Then I checked the specification:
set_by_lua
syntax: set_by_lua $res [$arg1 $arg2 ...]
context: server, server if, location, location if
phase: server-rewrite, rewrite
Also the example:
location /foo {
set $diff ''; # we have to predefine the $diff variable here
set_by_lua $sum '
local a = 32
local b = 56
ngx.var.diff = a - b; -- write to $diff directly
return a + b; -- return the $sum value normally
';
echo "sum = $sum, diff = $diff";
}
What's wrong with my Nginx?
There is a lot of things I shoud to learn~
Thx~
@StemonZhang lua-resty-mysql relies on ngx_lua's cosocket API which is not available in the set_by_lua* context due to the underlying limitations in nginx's standard ngx_rewrite module (you cannot do nonblocking I/O in ngx_rewrite module's directives).
This limitation is already documented in lua-resty-mysql's README: https://github.com/agentzh/lua-resty-mysql#limitations To quote, "this library cannot be used in code contexts like init_by_lua_, set_by_lua_, log_by_lua_, and header_filter_by_lua_ where the ngx_lua cosocket API is not available."
You can work around this limitation by using rewrite_by_lua or access_by_lua instead, in which you can access all the ngx_lua's Lua API including the cosocket API and nginx variable API.
Regards,
-agentzh
I got it~
Thank you very much,Big Zhang^_^
At 2013-08-27 06:38:40,"Yichun Zhang" notifications@github.com wrote:
@StemonZhang lua-resty-mysql relies on ngx_lua's cosocket API which is not available in the set_by_lua* context due to the underlying limitations in nginx's standard ngx_rewrite module (you cannot do nonblocking I/O in ngx_rewrite module's directives).
This limitation is already documented in lua-resty-mysql's README: https://github.com/agentzh/lua-resty-mysql#limitations To quote, "this library cannot be used in code contexts like init_by_lua_, set_by_lua_, log_by_lua_, and header_filter_by_lua_ where the ngx_lua cosocket API is not available."
You can work around this limitation by using rewrite_by_lua or access_by_lua instead, in which you can access all the ngx_lua's Lua API including the cosocket API and nginx variable API.
Regards,
-agentzh
—
Reply to this email directly or view it on GitHub.
Consider it resolved.
@agentzh , so basically, if i want for example to enrich Headers that are stored somewhere else, i can't do that ?
@driverpt Why are you sticking with set_by_lua*
? There are many other alternatives like rewrite_by_lua*
which have little limitations.
@driverpt Actually I've already suggested solutions in my earlier comments:
You can work around this limitation by using rewrite_by_lua or access_by_lua instead, in which you can access all the ngx_lua's Lua API including the cosocket API and nginx variable API.
I'm using Kong.
problem:API disabled in the context of set_by_lua*?
error code:
lua-resty-redis/lib/resty/redis.lua:59: API disabled in the context of set_by_lua*
stack traceback:
Solution ideas @agentzh
You can work around this limitation by using rewrite_by_lua or access_by_lua instead, in which you can access all the ngx_lua's Lua API including the cosocket API and nginx variable API.
Solution:
I can work around this limitation by using
rewrite_by_lua_file
nginx.conf
location ~ /hls/(\d+).m3u8$ {
set $a $1; # eg : 123456789
set $stream_id ""; # we have to predefine the $stream_id variable here
default_type 'text/html';
lua_code_cache off;
rewrite_by_lua_file /home/www/lua-tinywan/set_by_file.lua;
echo "stream_id :" $stream_id;
}
set_by_file.lua
local stream_a = ngx.var.a
local redis = require("resty.redis");
local redis_instance = redis:new();
redis_instance:set_timeout(1000)
local ip = '127.0.0.1'
local port = 6379
local ok,err = redis_instance:connect(ip,port)
if not ok then
ngx.say("connect redis error : ",err)
return err
end
local resp, err = redis_instance:hget("liveNodeRedis:"..stream_a,'liveNode')
if not resp then
ngx.say("get msg error : ", err)
return err
end
if resp == ngx.null then
ngx.say("this is not redis_data")
return nil
end
ngx.var.stream_id = resp
redis date
127.0.0.1:6379> HMSET liveNodeRedis:123456789 stream_id 123456789 liveNode "https://github.com/Tinywan/hls/123456789.m3u8" time 18:11
OK
127.0.0.1:6379> keys *
1) "liveNodeRedis:123456789"
127.0.0.1:6379> hget liveNodeRedis:123456789 liveNode
"https://github.com/Tinywan/hls/123456789.m3u8"
127.0.0.1:6379>
curl test
root@iZ236j3sofdZ:/usr/local/nginx/conf/lua# curl "http://localhost/hls/123456789.m3u8"
stream_id : https://github.com/Tinywan/hls/123456789.m3u8