title: OpenResty rewrite_by_lua vs. rewrite_by_lua_file - syntax errors
body: <p>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.</p>
  
  <pre><code>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
  '
  </code></pre>
  
  <p>However, if I extract this script in to a file, <code>memcached.lua</code> and then include it in the nginx config with <code>rewrite_by_lua_file</code>, I am unable to restart nginx and get notifications about syntax errors such as:</p>
  
  <p><code>unexpected "," in /etc/nginx/sites-enabled/memcached.lua</code></p>
  
  <p><code>unknown directive "--" in /etc/nginx/sites-enabled/memcached.lua</code></p>
  
  <p>If I remove the ngx.log line completely the syntax error disappears.</p>
  
  <p>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?</p>
  
  <h2>EDIT</h2>
  
  <p>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 <code>rewrite_by_lua</code></p>
  
  <p><code>cat /etc/nginx/sites-enabled/memcached.lua</code></p>
  
  <pre><code>-- 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
  </code></pre>
  
  <h2>SOLUTION</h2>
  
  <p><strong>TL:DR - put the .lua file outside of your Nginx configuration directory.</strong></p>
  
  <p>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:</p>
  
  <p><code>2015/12/17 10:04:02 [emerg] 6903#0: unexpected "," in /etc/nginx/sites-enabled/memcached.lua:18</code></p>
  
  <p>This time I copied the Lua code out of my nginx.conf and put it in a file called <code>memcached.lua</code> and saved it in my project directory. I then added the following include to my nginx.conf in place of the Lua script:</p>
  
  <p><code>rewrite_by_lua_file /path/to/my/project/memcached.lua;</code></p>
  
  <p>Immediately it starts working! </p>
  
  <p>Previously I had included it by symlinking it from my project directory in to <code>/etc/nginx/sites-enabled/memcached.lua</code> (assuming it would be better for it to actually live alongside the .conf that includes it) and then just used <code>rewrite_by_lua_file memcached.lua;</code> as it was relative the .conf file.</p>
  
  <p>So I initially wondered if it was because the <code>rewrite_by_lua_file</code> 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 <code>/etc/nginx/sites-enabled</code> so Nginx was automatically trying to load the file as though it was a normal Nginx configuration file.</p>
  
  <p>This is because Nginx (on Ubuntu/Linux Mint) is configured to import all config files using the path <code>/etc/nginx/sites-enabled/*</code> in to it's main config.</p>
  
  <p>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 <code>/etc/nginx/sites-enabled/*.conf</code> - 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.</p>