Project

General

Profile

Actions

Lua Trigger Functions » History » Revision 1

Revision 1/2 | Next »
gstrauss, 2022-05-11 20:39


Lua Trigger Functions

lighttpd mod_magnet can be configured to send a trigger to another process when a specific event occurs.

lua trigger functions

trigger_sock: send trigger to socket

function trigger_sock (addr, port, msg)
  -- connect and send msg to socket
  -- note: *blocking* connect() (and blocking send() unless msg is short)
  -- (caller should prefer addr "127.0.0.1" to succeed or fail fast)
  local socket = require("socket")
  local s = socket.tcp4()
  if (not s) then return false end
  s:settimeout(1)
  local rc = false
  if (s:connect(addr, port)) then
    local wr = s:send(msg)
    if (wr and wr == msg.len) then rc = true end
  end
  s:close()
  return rc
end

trigger_fifo: send trigger to FIFO

function trigger_fifo (path, msg)
  -- write msg to fifo; non-blocking; tries once or fails
  -- (requires luaposix)
  --   (lua-posix package or see https://github.com/luaposix/luaposix)
  local P = require "posix.fcntl" 
  local fd = P.open(path, P.O_WRONLY | P.O_NONBLOCK | P.O_CLOEXEC)
  if (not fd) then return false end

  local unistd = require "posix.unistd" 
  local wr = unistd.write(fd, msg);
  unistd.close(fd)
  return (wr and wr == msg.len)

  -- lua 5.3+ supports bitwise operations (used above)
  --local fd = P.open(path, P.O_WRONLY | P.O_NONBLOCK | P.O_CLOEXEC)
  -- lua 5.2 provides bit32 table of functions
  --local fd = P.open(path, bit32.bor(P.O_WRONLY, P.O_NONBLOCK, P.O_CLOEXEC))
  -- luaJIT
  --local bit = require("bit")
  --local fd = P.open(path, bit.bor(P.O_WRONLY, P.O_NONBLOCK, P.O_CLOEXEC))
  -- lua 5.1 needs an alternative bit operator implementation
  -- (if running lua 5.1 from before bit32 was backported to the lua 5.1 series)
  -- https://lua-users.org/wiki/BitwiseOperators
  --(not implemented here for lua 5.1)
end

trigger_execp_bg: trigger command execution in background

function trigger_execp_bg (path, argt)
  -- execute command in background (fork(), setsid(), fork(), execp())
  -- (requires luaposix)
  --   (lua-posix package or see https://github.com/luaposix/luaposix)
  local unistd = require "posix.unistd" 
  -- fork()
  local pid, _ = unistd.fork()
  if pid == nil then    -- error
    return -1
  elseif pid ~= 0 then  -- parent
    local syswait = require "posix.sys.wait" 
    local reaped, _, status = syswait.wait(pid)
    return reaped == pid and status or -1
  end                   -- child (pid == 0)
  -- setsid()
  if (not unistd.setpid('s', 0)) then -- setsid
    unistd._exit(-1)
  end
  -- fork()
  pid, _ = unistd.fork()
  if pid == nil then    -- error
    unistd._exit(-1)
  elseif pid ~= 0 then  -- parent
    unistd._exit(0)
  end                   -- child (pid == 0)
  -- execp()
  unistd.execp(path, argt)
  unistd._exit(-1)
end

lua trigger examples

thumbnail-trigger.lua

The example below triggers thumbnail creation (by an external process) following successful upload of an image file.

-- thumbnail-trigger.lua for lighttpd mod_magnet
--
-- trigger a script to generate a thumbnail after successful PUT of an image file
--
-- lighttpd.conf
--   server.modules += ("mod_magnet")
--   $HTTP["method"] == "PUT" {
--     magnet.attract-response-start-to = ("/path/to/thumbnail-trigger.lua")
--   }

local r = lighty.r
local req_attr = r.req_attr

-- check for successful PUT request with HTTP status 201 or 204
-- lighttpd 1.4.60 - 1.4.65 (to be removed in 1.4.66)
--local http_status = req_attr["response.http-status"]
-- lighttpd 1.4.65+
local http_status = r.req_item.http_status
if (not http_status == 201 and not http_status == 204) then return 0 end
-- (method is checked in lighttpd.conf sample in comment at top)
--if (not req_attr["request.method"] == "PUT") then return 0 end

-- get file path components
local path = req_attr["physical.path"]
local dir, file, ext = string.match(path, "^(.*/)([^/]+)([.][%a%d]+)$")
if (not ext) then return 0 end

-- check for .jpg (or list of extensions for which to trigger)
-- TODO: (as needed)
if (not ext == ".jpg") then return 0 end

-- string manipulation on path to get path to thumbnail
-- TODO: (as needed)
local thumb = dir .. "thumbs/" .. file .. ext

-- trigger thumbnail update
-- TODO: fill in and call chosen trigger method
--       (Functions must be defined before being called)
--       (e.g. copy reference code implementation into script)
--trigger_sock("127.0.0.1", 8888,         path .. " " .. thumb .. "\n")
--trigger_fifo("/path/to/thumbnail.fifo", path .. " " .. thumb .. "\n")
--trigger_execp_bg("/path/to/thumbnail.py, { path, thumb })

return 0

Updated by gstrauss 3 months ago · 1 revisions