OpenResty rewrite_by_lua vs. rewrite_by_lua_file - syntax errors - nginx

I am using OpenResty Nginx, and have a snippet of Lua script in the Nginx conf. (sample below, but truncated for brevity). This works fine when it is in the nginx.conf file.
rewrite_by_lua '
-- Load Memcached module
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.log(ngx.ERR, "Failed to instantiate memc: ", err)
return
end
'
However, if I extract this script in to a file, memcached.lua and then include it in the nginx config with rewrite_by_lua_file, I am unable to restart nginx and get notifications about syntax errors such as:
unexpected "," in /etc/nginx/sites-enabled/memcached.lua
unknown directive "--" in /etc/nginx/sites-enabled/memcached.lua
If I remove the ngx.log line completely the syntax error disappears.
How come the syntax is valid in the nginx conf but not when I extract it to a separate file? I've read somewhere about bytecode but not sure if that is related?
EDIT
Here is the full output of the .lua file. This exact code works if it's embedded directly in to the nginx.conf file via rewrite_by_lua
cat /etc/nginx/sites-enabled/memcached.lua
-- Define Memcached key
local memcached_key = "saas_" .. ngx.var.host
-- Load Memcached module
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.log(ngx.ERR, "Failed to instantiate memc: ")
end
-- Set Memcached timeout
memc:set_timeout(1000)
-- Connect to Memcached daemon
local ok, err = memc:connect("127.0.0.1", 11211)
if not ok then
ngx.log(ngx.ALERT, "Failed to connect to Memcached: ", err)
end
-- Query for branch name in Memcached
local branch, flags, err = memc:get(memcached_key)
if err then
ngx.log(ngx.NOTICE, "Failed to get account from Memcached: ", err)
end
-- If branch not found in Memcached, ask MySQL instead
if not branch then
-- Load MySQL module
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.log(ngx.ALERT, "Failed to instantiate MySQL: ", err)
return
end
-- Set MySQL timeout
db:set_timeout(1000) -- 1 sec
-- Connect to MySQL daemon
local ok, err, errno, sqlstate = db:connect{
path = "/var/run/mysqld/mysqld.sock",
database = "dbname",
user = "dbuser",
password = "dbpass" }
if not ok then
ngx.log(ngx.ALERT, "Failed to connect to DB: ", err, ": ", errno, " ", sqlstate)
return
end
-- Define subdomain string by extracting it from the http hostname
local subdomain = string.match(ngx.var.host, "([%w-]+).")
local quoted_subdomain = ngx.quote_sql_str(subdomain)
-- Execute an SQL query to get the branch name based on the subdomain
local sql = "SELECT branch FROM saas_account WHERE account = " .. quoted_subdomain
local res, err, errno, sqlstate = db:query(sql, 1)
if not res then
ngx.log(ngx.ALERT, "Bad result from DB: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
-- Check we got a result
if not res[1] then
ngx.log(ngx.NOTICE, "No docroot was returned for subdomain: ", subdomain)
ngx.var.branch = "chaletops"
-- Assign the result from MySQL to the Nginx variable
else
ngx.var.branch = res[1].branch
-- Store the result from MySQL back in to Memcached with a lifetime of 1 hour (3600 seconds)
local ok, err = memc:set(memcached_key, ngx.var.branch, 3600)
if not ok then
ngx.log(ngx.WARN, "Failed to set branch in Memcached: ", err)
-- return
end
end
-- Save MySQL KeepAlive connection
local ok, err = db:set_keepalive(10000, 100)
if not ok then
ngx.log(ngx.ALERT, "Cannot set MySQL keepalive: ", err)
return
end
ngx.log(ngx.NOTICE, "Loading branch from MySQL: ", ngx.var.branch)
-- Else we did get a result from Memcached
else
-- Assign the result from Memcached to the Nginx variable
ngx.var.branch = branch
ngx.log(ngx.NOTICE, "Loading branch from Memcached: ", ngx.var.branch)
end
-- Save Memcached KeepAlive connection
local ok, err = memc:set_keepalive(10000, 100)
if not ok then
ngx.log(ngx.ALERT, "Cannot set Memcached keepalive: ", err)
-- return
end
SOLUTION
TL:DR - put the .lua file outside of your Nginx configuration directory.
After being asked to post the exact error messages, I had to recreate the problem. For reference and Google searchers the error messages are like this:
2015/12/17 10:04:02 [emerg] 6903#0: unexpected "," in /etc/nginx/sites-enabled/memcached.lua:18
This time I copied the Lua code out of my nginx.conf and put it in a file called memcached.lua and saved it in my project directory. I then added the following include to my nginx.conf in place of the Lua script:
rewrite_by_lua_file /path/to/my/project/memcached.lua;
Immediately it starts working!
Previously I had included it by symlinking it from my project directory in to /etc/nginx/sites-enabled/memcached.lua (assuming it would be better for it to actually live alongside the .conf that includes it) and then just used rewrite_by_lua_file memcached.lua; as it was relative the .conf file.
So I initially wondered if it was because the rewrite_by_lua_file function could not follow symlinks or something, but then it dawned on me that it was nothing to do with the Lua include statement, but OBVIOUSLY (now!) because of the symlink being in /etc/nginx/sites-enabled so Nginx was automatically trying to load the file as though it was a normal Nginx configuration file.
This is because Nginx (on Ubuntu/Linux Mint) is configured to import all config files using the path /etc/nginx/sites-enabled/* in to it's main config.
I think the reason I made this simple error is that on later versions of Ubuntu with Apache, a similar process happens but with Apache (which I am much more used to) you have an include path of /etc/nginx/sites-enabled/*.conf - i.e. it specifically requires a .conf file extension, which is why I incorrectly assumed that Nginx would not try to include my .lua file.

Related

Environment Variables in LUA

I have a Lua Script which Logins to the Redis and Process some Query to enable IP Based Blocking
Below is the Redis Config I am using in my Lua script and to run this script at every hit to the webserver I use the access_by_lua directive in my Nginx conference
--- Redis Configuration
local redis_host = "100.2.4.4"
local redis_port = 6379
local redis_timeout = 30
local cache_ttl = 3600
I would like to use an environment Variable in the reds_host and the port rather than static value
Any Help is appreciated
Note:
I have tried it as below, but no luck
--- Redis Configuration
local redis_host = os.getenv("redis_auth_host")
local redis_port = os.getenv("redis_auth_port")
local redis_timeout = 30
local cache_ttl = 3600
Redis runs Lua script in a sandbox, which disables global variables, with a few exceptions. In your case, os is a disabled global variable, so you cannot use it.
In order to avoid hard-coding the host and port, you can set them in Redis' key space, i.e. setting host and port as key-value pairs in Redis, and get them with redis.call() method.
local redis_host = redis.call("get", "host")
local redis_port = redis.call("get", "port")

ESP HTTP connection issue : on connection callback function not getting called

I am using custom build for NodeMCU with following modules: cjson, file, gpio, http, net, node, ow, tmr, websocket, wifi.
conn = nil
conn=net.createConnection(net.TCP) -- 30 seconds timeout time of serv
conn:on("connection", function(conn, payload)
print("Server DB Connected, sending event") -- This line is not getting print on esplorer.
conn:send ( <some-data>)
end)
conn:connect(80,"mysite.com")
conn:close()
For debugging i tried using following code :
net.dns.resolve("www.google.com", function(sk, ip)
if (ip == nil) then
print("DNS fail!")
else
print("Resolved: " .. ip)
end
end)
But above is giving output " DNS fail! "
Site is working perfectly fine along with server.
A normal GET request to the same site using putty is returning correct data.
Please help me resolving the issue.

Lua entry thread aborted: runtime error bad argument #2 to 'tonumber' (number expected, got string)

Im using lapis framework and torch, sometimes the website showing internal server error when trying to load page, and the error from lapis is:
[error] 3726#81246: *19 lua entry thread aborted: runtime error: ...s/MyUser/torch/install/share/lua/5.1/xlua/init.lua:227: bad argument #2 to 'tonumber' (number expected, got string)
stack traceback:
coroutine 0:
[C]: in function 'require'
.../MyUser/torch/install/share/lua/5.1/lapis/init.lua:15: in function 'serve'
content_by_lua(nginx.conf.compiled:22):2: in function <content_by_lua(nginx.conf.compiled:22):1>, client: 127.0.0.1, server: , request: "GET /recommend HTTP/1.1", host: "localhost:9999", referrer: "http://localhost:9999/home"
After looking arround, the problem is gone when i remark this part:
local lapis = require("lapis")
local config = require("lapis.config").get()
local inspect = require("inspect")
local json = require('cjson')
local kb_recommend = require("recommender.knowledge")
-- local cb_recommend = require("recommender.content") <---- remark this
local mysql = require "luasql.mysql"
local env = mysql.mysql()
local conn = env:connect("restoran", "root", "")
Thats link to file recommender/content.lua:
package.path = package.path .. ";../?.lua"
local predictor = require("Content Based.predictor")
return predictor
This file returning the class where i wrote my torch code. I suspect the problem is coming from the 'require' part, but dont know why? I've been looking on google for solution, and nothing found. This my current version:
Lua 5.1.5
Torch7
Lapis 1.6.0
nginx/1.13.9
openresty/1.13.6.1
anyone can help? im very newbie in Lua environment.
tonumber is a Lua function for an example like this: tonumber("10") or tonumber(10)
I'm sorry I couldn't be of more help.
If you could show us the line where the error is located, I can most likely determine a fix for you.

How to use Lua with Redis?

I am using Lua+nginx with OpenResty bundle. But problem comes when I try to connect Lua script with Redis, I'm not able to make successful connection. I have gone through a lot of links and blogs, But in the end it always fails. This is the snippet of code which I am trying.
server {
location /test {
content_by_lua '
local redis = require "resty.redis" // **Problem in code "Not able to require "resty.redis""**
local red = redis:new()
red:set_timeout(1000) -- 1 sec
-- or connect to a unix domain socket file listened
-- by a redis server:
-- local ok, err = red:connect("unix:/path/to/redis.sock")
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end
}
}
Assuming "not able to require" means you are getting module 'resty.redis' not found message with a list of paths, the error indicates that you are missing the module. You need to check the paths that are listed and make sure that resty/redis.lua is in one of those folders. You will find that file in lua-resty-redis-<version> folder in your OpenResty installation.

define db value while creating connection with redis into nginx.conf file while using Openresty

I am using Redis with Django project which is running on nginx and i am creating connection by code
red = redis.Redis("localhost", port=6397, db=5, socket_timeout=2)
Now by using Openresty i am fetching cache data from Redis using lua into nginx.conf file i am able to create connection
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000) -- 1 second
local ok, err = red:connect("10.0.0.161", 6379)
Here in nginx.conf file i am not able to understand how can define db value .
I tried local ok, err = red:connect("10.0.0.161", 6379, {db=5) but it is not working .
Please help me.
Just use select once connected:
red:select(5)

Resources