Lua Scripts
Flussonic has a built-in experimental feature to execute scripts written in the Lua scripting language. Flussonic uses luerl as Lua interpreter, so error messages might be different from the standard one.
features
In addition to the standard lua library, Flussonic adds some features to scripts:
HTTP client
http.get(url)
http.get(url, headers)
http.get(url, headers, body)
http.get(url, headers, timeout)
http.get(url, headers, body, timeout)
An HTTP GET request is sent. A table with keys: code
, headers
, body
is sent as the reply.
http.post(url)
An HTTP POSt request is sent. The arguments and answer are like those in http.get
.
http.qs_encode(table)
The table is encoded into a query string.
JSON module
json.encode(table)
The table is translated into JSON
json.decode(text)
JSON is translated into the table
Flussonic API
flussonic.config()
partial configuration is returned
flussonic.streams()
current list of streams
flussonic.files()
current list of open files
flussonic.caches()
current list of disk caches
flussonic.clients()
flussonic.clients(stream)
current list either of all sessions or of specific sessions of the stream
flussonic.log(text)
output into the log by means of Flussonic
flussonic.debug(text)
debugging output into the log by means of Flussonic
flussonic.now()
current time UTC
flussonic.uuid()
uuid is generated
table.tostring(table)
returns the table as text
Comet server
comet.create_channel("channel")
comet.create_channel("channel", 100)
a channel in the inner comet server is created. Channel is optionally specified
comet.send("channel", "message")
a message is sent via the comet server internal channel
SWIFT client
auth_info = swift.auth("http://proxy-server/", "account", "password")
authorization data for further access is returned
swift.list_containers(auth_info)
the list of containers of the authorized account
swift.create_container(auth_info, 'videos')
swift.create_container(auth_info, 'videos', {})
a container, possibly with a meta-date, is created
swift.delete_container(auth_info, 'videos')
deleting the container
swift.list_objects(auth_info, 'videos')
list of objects in the container
swift.create_object(auth_info, 'videos', 'file.txt', 'contents')
creating an object
swift.upload_file(auth_info, 'videos', 'remote_path.mp4', 'local_path.mp4')
swift.upload_file(auth_info, 'videos', 'remote_path.mp4', 'local_path.mp4', 'local_callback_name')
downloading a file. The name of the local function can also be specified as a line that will be invoked upon booting
for indicating load on the server
FTP client
ftp.list("ftp://user:password@host/path")
The list of files in the directory
ftp.upload("local.mp4", "ftp://user:password@host/path/remote.mp4")
function progress(p) end ftp.upload("local.mp4", "ftp://user:password@host/path/remote.mp4", "progress")
the local file is uploaded to ftp. Optionally, a callback is invoked for the download status
Crypto API
crypto.md5("Hi")
md5 in hex format
crypto.sha1("Hi")
sha1 in hex format
crypto.sha256("Hi")
sha256 in hex format
Login using Lua
The login backend in Lua is an ordinary script that returns the result with the return
operator. The script receives an additional global table req
with the following fields, some of which are optional:
token
- token from the query string or automatically generatedip
- IP address of the username
- stream/file namereferer
- the optional referrer of the player (the address of the page it was inserted into)
The answer should look like:
return true, {user_id = 15, unique = true}
,
return "redirect", "http://someotherserver/path"
or
return false, {code = 403}
Event handlers
An example of using Lua for filtering and sending internal Flussonic events is provided in section Events API.
Web scripts
Lua can be used to generate web pages using the Flussonic infrastructure.
To do so, specify in the config:
web_script mytest priv/myscripts;
After that, when referring to the address http://192.168.2.3:80/mytest/counter
, a lua script priv/myscripts/web.lua
will be called,
and the http_handler.counter(req)
function will be called in it:
http_handler = {}
http_handler.counter = function(req)
if not req.cookies.flusession then
session_id = flussonic.uuid()
headers = {}
headers["Set-Cookie"] = "flusession="..session_id
headers["Location"] = "/mytest/counter"
return "http", 302, headers, "auth\n"
else
session_id = req.cookies.flusession
value = flussonic.session.get(session_id, "key1")
if not value or value == "undefined" then
flussonic.session.set(session_id, "key1", 1)
end
value = flussonic.session.get(session_id, "key1")
flussonic.session.set(session_id, "key1", value + 1)
return "http", 200, {}, tostring(value).."\n"
end
end
Now this script should be invoked:
$ curl -v http://localhost:80/mytest/counter
...
< HTTP/1.1 302 Found
< Connection: keep-alive
< Server: Cowboy
< Date: Fri, 06 Mar 2015 10:20:13 GMT
< Content-Length: 5
< Location: /mytest/counter
< Set-Cookie: flusession=4a41cc61-b089-4cd5-9c4a-28402c6db525
$ curl -s http://localhost:80/mytest/counter -H 'Cookie: flusession=4a41cc61-b089-4cd5-9c4a-28402c6db525'
1
$ curl -s http://localhost:80/mytest/counter -H 'Cookie: flusession=4a41cc61-b089-4cd5-9c4a-28402c6db525'
2
$ curl -s http://localhost:80/mytest/counter -H 'Cookie: flusession=4a41cc61-b089-4cd5-9c4a-28402c6db525'
3
$ curl -s http://localhost:80/mytest/counter -H 'Cookie: flusession=4a41cc61-b089-4cd5-9c4a-28402c6db525'
4
In this script, all the functions described above will be available. Also, the table req
is available:
req.query
- parsed query stringreq.headers
- HTTP headersreq.method
- HTTP method in uppercase lettersreq.body
- body of the HTTP header. If the body is in the www-form-encoded format, it should be parsed in lua on its own with the use ofhttp.qs_decode
:
if req.method == "POST" then
post = http.qs_decode(req.body)
end
The lua script can return the following responses:
return 'http', 200, {["Content-Type"] = "text/plain"}, "Hello, world!\n"
- the http response can be sent directlyreturn "json", {key = "value"}
- the table will be packed into JSON-
return "template", {var1 = "value1", var2 = "value2"}
- in this case, Flussonic will take the file calledpriv/cameras/list.html
that should be a valid DTL template, where the values from the script -
return "template" will be substituted, {headers = {}}, {var1 = "value1"}
the same but with the possibility to set headers
Examples
Sometimes, it is needed to disable authorization for secondary servers, i.e., for multiple IP addresses. In order to avoid adding this logic to the back-end, one can write their own authorization script:
if req.ip == "94.95.96.97" then
return true, {}
end
reply = http.get("http://backend/script.php")
if not reply.code == 200 then
return false, {code = reply.code}
end
opts = {}
if reply.headers["x-userid"] then
opts.user_id = reply.headers["x-userid"]
end
if reply.headers["x-unique"] then
opts.unique = true
end
return true, opts