This page documents the core Barracuda App Server (BAS) Lua/LSP API. Everything described here belongs to the standard Lua integration layer that is available in BAS builds with Lua support.
The BAS Lua documentation is split into two parts. This page covers the always-available core API: the ba library, the LSP execution model, request/response processing, directories, sessions, and related runtime services. Additional functionality is documented in The Auxiliary Lua API. The auxiliary API can be excluded in custom builds, but it is included in most products and example servers, including Mako Server and Xedge.
The Barracuda App Server (BAS) executes Lua code as trusted application logic deployed by the device manufacturer. Lua in BAS is not sandboxed by default and provides full access to Lua-to-C bindings.
It is, however, possible to provide a limited sandboxed environment (e.g., via custom _ENV tables) for systems that allow customers to write their own Lua code. However, implementing such a sandbox requires a deep understanding of Lua and the APIs exposed by BAS. In general, a secure approach is to explicitly grant access to a well-defined set of functions rather than attempting to exclude unsafe functionality.
For maximum security, applications should be deployed as signed packages, ensuring that only authorized and untampered code can execute.
Lua in BAS is not limited to server-side page generation. It is used for request handling, device and application logic, timers, authentication, directory services, and integration with C/C++ bindings. When the optional auxiliary libraries are enabled, the same Lua environment can also act as an HTTP(S) client, SMTP client, socket endpoint, and crypto integration layer. If you are new to Lua in embedded systems, start with the tutorial Why Smart C Coders Love Lua.
Real Time Logic designs BAS, its plugins, and the BAS-specific Lua bindings. The embedded Lua language itself is the standard Lua project, which uses the MIT license and is suitable for commercial products.
At runtime, Lua is typically entered from C code. A request, timer callback, socket event, or another BAS event activates Lua code, and that Lua code can in turn call back into C through bindings. This event-driven boundary between C and Lua is the key to understanding how BAS applications are structured.
The BAS library includes a large set of ready-made Lua bindings, and you can extend the environment with your own bindings when you need to expose device-specific or application-specific functionality. Binding creation is covered in the Lua book, and tools can automate much of the work by parsing C/C++ headers. For more information, see the online tutorial Lua to C Code.
How to use this page: Read the overview sections first to build the BAS mental model: LSP, HTTP directories, the request/response environment, and coroutine/thread mapping. After that, use the anchor links throughout the page as an API reference.
See the section Thread Mapping and Coroutines for the execution model behind BAS Lua events, blocking bindings, and thread-pool interaction.
Lua Server Pages (LSP) is BAS's server-side execution model for mixing Lua with text resources and for building dynamic request handlers. Although LSP started as a page-oriented technology, it is now also a practical foundation for embedded web interfaces, REST services, IoT logic, and other event-driven applications. If you are familiar with Node.js, see the comparison between Node.js and Barracuda App Server for additional context.
For web applications, LSP provides a direct way to generate dynamic responses without a separate compilation step. Conceptually it is similar to CSP, but LSP pages are parsed and executed directly at runtime.
We recommend reviewing the following tutorials before you begin designing web interfaces:
In a typical BAS web application, LSP is enabled by creating a Resource Reader (resrdr) and installing it in the Virtual File System. Both the Mako Server and Xedge provide straightforward ways to configure Resource Reader-based LSP applications. A Resource Reader is only one option, however; BAS also supports more advanced designs, including custom MVC-style engines such as the one used in the Ready-to-Run Embedded Web Interface tutorial.
LSP lets you mix Lua with any text resource, most commonly HTML, XML, JSON, JavaScript, or plain text.
LSP tags use XML-compliant syntax:
Because the tags are XML-compliant, most HTML editors and tooling can handle LSP pages without special configuration.
LSP can also be used together with CSP. CSP pages can include LSP pages and LSP pages can include or forward to CSP pages and other server resources.
As detailed in the Virtual File System Documentation, Lua can be used to build and assemble directory tree objects that participate directly in BAS request routing. Using the ba.create family of functions, you can create dir-derived objects such as resrdr, WebDAV, and WFS instances either in preload scripts or directly from Lua code. The directory APIs are intentionally close to the Barracuda C/C++ APIs, so the same mental model applies whether you work in Lua or native code. All directory types share a common base behavior and a common set of methods.
|
Lua uses environments to define variable scope. In the standalone Lua interpreter, the shared global environment is _G. LSP keeps that global environment, but adds a second environment for request handling called the request/response environment, also referred to as the CMDE (command environment). The easiest way to think about CMDE is as a per-request workspace. Variables created in LSP pages and directory functions are stored in this temporary environment and are shared across all included or forwarded resources that participate in the same request. The diagram (shown to the right) illustrates the relationship between the command environment, LSP pages, directory functions, and their associated tables. The command environment is created when the first LSP page or directory function executes and persists until the request ends. This makes it possible to pass state through a request without writing to Lua globals or to long-lived application data. Note: The diagram shows a deliberately deep delegation chain so the object relationships are easy to see. Real applications are usually simpler. |
Make sure to download the Request/Response example from GitHub.
Directory Function
A directory function is a Lua function installed in one of dir, resrdr, or dav. It gives you programmatic control over how a directory handles a request. In practice, directory functions are used when a static directory object is not enough and you need custom routing, access control, request transformation, or application-specific behavior.
Lua Server Pages
A Lua Server Page (LSP) is a Lua script resource, typically with the extension .lsp, executed by a Resource Reader. In other words, the resrdr provides the file-system-facing part of the application, while the LSP engine provides the execution environment for the page.
An LSP page executes with a small set of BAS-provided variables:
io. For example, assert(io:stat(pathname)) succeeds for the currently executing page. The following example calculates the path to the directory containing the current LSP page:
pathname:match"(.-)[^/]+$"
Page Table
Each LSP page has its own private page table. Data stored there lives for as long as the owning Resource Reader lives, which makes the page table useful for caching per-page state or counters that should survive across requests but remain private to that page. Resource Readers can be created and removed dynamically, and a resrdr that is no longer referenced is automatically cleaned up by Lua garbage collection.
<?lsp
-- Using page variables
print("<pre>");
page.count = (page.count or 0) + 1
print("Access count = ", page.count)
print("</pre>")
?>
This code updates the variable count each time the page is displayed. When there are multiple users of the page, the number may increment by more than one each time you refresh the page. If we change the code to the following:
<?lsp
-- Using page variables
print("<pre>");
page.count = (page.count or 0) + 1
print("Access count = ", page.count)
ba.sleep(10);
print("Access count = ", page.count)
print("</pre>")
?>
then the two values of the access count may be different when we have multiple users.
Application Table
A Resource Reader can optionally expose an application table by calling rsrdr:lspfilter(apptab). The table is shared by all LSP pages in that resrdr, but is private to other Resource Readers. Use it for code and data that should be shared at the application level, such as configuration, caches, timers, HTTP client instances, or helper functions loaded from a .preload script. The xedge and wfs examples both use this pattern.
Session Object/Table
In addition to the per-request CMDE, the per-page page table, and the per-application app table, the LSP engine can also expose a session object. Session state is visible only to the current user session and is destroyed when that session terminates.
Lua globals
Lua globals (_G) are shared across all pages, requests, and sessions running in the same Lua state. A value written to _G in one request can therefore be read from another request.
That makes globals useful for framework-level helpers, but risky for request-specific data. In LSP code, values can be read without the _G prefix, but to create or update a true global you must explicitly assign through _G.
<?lsp
-- Using Lua Globals
print("<pre>");
_G.count = (_G.count or 0) + 1
print("Global LSP Access count = ", _G.count)
print(_G.stdpageheader)
print(_G.copyright)
-- global functions
_G.myfunction()
print("</pre>")
?>
Lua provides coroutines, which are lightweight cooperative execution contexts. A coroutine runs until it explicitly yields or returns, which means Lua code can switch tasks without preemptive context switching and without the usual locking model associated with application-level threads.
For more information on Lua coroutines, see the Lua coroutine documentation and the online coroutine tutorial.
BAS extends this model by mapping incoming C-side events onto Lua coroutines. Each request, timer callback, socket event, or similar BAS event can execute on its own Lua stack even though Lua itself is not preemptive. This is what makes BAS feel event-driven while still preserving Lua's single-VM execution rules.
In practice, only one native thread executes Lua bytecode at a time. However, when a binding yields Lua while performing lengthy C work, another pending coroutine may run. This is how BAS can support blocking-looking operations such as SQLite queries or client-side HTTP work without requiring you to manually manage context switches in most cases. See Lua-SQLite and LSP Considerations for a concrete example.
The following LSP page demonstrates several calls that may spend significant time on the C side and may therefore yield execution while the operation is in progress:
<?lsp
response:setcontenttype("text/plain")
-- Trick to make the browser flush its internal cache and start displaying data as it trickles in
for i = 1, 15 do
print("--------------------------------------------------------------------")
end
-- Function to print and flush the server's send buffer
local function pf(...)
print(...)
response:flush()
end
pf("Fetching 50 quotes")
local http = require("httpm").create()
local t, err = http:json("https://zenquotes.io/api/quotes")
if t then -- If we received a Lua table (decoded JSON string)
for key, val in ipairs(t) do
print(val.q) -- Print quote
pf(val.a, "\n") -- Print author and flush
ba.sleep(200) -- Sleep for 200 milliseconds
end
end
?>
In this example, the following functions may yield:
When you click the run button above, you should see the data gradually appear in the browser window instead of all at once. This is due to the yielding behavior of the functions used, which allows the output to be sent in chunks and displayed progressively.
The following diagram provides a high-level overview of the event and threading mechanism in BAS:
The diagram above approximates a typical assembled BAS server such as the Mako Server and Xedge standalone; however, in Xedge standalone, the Thread Pool and Thread Library are combined. If you assemble your own server using C code, you decide on the components to include. The only required component is the Socket Event Dispatcher. While the server can run without additional threads, using the optional Thread Pool and Thread Library enhances performance for Lua code calling time-consuming C functions, like SQLite operations, and enables blocking code, such as the HTTP client library, to run without interfering with other services.
Note: when you call blocking code such as ba.sleep(), you suspend the native thread. You can see from the diagram above that this is not a good idea when you run in the context of the Socket Event Dispatcher and the Timer thread, as this will suspend these threads from performing their operations. You can initiate lengthy operations within the context of these two threads by calling ba.thread.run().
Authentication in the Barracuda Server is an optional component that can be installed in any directory type. You can configure a single authenticator for the entire application or install multiple authenticators as needed. An authenticator can protect all resources or be restricted to a specific subset.
If you don't need to interface with an existing user database and plan to store a user database in local persistent storage, we recommend using the JSON-encoded authenticator database created with ba.create.jsonuser(). For Xedge and the Mako Server, we strongly recommend using the TPM-protected version, which securely encrypts the user database. Refer to the TPM API and ba.tpm.jsonuser() for more details.
local dir=ba.create.dir() dir:insert() -- Enable authentication and -- authorization for the directory. dir:setauth(authenticator,authorizer) -- Note: you must also reference (anchor) -- the dir to prevent it from garbage collecting.
In this example, an unnamed directory is created and installed as a root directory. We install the directory in the root, thus covering all pages in the server. The last line inserts an authenticator and authorizer in the server. We will soon look into how one can create authenticator and authorizer objects. Authenticators can be installed, replaced, or removed in a running system. For example, the authenticator is removed by calling dir:setauth().
The Lua authentication and authorization logic are wrappers for the authentication and authorization classes implemented in C code. The C classes are based on an object oriented design and many of the classes are designed to be extended by the application designer. The Lua wrappers use the same concept and one can create multiple authenticator and authorizer types. The authenticator and authorizer can be implemented in Lua, but one can also use drop in authenticator and authorizer solutions implemented in C code. We are currently providing one authenticator and authorizer drop in solution that stores user database information as JSON. See ba.create.jsonuser() for more information.
The authenticator object is responsible for the authentication handshaking between the client and the server. The authorizer is an optional component that authorizes the action performed by authenticated users. The following example expands on the previous example and implements an authenticator, but we are not using an authorizer.
local dir=ba.create.dir() dir:insert() -- The username/password callback function. local function getpassword(username) if username == "admin" then return "admin" end end -- Create the username database from our getpassword func. local authuser=ba.create.authuser(getpassword) -- Create authenticator by using the username database. local authenticator=ba.create.authenticator(authuser) -- Enable authentication for the directory. dir:setauth(authenticator)
An authenticator is created by calling ba.create.authenticator(). It requires a user database, so in this example we first create a basic user database with ba.create.authuser(). The user database object requires a password lookup function. That function looks up the user and returns the password if the user exists. The authenticator compares the stored password with the password provided by the user and accepts the user when they match. In the example above, the password lookup function returns "admin" if the username is "admin", which means the user is accepted when both username and password are "admin". The example getpassword callback returns the password in plaintext. You can also return a hash value or use external authentication.
The above is all that is required to implement authentication for a directory. Authentication defaults to digest authentication when the authenticator type is not configured. The authenticator also uses an integrated HTTP response message, which is displayed if the user clicks the cancel button in the browser's digest pop-up window.
An authorizer object is created as follows:
local function authorizer(username, method, path)
-- return true or false
end
local authorizer = ba.create.authorizer(authorizer)
dir:setauth(authenticator,authorizer)
The authorizer callback function determines user access based on the username, HTTP method, and requested relative path. It returns true if the user has access, and false or nothing if the user does not.
You have flexibility in how you authorize users. While authorizers typically use the username, method, and path, you can implement additional criteria as needed. Each LSP page can make its own access decisions, or you can override the directory service function to create a generic authorizer tailored to your application.
The authenticator example above is using HTTP digest authentication, which is the default if the type is not specified. The authenticator type can be specified by setting field "type" in the optional "option table".
local authenticator=ba.create.authenticator(authuser,{ type="basic" })
The following authenticator types can be specified:
The authenticator uses digest or basic authentication if the client is directly specifying the authentication type by setting the "Authorization" header. Command based and HTTP client libraries integrated with applications typically set the "Authorization" header before sending the request. The authenticator also checks if the client sends a Barracuda specific "PrefAuth"http header which should be set to basic or digest.
The authenticator defaults to digest authentication if the type is not specified and the request is for a non text based URL or if the request includes the X-Requested-With: XMLHttpRequest header.
The authenticator defaults to form-based authentication if the authentication type is not specified and the request is for an .html, .lsp, or .csp file.
The "auth" authenticator requires a custom response message handler, which is typically more complex to design than custom response message handlers for the other authenticator types.
All authenticator types are designed to work with user databases where the passwords are not stored in cleartext, but as a hash value. However, the hash encoded passwords must be stored using an encoding called HA1. See storing passwords as a hash value for details.
A login response message handler is responsible for sending login information and login failed information to a client. The function is not called unless the client requires login information, or if the authenticator failed to authenticate the client, or if the client is denied by the authenticator, or an installed login tracker denied the request. |
![]() |
In the login sequence shown above, the response handler is called when the user requests a protected resource (1). The response handler requests the user credentials (2) by sending login information to the client. Note: The response handler should send response data, but it must not set the HTTP authorization header, since that header is managed by the authenticator. The response handler is also called if the username, password, or both do not match (3).
The following example shows how to create a login response message handler for form-based authentication:
-- Custom Response Message Handler
local function loginresponse(_ENV, authinfo)
if authinfo.username then response:forward".loginfailed.lsp" end
response:forward".loginform.lsp"
end
local authenticator=ba.create.authenticator(
authuser,{type="form", response=loginresponse})
The _ENV variable is the command environment where globals such as the request and response objects are found.
The authinfo is a table with information about the login status. The username is set if the user failed to login. The username is not set when the client requests the login page. Notice that we are not using an "else" statement when forwarding the request to the login form. The "else" statement is not needed since response:forward by default does not return to sender, thus the code below ".loginfailed.lsp" will not execute unless username is not set. The pages ".loginform.lsp" and ".loginfailed.lsp" are regular LSP pages that send HTML login information and error information to the client.
Form-based authentication requires a custom response message handler. The response handler can emit the complete response page, but it is often easier to create a response handler that forwards the request to a dedicated LSP page. The following example shows how to create the ".loginform.lsp" page for the form response message handler shown earlier.
<html>
<body>
<form method="post">
Username: <input type="text" name="ba_username"><br>
Password: <input type="password" name="ba_password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
The above HTML form includes the two required form fields ba_username and ba_password. Pressing the submit button sends the login information in plaintext to the server. For this reason, you should use a secure (SSL/TLS) connection when using form-based authentication. See the "force secure connection" example for more information.
The form authenticator supports cryptographic hashing and implements an authentication scheme similar to digest authentication, which allows user identity to be established securely without having to send a password in plaintext over the network. The form authenticator adds two additional fields to the authinfo table that can be used by the response handler when creating the login form.
The following examples show how to create a form response message handler and an LSP login form that supports cryptographic hashing.
Form response message handler:
We must modify the form response message handler shown earlier so that it supports the new form login page.
local function loginresponse(_ENV, au) authinfo=au -- Set authinfo in the global command environment if authinfo.username then response:forward".loginfailed.lsp" end response:forward".loginform.lsp" end
The code above is similar to the previous example, except that it makes the variable authinfo available in the command environment. We can then use authinfo in the new .loginform.lsp page by making it global in the command environment.
Form login page:
The new ".loginform.lsp" page includes a JavaScript file and two new form fields. We have also changed the "submit" button to a standard html button. Changing the submit button to a standard button makes it impossible to submit the form if JavaScript is disabled, thus preventing the password from being sent in plaintext.
<html>
<head>
<script src="/rtl/sha1.js"></script>
</head>
<body>
<form method="post">
Username: <input type="text" name="ba_username"><br>
Password: <input type="password" name="ba_password" autocomplete="off"><br>
<input type="hidden" name="ba_seed" value="<?lsp= authinfo.seed ?>">
<input type="hidden" name="ba_seedkey" value="<?lsp= authinfo.seedkey ?>">
<input type="button" id="ba_loginbut" value="Login">
</form>
</body>
</html>
Notice how the two form fields ba_seed and ba_seedkey are created dynamically using LSP and values from the authinfo Lua table. The global authinfo table is made available to the LSP page by the response handler above. The form itself does not include inline JavaScript. The JavaScript code in sha1.js automatically discovers the HTML form with the fields ba_password, ba_seed, and the button with id="ba_loginbut". These fields are required by the JavaScript code, which calculates a SHA-1 hash from the password and seed value. The seedkey is required by the server-side authenticator when the form is submitted. The user will not be able to log in if any of these fields are missing.
The JavaScript file is found in the Barracuda SDK /WebResources/ directory. The two precompiled servers included with the SDK also include this file in the integrated ZIP file and make it available in the /rtl/ directory. The file sha1.js uses the browser's native DOM API and has no library dependency.
Many browsers give the user the option of saving the username and password in the browser. The JavaScript code run when pressing the login button replaces the password entered by the user by the SHA1 hash before submitting the page, thus making it impossible for the user to save the password. This feature increases security but degrades the user experience. If you want the user to be able to save the password, make the following changes to the HTML form:
<form method="post">
Username: <input type="text" name="ba_username"><br>
Password: <input type="password" id="ba_password2"><br>
<input type="hidden" name="ba_password">
<input type="hidden" name="ba_seed" value="<?lsp=authinfo.seed?>">
<input type="hidden" name="ba_seedkey" value="<?lsp=authinfo.seedkey?>">
<input type="button" id="ba_loginbut" value="Login">
</form>
The ba_password field is now changed to a hidden field, and the visible password field uses id="ba_password2". Notice that we use an id and not a name attribute for ba_password2. Form fields without a name are not submitted to the server, which is what we want, i.e., to prevent the password from being sent in plaintext. The JavaScript code in sha1.js is designed to look for this combination. The hash is created from ba_password2 + seed and inserted into ba_password. This construction allows the user to save the password in some browsers.
<input type="hidden" name="ba_realm" value="Barracuda Server">
Realm is the authenticator's realm value. The default realm value is Barracuda Server.
You must also include spark-md5.min.js, which is used for calculating HA1.
The following shows the complete example:
<script src="/rtl/sha1.js"></script> <script src="/rtl/spark-md5.min.js"></script> <form method="post"> Username: <input type="text" name="ba_username"><br> Password: <input type="password" name="ba_password" autocomplete="off"><br> <input type="hidden" name="ba_realm" value="Barracuda Server"> <input type="hidden" name="ba_seed" value="<?lsp= authinfo.seed ?>"> <input type="hidden" name="ba_seedkey" value="<?lsp= authinfo.seedkey ?>"> <input type="button" id="ba_loginbut" value="Login"> </form>
Basic and form-based authentication are unsafe unless the login information is sent over a secure connection. The following example makes sure the client is using a secure connection:
-- Create a secure URL from URI (path)
-- cmd is the request and response object.
-- The username/password callback function.
-- Notice how we use the optional _ENV command environment.
local function getpassword(username, upasswd, _ENV)
if not request:issecure() then
-- Deny login: send redirect request
response:redirect2tls()
-- redirect2tls does not return to caller.
end
if username == "admin" then return "admin" end
end
-- Create the username database from our getpassword func.
local authuser=ba.create.authuser(getpassword)
-- The login response message handler
local function loginresponse(_ENV, authinfo)
if not request:issecure() then
-- Remove Authorization header set by basic or digest authenticator
response:setheader("Authorization",nil)
-- redirect2tls does not return
response:redirect2tls()
end
-- The connection is secure if we get this far.
if authinfo.username then response:forward".loginfailed.lsp" end
response:forward".loginform.lsp"
end
local authenticator=ba.create.authenticator(authuser,{response=loginresponse})
dir=ba.create.dir()
dir:insert()
dir:setauth(authenticator)
The login response message handler checks if the URL is secure, and if it is not, sends a redirect request to the client. Removing the "Authorization" header set by the authenticator is necessary if using Digest or Basic authorization since we do not want the client to send the credentials before using a secure connection. |
![]() |
A client normally starts by requesting a secure resource without providing the user's credentials (1), but a non-browser client such as an HTTP client library may directly send the credentials (3). The password is sent in plaintext and an eavesdropper could intercept it. We cannot prevent this on the server, but we can change the getpassword() function to ignore the login request and force a secure connection. The response is not normally committed in a getpassword() function, but the authenticators are designed such that they assume the getpassword() function sent a "denied" request if the response is committed. Method response:sendredirect() commits the response.
Note: The modified getpassword() function with the secure redirect is not needed if using the sform authenticator, since the secure form authenticator denies all non-secure requests and delegates the request directly to the response message handler.
The BAS APIs, accessed through the global ba table, are divided into two documentation sets: the core API described on this page and the optional Auxiliary API. Most BAS products include both, but custom BAS builds can omit the auxiliary libraries when client-side protocols, sockets, or optional crypto features are not needed.
When reading the reference below, keep in mind that BAS applications also execute inside an LSP runtime with BAS-provided objects such as request, response, cookie, session, and page. The ba library provides the server-level and utility functions that those higher-level constructs build upon.
A library that provides a number of BAS utility and I/O functions.
Error conventions: Parameters and return values below include their names and Lua types. A Throws section describes argument or state errors and any additional exceptions implemented by the binding. Errors returned as values are listed under Return values. Lua allocation failures can also raise an out-of-memory error, including in functions with no argument checks. Do not assume that every failure is an exception.
Parameters
Return values
Throws
Throws for an argument that cannot be read as a Lua string, embedded NUL in the encoded input, input larger than INT_MAX bytes, detected Base64 output overflow, or native buffer allocation failure. An incorrect key or authentication failure does not throw.
Decodes, authenticates, and decrypts a string returned byba.aesencode(). The key must be the same as the key used
when encoding the string. The function returns no values (nil in an assignment) if the
decoded input is too short or authentication fails, including an
incorrect key or modified ciphertext.
Parameters
Return values
Throws
Throws for arguments that cannot be read as Lua strings, input exceeding the checked buffer-size limits, native buffer allocation failure, or failure of the random generator.
Encrypts and authenticates a string using AES-GCM and returns the result as a Base64URL-encoded string. A new random initialization vector is generated for every call; encoding the same string and key multiple times therefore produces different results. The encoded value contains the initialization vector, ciphertext, and authentication tag required byba.aesdecode().
This function is intended for transient application state, not long-term persistent storage. It is typically used as a substitute for creating a session object. The LSP page can instead store the session state as a hidden variable in the dynamically created page returned to the browser. The authentication tag prevents modified state from being accepted. The following example illustrates how to encode and decode state information in a hidden variable.
Encoding:
-- Data to be encoded and stored in hidden variable
local stateInfo={x=10,y="Top Secret"}
local data=ba.aesencode(app.key, ba.json.encode(stateInfo))
Decoding:
-- Data received via hidden variable from client local data=ba.aesdecode(app.key, request:data"MyHiddenVariable") local stateInfo=data and ba.json.decode(data)
Parameters
Return values
Throws
Throws if a supplied non-nil length cannot be read as a Lua integer, or the random generator reports failure.
Create a cryptographically random 16 or 32 byte key that can be used byba.aesencode() and ba.aesdecode(). The key
is typically created at startup in the .preload script and
stored in the app table. Data encoded with such an in-memory key cannot
be decoded after the application is restarted and a new key is created.
Decode Base64 or Base64url text.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Also throws for embedded NUL, input larger than INT_MAX bytes, or detected output overflow.
Encode binary data as Base64.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string.
Encode binary data as Base64url.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Throws if padding is supplied and is neither a boolean nor nil.
Decode percent escapes in URL text.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Also throws for an embedded NUL, malformed % escapes, escaped NUL, raw or escaped ASCII control characters (0–31 and 127).
Encode URL text.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Also throws for embedded NUL, an input too large to allocate the worst-case encoded result.
Parameters
None.
Return values
Throws
No argument-validation errors or operational errors are raised by this binding.
Compare IPv4 or IPv6 address strings. IPv4 and equal-length IPv6 strings are compared as text. IPv6 strings of different lengths are converted before comparison. The literal prefix ::ffff: is recognized for comparison with an IPv4 string. This is not a general address-validation function.
Parameters
Return values
Throws
Throws if a supplied non-nil argument cannot be read as a Lua string. Address-conversion failure returns false.
print(ba.cmpaddr("127.0.0.1", "127.0.0.1")) -- Prints true
print(ba.cmpaddr("::1", "0:0:0:0:0:0:0:1")) -- Prints true
print(ba.cmpaddr("68.4.198.129","::ffff:68.4.198.129")) -- Prints true
print(ba.cmpaddr("68.4.198.129","::ffff:68.4.198.128")) -- Prints false
Compress a string or sequence of strings. See also response:setresponse().
Parameters
Return values
Throws
Throws for an unsupported data type, an empty sequence, or an element that cannot be read as a string. Also throws if zlib initialization fails, with "Zlib error".
A table of functions for creating Barracuda objects:
Creates an authenticator for dir:setauth(). See the authentication introduction.
Parameters
Return values
Throws
Throws for an invalid authuser, an unsupported type, an invalid realm or response value, a missing response handler for form/sform, or enabling a tracker that is not installed. Lua allocation and errors from option-table metamethods can also throw.
Writes the response when authentication requires a login response. This callback does not run when the authenticator is created.
Parameters
Return values
None. Return values are ignored.
Throws
Callback errors are caught and reported by the request error handler. They do not propagate as errors from the authenticator constructor.
Creates an authorizer for use with dir:setauth().
Parameters
Return values
Throws
Throws if callback is not a function or Lua allocation fails.
Parameters
Return values
Throws
Callback errors are caught by the binding and access is denied; they do not propagate as an error from the authorizer constructor.
-- isadmin is set by the application during login. local az=ba.create.authorizer(function(u,m,r,s) return s.isadmin end)
Creates a user database backed by a Lua callback. Pass it to ba.create.authenticator().
Parameters
Return values
Throws
Throws if callback is not a function or Lua allocation fails.
Parameters
Return values
Throws
During normal authentication, errors raised by the callback are caught by the request error handler; the credential result remains invalid. During an explicit authuser:getpwd() lookup, callback errors propagate to the getpwd() caller, with or without a request argument. Incorrect return shapes reject authentication or leave optional defaults unchanged rather than throwing from the constructor.
See HA1 hashes and external authentication for the alternative credential formats.
Parameters
None.
Return values
Throws
Throws if Lua allocation fails. Database content is checked by juser:set(), not by this constructor.
Replaces the JSON user database. Pass the database directly; each top-level key is a username, including v. Do not add an outer v wrapper.
Parameters
Return values
Throws
Throws for an invalid user-database object or a userdb argument that is neither a table nor convertible to a string. Lua allocation or errors from table conversion can also throw. JSON syntax and database-schema errors normally return nil, error.
A JSON parsing failure leaves the existing database intact. Once replacement begins, the old users are removed before the new records are validated. A schema or allocation error during replacement can leave an empty or partially populated database; failure does not restore the old users. Always check the return values.
-- Install a user database and check for invalid records.
local ju=ba.create.jsonuser()
assert(ju:set{alice={pwd='example-password',roles={'reader'}}})
Creates a JSON authorizer associated with this JSON user database. Multiple authorizers can share the same user database. The authorizer retains the user database for its lifetime.
Parameters
None.
Return values
Throws
Throws for an invalid JSON user-database object or Lua allocation failure.
The combined JSON authenticator user database and the JSON authorizer provide a ready-to-use user database and constraint management using JSON as the database format. The JSON user database and the JSON constraints can be saved to a file system.
Examples:The following example sets up an authenticator and authorizer that simulates the same authentication and authorization logic as in the security C code example. The tutorial How to Create a WebDAV Server explains in detail how this example works.
-- Set up users. Defaults: maxusers=5, recycle=false, inactive=0.
local userGuest={pwd='guest',roles={'guest'},maxusers=100}
local userKids={pwd='kids',roles={'guest','family'}}
local userDad={pwd='dad',roles={'guest','family','dad'},recycle=true,inactive=60*60}
local userMom={pwd='mom',roles={'guest','family','mom'},recycle=true,inactive=60*60}
-- Create a JSON user database object and install the user database
local authuser=ba.create.jsonuser()
authuser:set{guest=userGuest,kids=userKids,dad=userDad,mom=userMom}
-- Create a digest authenticator (using default values).
local authenticator=ba.create.authenticator(authuser)
-- Setup the constraints
local constr1={urls={'/*'},methods={'GET'},roles={'guest'}}
local constr2={urls={'/*','/family/*'},methods={'POST'},roles={'mom','dad'}}
local constr3={urls={'/family/*'},methods={'GET'},roles={'family'}}
local constr4={urls={'/family/mom/*','/family/dad/*'},methods={'GET'},roles={'mom','dad'}}
local constr5={urls={'/family/dad/*'},methods={'POST'},roles={'dad'}}
local constr6={urls={'/family/mom/*'},methods={'POST'},roles={'mom'}}
local constr7={urls={'/family/kids/*'},methods={'GET','POST'},roles={'family'}}
-- Note, the constraint names are not used by the authorizer.
local constraints={Guest=constr1,FamilyPost=constr2,FamilyGet=constr3,
Parents=constr4,Dad=constr5,Mom=constr6,Kids=constr7}
-- Create the authorizer and install the constraints.
local authorizer=authuser:authorizer()
authorizer:set(constraints)
-- Create a directory and set the authenticator and authorizer
local dir=ba.create.dir()
dir:setauth(authenticator,authorizer)
-- Note: you must also reference (anchor) the dir so it is not garbage collected.
Creates a WebDAV directory. It inherits the directory methods and requires a specialized 404 handler. See also WFS and asynchronous uploads.
Parameters
Return values
Throws
Invalid I/O objects and values that cannot be converted to integers in the priority or limit positions raise an argument error. A missing maxlocks after maxuploads also raises an error. Failure to enable locking does not throw; requests are handled with locking disabled.
Gets the backend supplied to the constructor.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws if called with an object of the wrong type.
Creates an HTTP directory. Retain a Lua reference while it is installed, unless its parent explicitly retains it.
Parameters
Return values
Throws
Throws for an invalid priority argument or Lua allocation failure.
Creates a virtual directory node.
local function testfunc(_ENV,path)
response:setdefaultheaders()
response:write[[
<!-- example usage -->
<html>
<head>
<title>test</title>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
</head>
<body>
<pre>HELLO WORLD!
]]
print("relative path=",path)
print("absolute path=",request:uri())
response:write[[
</body>
</html>]]
return true -- say we are done
end
testdir = ba.create.dir("test")
testdir:setfunc(testfunc)
testdir:insert()
Run the example one time and navigate to tutorial.realtimelogic.com/test/xyz
Output: HELLO WORLD! relative path= xyz absolute path= /test/xyz
Using ba.create.dir() for RESTful Services
A directory object provides the foundation for designing RESTful services. The following two tutorials show how to transform a simple directory object into a fully functional RESTful service object:
Creates a resource reader selected by the request Host header.
Parameters
Return values
Throws
Throws for an invalid domainname, I/O object, or 404-page argument, or Lua allocation failure.
local domains={
"my-domain-a.com",
"my-domain-b.com",
"my-domain-c.com"
}
local hio=ba.openio"home" -- Mako's home directory
dirs={} -- Reference all domain directory objects: prevent GC of directories.
for _,domain in pairs(domains) do
-- Create a sub-dir for each domain
assert(hio:stat(domain) or hio:mkdir(domain))
local dir=ba.create.domainresrdr(domain, ba.mkio(hio, domain))
dir:insert() -- as root dir
dirs[domain] = dir -- Reference
end
The Lua module wfs installs ba.create.wfs. This function creates a ready-to-use, standalone Web File Server directory containing three interfaces to the same I/O object: the browser-based Web File Manager, the WFS JSON/HTTP service used by NetIo, and a WebDAV server.
The table returned by require"wfs" also supports embedded and customized managers. Its create function creates the JSON/HTTP and WebDAV service without automatically generating a browser page, and its wfm function creates the standard full-page callback. See the dedicated Web File Server and Web File Manager documentation for construction modes, arguments, object methods, protocol details, authentication, and the ES-module embedding API.
Parameters
Return values
Throws
Throws when the parsed io is not a BAS I/O interface, supplied numeric values cannot be converted to integers by the native constructors, maxlocks is missing after maxuploads, maxuploads exceeds the native upload range, or Lua allocation fails. Optional arguments are recognized by type; omit unused ones. There is no constructor nil/error return for later filesystem or request failures.
The created object inherits the standard directory methods. Retain a Lua reference while it is installed in the virtual file system. Protect writable WFS and WebDAV mounts with an authenticator in production.
local wfs = require"wfs" -- Also installs ba.create.wfs
local io = ba.openio"home"
-- Ready-to-use standalone manager at /fs/
app.fs = ba.create.wfs("fs", io, ".LOCK")
app.fs:insert()
-- For an embedded manager, use wfs.create(...) and mount the
-- browser client in an application page. See wfs.html.
Creates a directory that serves resources from a BAS I/O interface.
Parameters
Return values
Throws
Throws if the parsed io argument is not a BAS I/O interface or Lua allocation fails. Optional arguments are recognized by type; use an integer priority and omit it entirely when not needed.
Creates a Barracuda Resource Reader. The first two parameters are the same as ba.create.dir().
The name represents a directory name. io - an I/O interface created by ba.mkio() or ba.openio() a reference to the I/O interface exists for as long as the created object exists.
When using the Mako Server or the Xedge, the two servers automatically create a resource reader for each application loaded. The resource reader directory object is automatically included in the application's environment and can be accessed in the .preload script as 'dir'. You can remove the resource reader from the server's virtual file system as follows if you create an application that does not provide a Web/REST/AJAX API: dir:unlink().
The created object has the following additional directory methods:
Reads the configured application table.
Parameters
None.
Return values
Throws
Throws for an invalid resource-reader object. Lua allocation can also throw.
Returns the retained I/O object.
Parameters
None.
Return values
Throws
Throws for an invalid resource-reader object. Lua allocation can also throw.
Enables LSP processing. Every call resets the persistent-page cache and replaces or removes the application table, even when the filter is already installed.
Parameters
Return values
Throws
Throws for an invalid resource-reader object. Lua allocation can also throw.
Replaces the additional response headers for this resource reader, including its LSP responses.
Parameters
Return values
Throws
Throws for an invalid resource reader or non-table argument. Unsupported keys can cause a Lua table-iteration error. Lua or header-storage allocation failure can throw.
Include additional/custom HTTP headers as part of every response for all resources delivered from the Resource Reader, including LSP pages. The method is typically called in a .preload script (as dir:header{...}) when configuring CORS settings that should be the same for all LSP pages included in the application. Individual LSP pages can set new CORS header values or overwrite the pre-set values.
-- Example: harden security policy
rsrdr:header{
["Content-Security-Policy"]= "default-src 'self'",
["X-Content-Type-Options"]="nosniff",
["Strict-Transport-Security"]="max-age=31536000; includeSubDomains",
}
Sets the cache lifetime for resources served by this reader, excluding LSP output.
Parameters
Return values
Throws
Throws for an invalid resource reader or a seconds value that cannot be converted to an integer.
Inserts a child into the resource reader's prologue directory list, searched before its resources.
Parameters
Return values
Throws
Throws for invalid objects, an already-linked child, insertion into itself, or an invalid reference argument. Reference validation follows insertion, so an invalid reference argument can leave the child inserted. Lua allocation can also throw.
Inserts a directory as a child in the Resource Reader. The method is similar to dir:insert, except for that the directory is inserted in the Resource Reader's prologue directory list. The prologue directory list is search prior to searching for resources in the Resource Reader. Directories inserted with dir:insert() are only searched if the resource was not found in the Resource Reader. Method rsrdr:insertprolog() is typically used when authentication is only needed on sub-directory in the Resource Reader. A prologue directory with an authenticator and directory name matching the directory in the Resource Reader that must be protected can be inserted as a prologue directory. The prologue directory will be activated if the relative URL matches the prologue directory, the authenticator will kick in, and make sure the user is authenticated.Creates a function that saves HTTP PUT or multipart/form-data POST uploads to persistent storage using asynchronous sockets. Call it from an LSP page or a directory callback. Unlike request:multipart() and request:rawrdr(), an active upload does not need a dedicated thread. The implementation uses the C HttpUpload class.
Parameters
Return values
Throws
Throws for an invalid I/O object, an invalid limit type, or a limit outside the supported range. The limit uses Lua integer conversion.
Starts an asynchronous upload. The default call ends execution of the current request handler. Storage and connection failures during an active upload are delivered to errorfunc. Reaching the concurrent upload limit, or failing to allocate an upload node, sends HTTP 503 without invoking a callback.
Parameters
Return values
No values. With return2caller omitted or false, BAS stops the current request handler instead of returning normally.
Throws
Throws for invalid arguments, an expired request, use inside an included response, or a request that is neither PUT nor multipart/form-data POST. The default handler termination also uses Lua error unwinding internally; it is a BAS control transfer. Active-upload failures use errorfunc rather than an exception in the original caller.
Called for each multipart file after extracting its filename and before opening the destination file. It is not called for PUT. Use it to validate the destination. Calling upload:response() stops receiving the upload and lets you send an early response.
Parameters
Return values
Callback return values are ignored.
Throws
Errors raised by your callback are caught and logged by the upload binding. They terminate the upload; if no deferred response has been obtained, BAS sends HTTP 500.
Called when the upload request completes successfully. Obtain upload:response() and send and close the response. If the callback finishes without obtaining a deferred response, BAS sends HTTP 500 (No response in Lua callbacks).
Parameters
Return values
Callback return values are ignored.
Throws
Errors raised by your callback are caught and logged by the upload binding. They terminate the upload; if no deferred response has been obtained, BAS sends HTTP 500.
Called for an error during an active upload, such as a failed file write or broken connection. A response can only be delivered if the connection is usable. Without a deferred response, BAS attempts to send HTTP 500.
Parameters
Return values
Callback return values are ignored.
Throws
Errors raised by your callback are caught and logged by the upload binding. They terminate the upload; if no deferred response has been obtained, BAS sends HTTP 500.
Gets the destination path.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws for an invalid or expired upload handle.
Gets the URL recorded for the upload request.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws for an invalid or expired upload handle.
Identifies the upload request format.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws for an invalid or expired upload handle.
Looks up the session associated with the upload request.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws for an invalid or expired upload handle.
Switches the upload from receiving data to sending a response. In a start callback, this stops the upload early. Close the returned response when finished.
Parameters
None, apart from the object before the colon.
Return values
Throws
Throws for an invalid or expired upload handle, or if a response has already been obtained for this upload.
Run a command and wait for completion. Output collection stops after reaching at least 65536 bytes; the final read can extend beyond that threshold. The BAS mutex is released while waiting and reading. Available only on supported process-based platforms. See also ba.forkpty().
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Failure to open the pipe and nonzero process status are returned rather than thrown.
See also
Binary JSON
XML Parser
A library that supports JSON encoding and decoding.
Encodes one or more Lua tables. Multiple tables produce consecutive JSON documents in one string.
Parameters
A table with a nonzero raw length becomes an array of its indexed values; other keys are ignored. Otherwise it becomes an object with string or numeric keys. An empty table becomes {}. Unsupported value types and recursive table references become JSON null. Unsupported object-key types produce an error return.
Return values
Throws
Throws if the first argument is not a table, or a later argument before size is neither a table nor numeric. Errors from array-access metamethods can propagate. Reported encoding errors return nil and an error string; Lua allocation failures outside the protected result-copy step can still throw.
Decodes one or more complete JSON objects or arrays. Top-level scalar values are not supported.
Parameters
jnull is recognized only when the next argument is boolean; otherwise that argument occupies the stacklen position. Nil selects the default for a numeric option.
Return values
Throws
Throws if json cannot be read as a string or the numeric options cannot be read as Lua integers. Parse errors use the error returns above. Lua allocation failures while constructing the result can throw.
print(ba.json.decode('{"myvar":null}').myvar == ba.json.null) -- prints true
print(ba.json.decode('{"myvar":null}',false).myvar == nil) -- prints true
local table1, table2 = ba.json.decode('{}{}')
assert(type(table1) == "table" and type(table2) == "table")
Parameters
Return values
Throws
Throws if the argument cannot be read as a Lua string. Invalid UTF-8 returns nil, "utf8". Lua allocation failure can throw.
Creates a parser that accepts JSON objects and arrays in successive chunks. Use ba.json.decode when all input is already available.
Parameters
Options use the same positional rules and minimums as ba.json.decode.
Return values
Throws
Throws if numeric options cannot be read as Lua integers or Lua cannot allocate the parser and its state.
The JSON parser is ideal for building advanced, asynchronous, message passing protocols on any type of communication channel. The communication can, for example, be between a standalone web server and other programs, or between embedded systems that are interconnected. The JSON parser can easily be used together with the socket library, but you can also use the JSON parser in combination with your own specialized communication channels such as message queues, USB connections, serial connections, etc.
Parses a chunk and retains any incomplete object or array for the next call.
Parameters
Return values
Throws
Throws for an invalid parser receiver or data that cannot be read as a string. Lua allocation failures can throw. Incomplete input is accepted; parse failures return nil and an error code. Create a new parser after a parse failure.
The following example shows a potential use case for the JSON parser. A specialized LSP page is designed to extract the active socket connection from the current request and morph the HTTP request into an asynchronous receive channel for JSON data. See the socket API for more information on how to use sockets. Note: see also the JSONS module.
<?lsp
-- Activated when s:event(asyncReceiveCoroutine) is called below
local function asyncReceiveCoroutine(s)
local parser=ba.json.parser()
-- variable x: multiple types, or nil on error
local x,err=true,nil
while x do -- While no error
-- Block and wait for data
x,err=s:read()
if x then -- x is JSON socket data
local array
x, array = parser:parse(x,true)
if x then -- If ok
if array then -- If at least one object
for _,v in ipairs(array) do
-- Dispatch the parsed JSON object 'v'
end
end
else
-- Parse error
err=array -- array is now error code
end
end
end
if err == "closed" then
print"Socket closed"
else
print("Socket or JSON parser error:", err)
end
send=nil
-- Return: exit and close connection
end
response:flush() -- Send HTTP response headers
-- Morph HTTP request into a socket connection
local s = ba.socket.req2sock(request)
-- Enable asynchronous socket receive
s:event(asyncReceiveCoroutine)
?>
The above code is designed to receive data. You can easily extend the code to also send asynchronous JSON data to the client side.
Example 2, JSON Client:The following example shows a basic JSON HTTP client that can be used with the JSON service above.
local c=http.create.basic()
c:request{method="GET",url="URL-TO-SERVER_RESOURCE"}
-- Morph HTTP request into a socket connection
local s=ba.socket.http2sock(c)
local data={txt="hello"} -- The data to send
s:write(ba.json.encode(data)) -- Encode and send
JSONS (JSON stream parser) is a small Lua library that simplifies the use of the JSON parser object when using the JSON parser for parsing data that trickles in on a TCP/IP connection or on a WebSocket connection.
Load the library as follows.
local js = require("JSONS")
JSONS functions:
Creates a JSON stream reader/writer. Load the module with local js = require("JSONS"). The wrapper retains the supplied socket and uses its read, write, state, and close methods.
Parameters
Return values
Throws
Throws for an invalid maxsize, a protected instance metatable, or errors raised by instance/configuration table access. Lua/parser allocation failures can also throw. Socket misuse may only be detected by a later method call.
Optional callback supplied as cfg.bincb. Called synchronously by get for each binary WebSocket chunk; get continues looking for a JSON value after the callback returns.
Parameters
Return values
Throws
Callback errors propagate from get; JSONS does not catch them. A callback error does not set the persistent parser/size error, but the binary chunk has already been consumed.
Reads and returns one top-level JSON object or array as a Lua table. Supports blocking sockets and sockets used in their required asynchronous/cosocket context.
Parameters
Return values
Throws
Throws for an invalid instance/socket, unsupported socket use or execution context, or a failure in cfg.bincb. Lua allocation and table-access errors can also throw. Ordinary socket, parser, and size failures return nil and an error string.
The native parser handles partial input and multiple values in a read. Complete values are queued for subsequent get calls. The maxsize guard is checked only when parsing produces no complete value. After a parser or size error, later get calls return that error without reading more data; close the socket. Timeouts and unhandled binary chunks do not set this persistent error, and partial text data is retained. get never closes the socket itself.
Encodes a Lua table as JSON and writes the encoded bytes to the socket. For WebSockets, sends a text WebSocket frame. For TCP sockets, sends the same JSON bytes. The receiving maxsize option does not limit outgoing data.
Parameters
Return values
Throws
Throws for a non-table input, invalid instance/socket, unsupported socket use, or errors raised by encoding table access. The BAS socket also throws if a WebSocket payload exceeds 65535 bytes. Returned encoding and socket errors are forwarded as nil, error.
Encodes a Lua table as JSON and writes the encoded bytes to the socket. For WebSockets, sends a binary WebSocket frame. For TCP sockets, sends the same JSON bytes. The receiving maxsize option does not limit outgoing data.
Parameters
Return values
Throws
Throws for a non-table input, invalid instance/socket, unsupported socket use, or errors raised by encoding table access. The BAS socket also throws if a WebSocket payload exceeds 65535 bytes. Returned encoding and socket errors are forwarded as nil, error.
Calls the retained socket's close method. Pending parsed values and wrapper state are not cleared.
Parameters
None. Additional arguments are ignored.
Return values
Throws
Throws for an invalid instance/socket or an error raised by the socket adapter. The BAS close method does not return a separate error string.
Load Lua code through a BAS I/O object.
Parameters
Return values
Throws
Throws for an invalid filename argument, an invalid I/O userdata, or a supplied environment that is not a table. File-loading and Lua compilation errors are returned as nil and an error message.
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. An unknown extension is not an exception.
The DateTime type represents dates and times with values ranging from 00:00:00 (midnight), January 1, 0001 through 11:59:59 P.M., December 31, 9999 in the Gregorian calendar. Time values are measured in nanosecond units called ticks. The ticks are internally stored as a 3-tuple {seconds, nanoseconds, offset}. The offset represents a time zone in minutes controlled by you. The 3-tuple {0, 0, 0} represents the time "1970-01-01T00:00:00Z". The time is internally always assumed to be UTC. The offset is used during encoding to ISO 8601 and optionally when encoding to TimeTable.
The DateTime object works together with the following supporting Lua tables:
TimeTable : {
year = integer, -- 1 to 9999
month = integer, -- 1 to 12
day = integer, -- 1 to [max value depends on month]
hour = integer, -- 0 to 23
min = integer, -- 0 to 59
sec = integer, -- 0 to 59
nsec = integer, -- 0 to 999,999,999
offset = integer, -- -1,439 to +1,439 [ i.e. time zone +- 60*24-1 ]
}
TimeSpan : {
days = integer, -- Whole days; default: 0
hours = integer, -- Whole hours; default: 0
mins = integer, -- Whole minutes; default: 0
secs = integer, -- Whole seconds; default: 0
nsecs = integer, -- -999999999 to 999999999; default: 0
}
Constructors validate the initial date and the adjusted result within years 1 through 9999 at the stored offset. They validate integer values before converting to narrower C fields. A TimeSpan cannot repair an invalid initial date. Numeric arguments and table fields checked as integers also accept values Lua can convert exactly to integers; the optional NOW offset must have Lua integer type.
TimeSpan fields may be positive or negative. Converting the fields to seconds must not overflow a signed 64-bit integer, including intermediate sums. Arithmetic normalizes the nanosecond component before checking the resulting date range.
Creates a new DateTime at the earliest supported instant, 0001-01-01T00:00:00Z.
Parameters
Return values
Throws
Lua allocation failure can throw. This fixed-value constructor does not return nil and an error message.
Creates a new DateTime at the latest supported instant, 9999-12-31T23:59:59.999999999Z.
Parameters
Return values
Throws
Lua allocation failure can throw. This fixed-value constructor does not return nil and an error message.
Creates a DateTime using the current UTC clock. Clock precision depends on the platform.
Parameters
None.
Return values
Throws
Throws for incorrect argument types or table fields that cannot be converted to integers. Lua allocation failure and errors raised by table field access can also throw. Invalid date values and ranges return nil and an error string.
Creates a DateTime using the current clock.
Parameters
Return values
Throws
Throws for incorrect argument types or table fields that cannot be converted to integers. Lua allocation failure and errors raised by table field access can also throw. Invalid date values and ranges return nil and an error string.
Parses an ISO 8601 timestamp, preserving its timezone offset.
Parameters
Return values
Throws
Throws for incorrect argument types or table fields that cannot be converted to integers. Lua allocation failure and errors raised by table field access can also throw. Invalid date values and ranges return nil and an error string.
Creates a DateTime from calendar fields.
Parameters
Return values
Throws
Throws for incorrect argument types or table fields that cannot be converted to integers. Lua allocation failure and errors raised by table field access can also throw. Invalid date values and ranges return nil and an error string.
Creates a DateTime from UTC seconds, a nanosecond component, and a display offset.
Parameters
Return values
Throws
Throws for incorrect argument types or table fields that cannot be converted to integers. Lua allocation failure and errors raised by table field access can also throw. Invalid date values and ranges return nil and an error string.
ba.datetime returns a DateTime object with these methods.
Formats the instant as ISO 8601 using the stored offset or a temporary override. Does not change the stored offset.
Parameters
Return values
Throws
Throws for an invalid DateTime object or an integer offset outside -1439 through 1439. Lua allocation failure can also throw. The __tostring metamethod uses the same formatter.
Reads or changes the stored display offset without changing the instant.
Parameters
Return values
Throws
Throws for an invalid DateTime object or an integer offset outside the supported range. The setter does not check whether displaying the instant at the new offset crosses the calendar limits; tostring() or date(true) can subsequently report that range error.
Returns the stored instant and offset as three separate values.
Parameters
None.
Return values
The full supported calendar requires 64-bit Lua integers to represent secs. The binding does not check for narrowing in a build with smaller Lua integers.
Throws
Throws for an invalid DateTime object. Does not validate the stored calendar range.
Converts the instant to calendar fields.
Parameters
Return values
The returned table contains these integer fields:
Throws
Throws for an invalid DateTime object or a non-boolean local argument other than nil. Calendar conversion failure returns nil and an error string.
In addition, the DateTime object supports the following meta methods: __add, __sub, __eq, __lt, __le, and __tostring. The metamethods enable arithmetic operations and automatic conversion to ISO8601 string.
Valid operations:first - second: first and second are DateTime userdata. Returns nanoseconds (integer), the nonnegative difference between the instants.datetime +/- span: datetime is DateTime userdata and span is a TimeSpan table. Returns result (DateTime userdata), preserving datetime's offset.datetime +/- nanoseconds: datetime is DateTime userdata and nanoseconds is an integer. Returns result (DateTime userdata), preserving datetime's offset.first OP second: first and second are DateTime userdata; OP is <, <=, ==, ~=, >=, or >. Returns matches (boolean), comparing the stored instants.Throws
DateTime addition and subtraction throw for invalid operand types, invalid TimeSpan fields, or a TimeSpan seconds calculation that overflows a signed 64-bit integer. They also throw if an input DateTime is invalid or the result falls outside years 1 through 9999 at the object's stored offset. Nanoseconds must be normalized to 0 through 999999999 and the offset must be within -1439 through 1439 minutes. Adding two DateTime objects is not supported and throws.
Subtracting two DateTime objects also throws if first is earlier than second or the nanosecond difference exceeds the maximum Lua integer. These are programmer errors; the operators do not return nil and an error message. Failed arithmetic leaves both input objects unchanged.
print(ba.datetime"MIN") -- Prints: 0001-01-01T00:00:00Z
print(ba.datetime"MAX") -- Prints: 9999-12-31T23:59:59.999999999Z
print(ba.datetime"NOW") -- Prints the current UTC time
print(ba.datetime(0)) -- Prints: 1970-01-01T00:00:00Z
print(ba.datetime(0,0,60)) -- Prints: 1970-01-01T01:00:00+01:00
print(ba.datetime(0,0,-60)) -- Prints: 1969-12-31T23:00:00-01:00
print(ba.datetime"MIN" + {secs=62135596800}) -- Prints: 1970-01-01T00:00:00Z
-- MIN + (59 seconds and 123456789 nano seconds)
print(ba.datetime"MIN" + 59123456789) -- Prints 0001-01-01T00:00:59.123456789Z
-- Catch the deliberately invalid operation so the rest of this example runs.
local ok, err = pcall(function() return ba.datetime"MIN" - 1 end)
print(ok, err) -- false, error message containing "Invalid datetime range"
print(ba.datetime{year=1000}) -- Prints: 1000-01-01T00:00:00Z
print(ba.datetime({year=2000}, true)) -- Prints: 2000-01-01T00:00:00Z
print(ba.datetime({year=2000,offset=60},true)) -- Prints: 2000-01-01T00:00:00+01:00
print(ba.datetime({year=2000}, {days=-2000})) -- Prints: 1994-07-11T00:00:00Z
print(ba.datetime(-62135596800)) -- Prints: 0001-01-01T00:00:00Z
print(ba.datetime(-62135596800,0,0,
{hours = 62135596800/(60*60)})) -- Prints: 1970-01-01T00:00:00Z
The I/O interface provides common functions for working with files stored on different media types, including standard file systems, ZIP files, and network files. The Lua I/O interface connects to the C-side implementation of IoIntf. C startup code initializes these interfaces and makes them accessible to Lua via ba.openio(ioname). New I/O interfaces can be created using ba.mkio(baseio, path).
The I/O interfaces are supported on all environments, from High Level Operating Systems (HLOS) to deep embedded RTOS environments. The standard Lua I/O is also supported on all HLOS, but not RTOS environments. The standard Lua I/O can be accessed by prefixing 'io' with _G. Example: local io = _G.io.
The I/O interfaces are delivered as C code and require compilation, linking, and installation by the C startup code. The Mako Server and Xedge provide examples for setting up these interfaces. ZipIo and NetIo are suitable for embedded systems without a file system, with NetIo for development and ZipIo for deployed applications. See the NetIo Tutorial for how to use the NetIo in an embedded device without a file system during development.
Parameters
None.
Return values
Throws
No explicit argument errors. Lua allocation failure can throw.
Returns a table with all I/O resources registered by the C/C++ startup code. The C/C++ startup code must call the function balua_iointf() for each I/O that should be available to the Lua code. The key is the I/O name, and the value is the I/O resource. See the I/O Methods for information on the methods supported by the returned objects.for name,io in pairs(ba.io()) do print(name, io:realpath"", io:resourcetype()) assert(io == ba.openio(name)) end
Parameters
Return values
Throws
Throws if ioname cannot be read as a string. An unknown name returns nil.
Returns a Barracuda I/O object. The I/O object must have been installed by the C startup code by calling function balua_iointf().C/C++ startup code example:
/* Register the DiskIo as "disk" */ balua_iointf(L, "disk", (IoIntf*)&diskIo);
Lua code example:
--Open the "disk" I/O interface created by the C startup code:
local diskio = ba.openio("disk")
--Open the "net" I/O interface created by the C startup code:
local netio = ba.openio("net")
balua_installZIO.Queries the ZIP security configuration installed by the C startup code.
Parameters
None.
Return values
Throws
No explicit argument errors in the no-argument form.
Creates a ZIP I/O interface for an embedded ZIP reader installed by balua_installZIO.
Parameters
Return values
Throws
Throws if name cannot be read as a string. Lua allocation failures can throw. Reported ZIP creation failures return nil and an error code.
Parameters
Return values
Throws
Throws for an invalid or unavailable baseio, a path that cannot be read as a string, or a Lua allocation failure. Backend path lookup, duplication, and ZIP initialization failures return nil and an error code.
Dynamically create an I/O interface object by opening a directory, a URL, or a ZIP file. The path must be relative to the base I/O. The I/O object returned from this function have the same methods as ba.openio().
-- Create a new DiskIo instance by using the sub directory "tmp" as
-- the base directory for the new I/O:
local appsio = ba.mkio(ba.openio("disk"), "tmp/")
print("appsio:")
for name in appsio:files"/" do print(name) end
-- Create a ZipIo by opening a ZIP file in the /home/mako/tutorials/
-- directory:
local zio = ba.mkio(ba.openio("disk"), "/home/mako/tutorials/intro.zip")
print("\nzio:")
for name in zio:files"/" do print(name) end
-- Required by the two examples below using https://
ba.openio("net"):netconf{shark=ba.sharkclient()}
-- Create a new NetIo by using the URL
-- https://tutorial.realtimelogic.com/fs/home/mako/tutorials/
-- as the base path. Note: Requires that a wfs instance is running on
-- tutorial.realtimelogic.com/fs/.
local netio = ba.mkio(ba.openio("net"),
"https://tutorial.realtimelogic.com/fs/home/mako/tutorials/")
-- Configure HTTPS on the newly created NetIo as well.
netio:netconf{shark=ba.sharkclient()}
print("\nnetio:")
for name in netio:files"/" do print(name) end
-- Mount the ZIP file
-- https://tutorial.realtimelogic.com/fs/home/mako/tutorials/opc.zip
-- by chaining the NetIo and ZipIo
local netzipio = ba.mkio(
ba.openio("net"),
"https://tutorial.realtimelogic.com/fs/home/mako/tutorials/opc.zip")
print("\nnetzipio:")
for name in netzipio:files"/" do print(name) end
Parameters
Return values
Throws
Throws for an invalid file-handle type, a build without integrated standard Lua I/O support, or Lua allocation failure. An unusable stream or a reported ZIP initialization failure returns nil and an error code.
The ZIP I/O retains the standard Lua file handle. Keep that handle open while using the ZIP I/O. Closing the ZIP I/O releases its reference but does not close the original file handle.
Dynamically create a ZIP I/O by using a Lua file handle that refers to a valid zip file. You may use file handles opened with io.open() and io.tmpfile(). Zip files opened with io.open() must use the "rb" (read binary) mode. Note: this feature requires a server compiled with integrated Lua I/O support.Example 1:
-- Open using std Lua io
local fp = _G.io.open("my-zip-file.zip","rb")
-- Example: extract from zip file and print file content
local zio = ba.mkio(fp)
local fp = zio:open"my-file-inside-zip-file.txt"
print(fp:read"a")
fp:close()
zio:close()
Example 2:
-- Using online tutorial server, open the intro.zip application
local fp = _G.io.open("/home/mako/tutorials/intro.zip","rb")
local zio = ba.mkio(fp)
-- Open Amazon root cert embedded in ZIP file
local fp = zio:open"AmazonRootCA1.pem"
print(fp:read"a")
fp:close()
zio:close()
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if mode cannot be read as a string or does not start with r, w, or a. Backend open failures use the error returns above.
This function opens a file, in the mode specified in the string mode. In case of success, it returns a new file handle.
The optional mode string can be any of the following "POSIX file" open modes:
Note: the DiskIo for most embedded RTOS ports support mode "r" and "w" only. The ZipIo supports mode "r" and the NetIo supports mode "r" and "w".
File handles returned by io:open() provide these methods:
Parameters
None.
Return values
Throws
Throws for an invalid or closed file handle. The handle is marked closed even when the backend reports a close error.
Parameters
None.
Return values
Throws
Throws for an invalid or closed file handle. Backend failures are returned.
Parameters
None.
Return values
Throws
Throws for an invalid file-handle receiver. A closed file handle is accepted.
Parameters
Return values
Throws
Throws for an invalid or closed file handle. Throws for an unsupported format, an option that cannot be read as a string when it is not numeric, or insufficient Lua stack space. The binding does not explicitly reject negative byte counts. Lua allocation failures can throw.
Parameters
Return values
Throws
Throws for an invalid or closed file handle. Throws if position cannot be read as a Lua integer. Backend seek failures are returned.
Parameters
Return values
Throws
Throws for an invalid or closed file handle. Throws if a value cannot be read as a string. Earlier values may already have been written when a later argument or write fails.
local dio = ba.openio"disk"
local fp = dio:open("/tmp/hello.txt", "w")
assert(fp,"Should work on online demo server")
fp:write"Hello\n"
fp:close()
fp = dio:open("/tmp/hello.txt", "a+")
fp:write"World\n"
fp:close()
fp = dio:open("/tmp/hello.txt") -- Defaults to "r" - read mode
print(fp:read"a") -- Read entire file
fp:close()
fp = dio:open("/tmp/hello.txt", "r")
local a,b,c=fp:read(5, 1, "a")
print("a",a)
assert(b == "\n")
print("c",c)
fp:close()
Parameters
None.
Return values
Throws
Throws for an invalid or unavailable I/O receiver, or if the backend type query fails.
Parameters
Return values
Throws
Throws only when the argument is missing. Nil and other non-file values return nil.
Parameters
Return values
Throws
Throws for an invalid I/O receiver, an unreadable dirname argument, missing directory support, or failure to open the directory. Directory-read errors end iteration without an error result. Lua allocation failures can throw.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if the backend has no stat function. Missing paths and other backend failures use the error returns.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Unavailable paths return no values.
Creates a directory.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if the backend has no implementation of this operation. Backend failures use the error returns.
Removes a directory.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if the backend has no implementation of this operation. Backend failures use the error returns.
Removes a file.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if the backend has no implementation of this operation. Backend failures use the error returns.
Renames a file or directory.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if newpath cannot be read as a string or the backend has no rename implementation. Backend failures use the error returns.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if a supplied _ENV is not a table. Loading and compilation failures use the error returns.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if a supplied env is not a table, loading or compilation fails, environment assignment fails, or execution of the chunk raises an error.
Sets or clears the hidden-file attribute on backends that support it.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string. Throws if action cannot be read as a Lua integer.
Sets the password for accessing a ZIP file that was opened using ba.openio or created with ba.mkio, provided the ZIP file is password-protected. The Barracuda platform only supports ZIP files encrypted with AES.
In addition to setting a password for individual ZIP files, you can apply a password to all loaded ZIP files globally when compiling the C code. This method allows embedding an obfuscated password that automatically applies to all ZIP files. See Signed and Encrypted ZIP files for more details. You can still set a password for specific files, which will override the globally applied password.
Parameters
See binpwd2str for the binary password format.
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a password that cannot be read as a string. If setting the password succeeds, supplied non-nil options must be booleans; invalid options then throw. The password is set before those options are checked.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver or a path that cannot be read as a string.
Parameters
None.
Return values
None.
Throws
Throws for an invalid or unavailable I/O receiver, a statically registered I/O, an unsupported close operation, or a backend close failure.
Close a dynamically created ZipIo, i.e., a ZipIo created with function ba.mkio(). The ZipIo can no longer be used after you callio:close().io:close(). This function is designed for operating systems such as Windows and CE that lock open files. The file cannot be deleted from the file system before it is closed. Explicitly calling io:close() makes it possible to delete the ZIP file from the file system without waiting for the garbage collector to collect the dynamically created ZipIo.The NetIo is similar to a network file system and makes it possible for the server to access resources on another Barracuda server. NetIo is typically used during development and is often required when developing Lua code on an embedded device with no native file system support. See the NetIo Tutorial for details on using the NetIo client and server to set up a network file system.
Note that you may get severe performance degradation when using the NetIo since the NetIo generates multiple requests for each resource fetched. The NetIo speed is directly proportional to the speed of the TCP/IP stack being used in the embedded system. The faster the TCP/IP stack, the faster the NetIo will respond. The following diagram illustrates a page request using the NetIo:
Browser Embedded System Web File Server | | | | get page | | | ---------------> | | | | stat (file exists?) | | | --------------------> | | | yes | | | <------------------- | | | | | | get fragment 1 | | | --------------------> | | | fragment 1 | | response | <------------------- | | <--------------- | | | | | | | get fragment 2 | | | --------------------> | | | fragment 2 | | response | <------------------- | | <--------------- | | | | | | | |
Figure 6: Browser to Device to WFS Sequence Diagram
A NetIo is typically created and installed in an uninitialized state by the C/C++ startup code. Method io:netconf() lets you configure either the NetIo installed by the C/C++ startup code or a NetIo clone created with ba.mkio(). See the NetIo C documentation for more information.
Parameters
Return values
Throws
Throws for an invalid or unavailable I/O receiver, a non-table options argument, unreadable string fields, or an invalid proxyport type when it is checked. A supplied SharkSSL userdata must have the correct type and client role. A checked backend operation returning "not implemented" throws "Not a NetIo object". Errors from options-table metamethods can propagate.
Configuration is applied in stages. Earlier changes remain if a later option fails; the call does not roll them back. A rejected SharkSSL property update releases the newly acquired reference and follows the same error handling as other property updates.
Configure the source NetIo before calling ba.mkio(netio, URL) when accessing the URL requires credentials, a proxy, or HTTPS. The two-argument constructor verifies the path. A new NetIo clone does not retain the source object's SharkSSL configuration; configure shark on the clone before using HTTPS through it.
Always supply a path or URL with a base I/O object. ba.mkio(netio) is not a supported clone form, and ba.mkio() is the ZIP security query described above.
Reports memory statistics when the BAS build uses the bundled dlmalloc allocator, includes mallinfo support, and registers this function.
Parameters
None. Additional arguments are ignored.
Return values
The binding converts native counters to Lua integers without checking for narrowing. Statistics are sampled before allocating the result table.
Throws
Lua allocation failure while constructing the result can throw. The binding performs no argument checks and does not return nil and an error string.
local fmt=string.format
-- Inspect the configured heap and allocator footprint.
local m=ba.mallinfo()
print(fmt("\nTotal memory: %d bytes",m.size))
print(fmt("Peak footprint: %d bytes",m.usmblks))
print(fmt("Used: %d%% (%d bytes)", m.uordblks*100//m.size, m.uordblks))
print(fmt("Free: %d%% (%d bytes)",(m.size-m.uordblks)*100//m.size, m.size-m.uordblks))
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua integer.
Encodes time in a format suitable for an HTTP response.-- Prints: Thu, 01 Jan 1970 00:00:00 GMT print(ba.encdate(0)) -- Prints 1000 print(ba.parsedate(ba.encdate(1000)))
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Unrecognized date text returns 0.
Parses the date string and returns the number of seconds since 1970-01-01 00:00:00 GMT. This function is designed for parsing the HTTP date header and is used by several library functions such as http:stat().-- Prints the number 0 print(ba.parsedate"Thu, 1 Jan 1970 00:00:00 GMT") -- Prints: 2001-09-11T18:00:00Z print(ba.datetime(ba.parsedate"Tue, 11 Sep 2001 18:00:00 GMT"))
Parameters
Return values
Throws
Throws if the required argument cannot be read as a Lua string. Throws if embed is supplied and is neither boolean nor nil. LSP preprocessing errors are returned as nil and a message.
Parses and returns the Lua Server Page as a Lua chunk. The returned string can for example be loaded by function load().
The default is to parse the LSP page as a standalone page, unless embed is set to true. The LSP page expects the following arguments when compiled as a standalone page: page(_ENV,pathname,io,page,app), where _ENV is the command environment, pathname is typically derived from a directory functions relative path. The arguments io,page, and app are the LSP page's I/O object, page table, and application table.
See the tutorial How to Build an Interactive Dashboard App for a practical example of how to use function ba.parselsp()
Function parselsp can for example be used as an alternative to response:include(). The following example shows how to use parselsp in one LSP page to include another LSP page.
<?lsp
local fp,err=io:open"mypage.lsp"
if fp then
local data
data,err = fp:read"a"
fp:close()
if data then
-- Convert LSP to Lua
data,err = ba.parselsp(data)
if data then
local func
-- Compile Lua code
func,err = load(data,"mypage.lsp","t",_ENV)
if func then
local ok
-- Let child use our: _ENV,io,page,app
ok,err = pcall(func,_ENV,"mypage.lsp",io,page,app)
end
end
end
end
?>
Adds seed data to the SharkSSL random generator used by the random-data and AES functions.
Parameters
Return values
None.
Throws
Throws if seed is neither numeric nor readable as a string. The binding does not explicitly check the numeric range or the seed function's return status.
The following example connects to the Randomness Beacons project at NIST, downloads the data, and compacts the downloaded data using HMAC SHA512. The binary SHA512 string (64 bytes long) is then used as seed value.
ba.thread.run(function() -- Run the blocking HTTP request in a separate thread
-- Create an HTTP object
local http=require"httpc".create()
local ok,err=http:request{
trusted=true,
url="https://beacon.nist.gov/beacon/2.0/pulse/last",
}
if ok and http:status() == 200 then
local rnddata=http:read"*a" -- Read all random data
rnddata=ba.crypto.hash("hmac","sha512",ba.clock())(rnddata)(true,"binary")
ba.rndseed(rnddata) -- 512 bit compacted value (16 32bit words)
end
-- Seed using millisec clock.
-- The HTTP response time creates a random delay.
ba.rndseed(ba.clock()) -- Number
end)
Returns a random integer within an inclusive interval. With no arguments, or with a single argument of 0, the interval is 0 through math.maxinteger. This provides 63 random bits.
Parameters
Bounds must be convertible to Lua integers. BAS floors fractional numeric arguments during this conversion.
Return values
Throws
Throws for more than two arguments, bounds that cannot be converted to Lua integers, a negative single upper bound, or low greater than high. Also throws "random generator failed" if the random generator reports failure or all 64 attempts are rejected during range selection.
local value = ba.rnd() -- 0 through math.maxinteger local bits31 = ba.rnd(0x7fffffff) -- Explicit 31-bit range local die = ba.rnd(1, 6) -- 1 through 6
Generates a random integer containing up to size bytes of random bits.
Parameters
Return values
Throws
Throws if size cannot be read as a Lua integer or the random generator reports failure. The binding does not reject an out-of-range size.
Returns a string of random bytes.
Parameters
Return values
Throws
Throws if size cannot be read as a Lua integer, is outside 1 through 65535 after conversion, or the random generator reports failure. Lua allocation failure can also throw.
Find an existing session by numeric ID, reference string, or session URL. Only the numeric-ID form can be used without a request object. Missing or invalid session references return false; these calls do not create new sessions.
Parameters
Return values
Throws
The numeric-ID form does not explicitly validate argument types. An unknown ID returns false.
Parameters
Return values
Throws
Throws for an invalid or expired request object, or a supplied create value that is neither boolean nor nil. Lookup failure returns false.
Parameters
Return values
Throws
Throws for an invalid or expired request object, a relpath that cannot be read as a string, or an invalid create type when a reference lookup is attempted. A missing session returns false without a second result.
See request:session() for cookie-based session management and the Web File Server for session URL usage.
local s = request:session(true) local id = s:id() -- Returns a number suitable for local server use assert(id == ba.session(id):id())
Parameters
Return values
Throws
Throws if username is supplied but cannot be read as a Lua string. A user with no active sessions produces an empty table.
Parameters
Return values
None.
Throws
Throws if milliseconds cannot be read as a Lua number. The binding does not explicitly check the sign or range.
Pauses the execution of the current request or thread for the specified duration in milliseconds. The pause may allow other Barracuda threads to run, potentially resulting in a longer pause than specified. Calling ba.sleep(0) allows other pending Barracuda threads to execute, effectively acting as a yield operation.
Note: Given that BAS operates largely on an event-driven model use this function sparingly, ideally within the context of an LSP page or when running in ba.thread.run(). Refer to the threading documentation for more information on how this function interacts with Barracuda threads.
Parameters
Return values
Throws
Throws if handler is supplied and is neither a function nor nil. The previous handler is removed before this check, so a bad argument also removes it.
Install a Lua error handler. The error handler is called if a Lua script causes an exception. The callback function's first argument is the error message. The callback function receives the ephemeral _ENV as a second argument if an LSP page produced the error. Function ba.seterrh() returns the previously installed error handler, if any.
Called when BAS reports a Lua error through the installed handler.
Parameters
Return values
None required. BAS discards the callback's results.
Throws
If the callback raises an error, BAS catches and logs it. The error does not escape this callback invocation.
An error handler could for example be installed in a deployed system and send the error message by using the SMTP library. Another possibility is to upload the error message to an online database by using the HTTPS client library. Note: All errors are sent to the Barracuda HttpTrace library, thus a Lua error handler is typically not needed during debugging.
See also Mako Server's logerr option and Xedge's SMTP settings.
Parameters
Return values
Throws
Throws if callbackFn is not a function. Lua allocation failure can also throw. The constructor does not invoke the callback or schedule an event.
Function ba.timer schedules tasks to run after a specified time. It can either call a function once (one-shot timer) or repeatedly at set intervals (interval timer). When creating a timer, the timer callback determines when to stop. If the callback returns true, the timer repeats. If it returns false or nothing, the timer stops and cancels itself automatically. You can easily create specialized timers that run for a while and then stop by returning false. In addition, the timer function can operate as a Lua coroutine, stay in a forever loop, and use coroutine.yield(true) to pause and wait for the next timer tick.
The ba.timer function returns an object with three methods: set, reset, and cancel. These methods control the timer's state, which can be active or inactive. Initially, the timer is inactive and needs to be activated with set. The reset and cancel methods work on an active timer, while set is used to activate or reactivate an inactive timer.
Keep in mind that the timer object, like all Lua objects, can be collected by the Lua garbage collector if no references are held. You might be tempted to immediately call the set method on the returned object like this:
ba.timer(function() trace(ba.datetime"NOW") end):set(5000)
However, this might get garbage collected before the timer runs. To prevent this, keep a reference to the timer object:
timer = ba.timer(function() trace(ba.datetime"NOW") end) timer:set(5000)
Alternatively, the set method has a parameter that enables automatic referencing, allowing the first example to work if you include the reference option.
The ba.timer function allows for creating advanced timer logic. However, if you're looking for a simpler approach similar to the JavaScript timer API, check out our JavaScript-like timer wrapper API. This wrapper offers a familiar interface, closely mirroring JavaScript's timer functionalities, making it easier for users accustomed to JavaScript to manage timers. For those also using the C/C++ API, it's helpful to know that the Lua timer logic internally utilizes the functionality of the C/C++ Barracuda timer class.
Parameters
Return values
Throws
Throws for an invalid timer object or a saved callback error. A callback error is logged and its message is saved when memory is available; later control calls raise that message. Create a new timer to recover from a saved callback error.
An invalid millisecs argument, including a fractional, negative, non-finite, or out-of-range number, also throws. Argument validation occurs before cancelling an existing event or invoking an immediate callback. Otherwise set() cancels the previous event first; a failed scheduling attempt leaves the timer inactive.
Activates an inactive timer object. If the timer is active, the timer is cancelled and then activated. The timer callback function is activated in "millisecs" time unless method "reset" or "cancel" is called before the timer triggers.ba.timer(function() trace(ba.datetime"NOW") end):set(5000,true)
ba.timer(function()
-- This code runs immediately when 'set' is called
local starttime = ba.datetime"NOW"
for i = 1, 10 do
coroutine.yield(true) -- Wait for the next timer tick
trace("This coroutine timer has run for: ",
ba.datetime"NOW" - starttime, "picoseconds")
end
trace("Exiting timer coroutine")
end):set(1000, true, true)
Reschedules an active timer using the new interval, measured from this call. Does not invoke the callback immediately.
Parameters
Return values
Throws
Throws for an invalid timer object or a saved callback error. A callback error is logged and its message is saved when memory is available; later control calls raise that message. Create a new timer to recover from a saved callback error.
Invalid millisecs, including a fractional, negative, non-finite, or out-of-range number, throws only when the timer is active and leaves its existing event unchanged; an inactive timer returns nil,"inactive" without checking that argument. A saved callback error still throws.
Cancels the scheduled event and releases its automatic reference. The timer can be scheduled again with set() unless it has a saved callback error.
Parameters
None.
Return values
Throws
Throws for an invalid timer object or a saved callback error. A callback error is logged and its message is saved when memory is available; later control calls raise that message. Create a new timer to recover from a saved callback error.
-- One-shot timer example: local function timeout() -- do something end -- Create a timer. The timer object 't' is referenced in the _ENV table. t = ba.timer(timeout) -- Set the timeout to one second. t:set(1000)
-- Interval timer that never stops. local function timeout() -- do something return true end -- Create a self referencing interval timer ba.timer(timeout):set(1000,true)
local function timeout()
for i=1,5 do
trace("Interval", i)
coroutine.yield(true)
end
trace("Stop interval")
coroutine.yield(false)
end
-- Create a self referencing interval timer and start the coroutine immediately.
ba.timer(timeout):set(1000,true,true)
A timer callback function in coroutine mode cannot be re-used when the function calls coroutine.yield(false). However, the function can call timer:cancel(), or timer:reset() to either temporarily cancel an active timer or to change the interval time.
This example demonstrates how to create a coroutine timer in an LSP page that can be started, canceled, and reset. The timer is initialized on the first LSP invocation, and subsequent LSP calls reset the timer. You can toggle the cancel/set state using the URL argument ?cancel=. Notice that the printouts follow the pattern A->B->A->B, regardless of how the timer is managed (set, canceled, or reset).
<?lsp
response:setcontenttype"text/plain"
if page.t then -- If timer saved in LSP's persistent page table.
if request:data"cancel" then
if page.cancel then
trace("set: 2000")
page.cancel=false
page.t:set(2000)
else
trace("cancel")
page.cancel=true
page.t:cancel()
end
else
trace("reset: 1000")
page.t:reset(1000)
end
else -- First LSP invocation
-- Create timer
local function run()
trace"--- start ---"
while true do
trace"A"
coroutine.yield(true) -- Wait for the next timer tick
trace"B"
coroutine.yield(true) -- Wait for the next timer tick
end
end
page.t=ba.timer(run)
page.t:set(500)
end
?>
See console for trace data.
The example below illustrates how a wrapper for the timer can be designed to create an API compatible with the JavaScript timer API. Notice the prefixing of _G before the three function names. This specific usage ensures that the functions are declared within the global environment, making them accessible in a manner akin to JavaScript's global scope.
-- setTimeout(callback, delay)
-- Schedules a function to be executed once after a specified delay.
-- callback: function - The function to be executed after the delay.
-- delay: number - The time in milliseconds after which the callback
-- function should be executed.
-- returns a handle - A unique identifier for the timeout.
function _G.setTimeout(callback, delay)
local t = ba.timer(function() callback() return false end)
t:set(delay,true)
return t
end
-- setInterval(callback, interval)
-- Schedules a function to be executed repeatedly at specified intervals.
-- callback: function - The function to be executed at each interval.
-- interval: number - The time in milliseconds between each execution
-- of the callback.
-- returns a handle - A unique identifier for the timeout.
function _G.setInterval(callback, interval)
local t = ba.timer(function() callback() return true end)
t:set(interval,true)
return t
end
-- clearTimer(timer)
-- Cancels a timeout or interval set by setTimeout or setInterval.
-- timer: handle - The identifier of the timeout or interval to clear.
function _G.clearTimer(timer)
timer:cancel()
end
-- Example code
setTimeout(function() trace"One shot timer" end, 100)
local timerHandle = setInterval(function() trace"interval" end, 300)
setTimeout(function()
trace"Canceling interval"
clearTimer(timerHandle)
end,
1000)
setTimeout(function()
for ix=1,5 do
trace("Coroutine timer", ix)
coroutine.yield(true)
end
trace"Done"
end, 1500)
Returns the retained successful-login records, oldest first. The default tracker retains at most 50 records; these are login events, not a list of currently authenticated users.
Parameters
None.
Return values
Throws
Throws if the default tracker is unavailable or Lua allocation fails.
Returns a snapshot of the failed-login tracker cache.
Parameters
None.
Return values
Throws
Throws if the default tracker is unavailable or Lua allocation fails.
Removes failed-login cache entries. It does not clear the separate successful-login history.
Parameters
None.
Return values
Throws
Throws if the default tracker is unavailable or Lua allocation fails.
Replaces the login-notification callback. Call with no arguments to remove it.
Parameters
Return values
None.
Throws
Throws if the tracker is unavailable or a supplied callback is not a function. The previous callback is removed before the new argument is validated, so an invalid argument also removes the previous callback. Lua allocation can throw.
Called by the tracker after a successful login or a reported failed login with a user name.
Parameters
Return values
None.
Throws
Callback errors are caught by the request error handler. The tracker then unregisters the callback, so it receives no further notifications until setlogh() installs another callback.
Parameters
None.
Return values
Throws
No argument-validation errors or operational errors are raised by this binding.
Returns an array with the name(s) of the current active user(s).The following example terminates all sessions:
-- Iterate all authenticated users
for _,name in ipairs(ba.users()) do
-- Iterate all sessions for the user
for _,sesid in ipairs(ba.sessions(name)) do
local s = ba.session(sesid) -- Fetch session using session ID.
print(string.format("Logging out %s:%X IP address: %s",name,sesid,s:peername()))
s:terminate()
end
end
Parameters
None.
Return values
Throws
No argument-validation errors or operational errors are raised by this binding.
Returns 3 values: the BAS library version, the LUA version, and the time and date the library was compiled.
local bv,lv,date=ba.version()
print(bv,lv,date)
-- ba.parsedate requires 'day', but it's not used
date="Mon, "..date:gsub("^(%w+)%s*(%w+)","%2 %1")
print(ba.parsedate(date), ba.datetime(ba.parsedate(date)))
Prints:
5354 504 Nov 14 2022 06:34:18 1668407658 2022-11-14T06:34:18Z
The request object is a global variable in the command environment, accessible in directory functions and Lua Server Pages (LSP). It contains all the information sent by the client to the server, enabling you to handle incoming data like form submissions, query parameters, and more.
Note: The request and response objects are the same instance, meaning that both request-related and response-related methods are combined in a single object. For example, the following assertion will not fail: assert(request == response).
<html>
<!-- request example usage -->
<?lsp
-- has the page been modified in the last 2 minutes
print("<h2>request methods</h2>");
print("<pre>");
request:checktime(os.time() - 120)
print("request:checktime(os.time() - 120)");
print("request:user() ", request:user())
print("request:cookie'z9ZAqJtI'", request:cookie"z9ZAqJtI")
print("request:header'User-Agent'", request:header"User-Agent")
print("\nAll request headers")
for k,v in next, request:header() do print(k,'=',v) end
print("\nrequest:method() ", request:method())
print("request:uri() ", request:uri())
local t =request:data()
print("request:data() ", request:data())
for k,v in next, t do print("\t",k,'=',v) end
print("\nrequest:session() ", request:session(true))
if request:session() then
print("session id", request:session():id(),"\n")
end
print("request:version() ", request:version())
print("</pre>")
?>
</html>
Stops the current request handler and invalidates its request/response object. Prepare the response first. See response:abort().
Parameters
None, apart from the request object.
Return values
Does not return normally.
Throws
Throws if the request object is invalid or expired. Normal termination uses Lua error unwinding as a BAS control transfer.
Checks the allowed HTTP methods at the start of a request handler. A disallowed method produces HTTP 405 and ends the handler. With defaults enabled, BAS handles OPTIONS itself and ends the handler. The check is skipped for a forwarded or included response.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws for a non-table methods argument or an unrecognized method value. Rejection and internal check failures end the handler using BAS control transfer; they do not return false.
-- only allow GET and POST for this page
request:allow{"GET", "POST"} -- Auto abort script if not GET or POST
-- valid request; let's continue
print"hello world"
Test by removing "GET".
Requests a client certificate on a TLS connection when one is not already available. This may initiate a supported TLS renegotiation and cause a browser certificate-selection prompt. Retrieve the certificate and its trust result with request:certificate().
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. TLS negotiation failure returns false. This method is only registered in builds with SharkSSL support.
Gets the peer certificate chain already available on this connection. Calling clientcert() first is only necessary when a certificate has not already been supplied. For Mako CA-store configuration, see certstore.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. Throws if the SharkSSL helper functions have not been installed. A TLS connection without a certificate returns nil, false; a non-TLS connection returns nil, error.
if request:clientcert() then
local certT,trusted = request:certificate()
print("You are", trusted and "" or "not", "trusted")
print(certT and ba.json.encode(certT) or "No client certificate")
end
Gets information about the current TLS connection.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. Throws if the SharkSSL helper functions have not been installed. A non-TLS connection returns nil, error.
Compares the resource modification time with If-Modified-Since. If a valid, nonzero header time is equal to or later than time, sets HTTP 304 with an empty body and ends the handler. Otherwise the handler continues. Call before committing the response.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws if time cannot be converted to an integer. HTTP 304 handling uses BAS control transfer.
-- switch off the default cache headers response:setheader"Cache-control" response:setheader"Pragma" -- check the modified time (anything up to a day old) if not request:checktime(os.time() - (60*60*24)) then return end -- lets provide the updated page print"hello world"
Gets the authenticated user associated with the request.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Creates a server-side login after your application has authenticated the client, for example through an external identity provider. This method does not verify a password or call the configured credential callback. Call before committing the response.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. For a new login, invalid argument types throw. Lua allocation can throw. Admission failure normally returns false; some native allocation failures also send HTTP 503.
Logs out the request user and terminates the associated session. If no user is authenticated, an existing request session is still terminated. Use all=true when all sessions for a named user must be ended, such as after a password change.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws if a supplied non-nil all argument is not a boolean.
Looks up a request cookie.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws for an invalid name type.
Gets the command environment associated with this request.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Gets one request header or a table of all parsed headers.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws for an invalid name type.
Gets the lowercase Host value without its port, for example example.com or [::1]. If Host is absent or the native domain string cannot be allocated, this delegates to request:peername().
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Gets the HTTP request method.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Gets parsed URL-encoded form or query parameters. Use rawrdr() for other body formats and datapairs() to preserve duplicate names.
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Throws for an invalid parameter-name type.
-- get some values
custnbr = request:data("custnbr") -- get the value of custnbr
name, num = request:data("name", "num") -- get two values
-- Print all values.
-- Method request:data() returns a Lua table with all name/val pairs.
for name,value in pairs(request:data()) do
print(name,'=',value)
end
The values printed are the ones used by the tutorial engine.
Additional examples:
Iterates all parsed URL-encoded form or query parameters, including duplicate names. The iterator retains the request object but does not extend its active lifetime.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. Calling the iterator after the request expires also throws.
-- display all posted values
for name,value in request:datapairs() do
print(name,'=',value)
end
Creates a reader for the raw request body, including binary data. It handles Content-Length and chunked transfer encoding. For URL-encoded or multipart form data, use request:data() or request:multipart(). For asynchronous file uploads, see ba.create.upload().
Parameters
Return values
Throws
Throws for an invalid or expired request, an invalid block size, a missing Content-Length without chunked encoding, or a body in URL-encoded or multipart/form-data format. Read failures are returned by reader(), not thrown. Lua allocation failures can still throw.
Reads the next raw-body chunk. A read can wait for network data. It returns up to blocksize bytes, combining native reads when necessary.
Parameters
None.
Return values
If successful native reads have already contributed bytes to the current Lua chunk when a later read fails, that partial chunk is returned first. The next call returns nil, error. Repeated calls after failure keep returning nil, error; repeated calls after normal EOF return nil. Neither case reads the socket again.
Throws
Throws if the owning request expires before reading finishes, or Lua allocation fails. Connection and body-decoding failures return nil, error. Once EOF or failure has been recorded, retrieving that result does not require an active request.
A generic for loop stops at nil and cannot distinguish EOF from failure. Call the reader explicitly when you need to verify that the body was received successfully.
This streaming example logs a read failure and stops the request. Data already written to the response cannot be taken back:
<?lsp
local reader = request:rawrdr()
while true do
local data, err = reader()
if not data then
if err then
trace(err)
request:abort()
end
break
end
response:write(data)
end
?>
This small JSON example waits for normal EOF before decoding or returning a successful response:
<?lsp
if "application/json" == request:header"Content-Type" then
local reader, chunks = request:rawrdr(), {}
while true do
local data, err = reader()
if not data then
if err then
response:senderror(400, err)
request:abort()
end
break
end
chunks[#chunks+1] = data
end
-- Decode only after the complete body has arrived.
local ok, value = pcall(ba.json.decode, table.concat(chunks))
if ok and type(value) == "table" then response:json(value) end
response:senderror(400, "Invalid JSON object or array")
request:abort()
end
?>
<html>
<script>
const data={
weekdays:
["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"]
};
async function sendData() {
const response = await fetch(location.href, {
method: 'POST',
body: JSON.stringify(data),
headers: {'Content-Type': 'application/json'}
});
const result = await response.json();
console.log(result);
document.body.innerHTML = "Server response: "+JSON.stringify(result);
}
sendData();
</script>
<body></body>
</html>
Reads a multipart/form-data POST synchronously, delivering fields and file data to callbacks. The call waits until parsing completes, is canceled, or fails. For asynchronous file storage, see ba.create.upload().
Parameters
Return values
Throws
Throws for an invalid or expired request, an already-committed response, a non-multipart POST, invalid argument types/counts, or an invalid callback combination. An exception raised by any callback is rethrown after the native parser is cleaned up, preserving the original Lua error object. Network, parser, and native allocation failures return nil, error, code. Lua allocation failures can still throw.
Called for each ordinary form field.
Parameters
Return values
Throws
A callback exception stops processing. After parser cleanup, multipart() rethrows the original error object to its caller; it is not replaced by a generic parser error.
Called before the data for each uploaded file. This parser does not save the file; your filedata callback handles its contents.
Parameters
Return values
Throws
A callback exception stops processing. After parser cleanup, multipart() rethrows the original error object to its caller; it is not replaced by a generic parser error.
Called as chunks of file data arrive. The same file can produce many calls.
Parameters
Return values
Throws
A callback exception stops processing. After parser cleanup, multipart() rethrows the original error object to its caller; it is not replaced by a generic parser error.
Called at the end of a successfully parsed multipart request.
Parameters
None.
Return values
Callback return values are ignored.
Throws
A callback exception stops processing. After parser cleanup, multipart() rethrows the original error object to its caller; it is not replaced by a generic parser error.
Called when the native parser reports an error. It is not called again to report a Lua callback exception.
Parameters
Return values
Callback return values are ignored. Returning normally does not turn the failed upload into a success.
Throws
A callback exception stops processing. After parser cleanup, multipart() rethrows the original error object to its caller; it is not replaced by a generic parser error.
This example accepts ordinary form fields and checks the final parser result. File data is discarded because no file callbacks are installed:
local fields = {}
local ok, err, code = request:multipart{
formdata = function(name, value)
if name then fields[name] = value end
end
}
if not ok then
trace("Multipart request failed", err, code)
response:senderror(400, "Upload failed")
request:abort()
end
response:json(fields)
Example forms that produce ordinary-field and file callbacks:
<form method="post" enctype="multipart/form-data"> <input type="text" name="Text input" /> <textarea name="Text area" cols="40" rows="3"></textarea> </form>
<form method="post" enctype="multipart/form-data"> <input type='file' size='40' name='File 1'/> <input type='file' size='40' name='File 2'/> </form>
Gets the request URI path.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Builds an absolute URL from the request host and escaped URI path. This is also used by tostring(request).
Parameters
Return values
Throws
Throws if the request object is invalid or expired.
Gets the request session, optionally creating one. Create the session before committing the response so BAS can send its session cookie. See also ba.session().
Parameters
Return values
Throws
Throws if the request object is invalid or expired. Failure to obtain or create a session returns false.
Gets the HTTP request version.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Checks the actual request connection. See response:redirect2tls().
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired.
Gets the connected client socket address.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. Socket failures return nil, error, code.
Gets the connected server socket address.
Parameters
None, apart from the request object.
Return values
Throws
Throws if the request object is invalid or expired. Socket failures return nil, error, code.
Changes the TCP_NODELAY socket option.
Parameters
Return values
None.
Throws
Throws if the request object is invalid or expired. Throws unless enabled is a boolean. The binding does not return a socket-option status.
The response object is a global variable in the command environment, accessible to directory functions and LSP pages. It offers methods for sending messages to the client. Return values and error handling depend on the method; see each entry below. If you need to compress dynamically generated response data, use the response:setresponse() method to handle this.
Note: The request and response objects are the same instance, meaning that both request-related and response-related methods are combined in a single object. For example, the following assertion will not fail: assert(request == response).
Stops the current LSP page or directory function and invalidates its request/response object. Prepare the response before calling this method. The binding does not itself send or flush data; response completion is handled by the surrounding server code.
Parameters
None.
Return values
None. The method does not return normally.
Throws
Always unwinds Lua execution. For a valid object, it sets the request stop flag, invalidates the object, and raises an internal Lua error that the BAS request error handler recognizes as normal termination. For an invalid or expired object, it throws a programmer error instead.
A calling page can regain control when forward(), redirect(), or include() uses return2caller=true. With false, the destination's stop propagates. Returning to a higher scope does not restore the request/response object.
Lua pcall() can catch the unwind, but it also does not restore the object. Most subsequent request/response method calls throw request/response expired; response:valid() can check its state. The same object is used for request and response, so both names become invalid together.
Gets the body byte count maintained by the response output logic.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Looks up a header in the response header database.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Invalid name types throw.
Requests connection closure after the response is sent.
Parameters
None, apart from the response object.
Return values
None.
Throws
Throws for an invalid or expired request/response object.
Creates a cookie object, or returns an existing cookie with the same name. Names are matched case-sensitively. Set the cookie's attributes and call cookie:activate() before response headers are sent.
Parameters
Return values
Throws
Throws for an invalid or expired response object or an invalid argument type. Native allocation failures return nil, error, code. Creation itself does not check whether headers have already been sent; creating a cookie afterward cannot add it to those headers.
Transfers the request's connection to a deferred response object so the response can be completed later, normally from a thread. Call this before committing the standard response. Use the returned object for subsequent output, set its status and headers before writing its body, and finish with close().
Parameters
None, apart from the active response object.
Return values
Throws
Throws for an invalid or expired response object, or if the standard response is already committed. Lua allocation errors can propagate. This constructor returns no operational error pair.
Requests HTTP/1.0 response mode and disables persistent connections. If chunked transfer mode has already been selected, the native operation does nothing; the Lua binding does not report this refusal.
Parameters
None, apart from the response object.
Return values
None.
Throws
Throws for an invalid or expired request/response object.
Builds a redirect URL from an HTTP or HTTPS URL, a server path beginning with /, or a path relative to the current request. Relative paths normally acquire the request's host and HTTP or HTTPS scheme. Without a Host header, the result remains relative.
Parameters
For example, if the request contains a=2, encoding /next?a=1 with withdata=true produces a URL ending in /next?a=1&a=2. The method adds ? for a new query or & for an existing query, and reuses a trailing ? or &. The same separator rules apply when appending the current session ID. When sessionURL is true, session-ID parameters in the copied request data are omitted as described above; existing query text supplied in url is preserved.
Return values
Throws
Throws for an invalid or expired response object or an invalid URL argument type. Native URL construction failures return nil.
Escapes a path for use in a URL and normalizes dot segments and repeated slashes in the path. For example, a/../path/with spaces becomes path/with%20spaces. Text from the first question mark onward is preserved; this method does not encode query parameter values.
Parameters
Return values
Throws
Throws for an invalid or expired response object or an invalid path argument type. Native allocation failures return nil.
Flushes the current response writer. With the default writer, this can commit the headers and send buffered body data.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object. A failed native flush returns false.
Runs another resource as a forwarded request. Standard directory authentication and authorization checks are skipped for forwarded requests. Call before response headers have been sent. Buffered response body data is discarded. The destination LSP page shares the caller's request environment.
Parameters
Return values
Native operational failures return nil, error, code even with return2caller=false, unless a request stop from the destination propagates. Check the return value to handle a failed dispatch; code after the call can now run on failure. Returning to the caller does not restore an object already invalidated by the destination. Check response:valid() before using request/response methods again.
Throws
Throws for an invalid or expired object, invalid argument types, a missing destination resource, an already-committed response, or a native delegation/output misuse error. Forward nesting is limited to 10 active forwards; exceeding the limit throws. Normal request termination uses the internal Lua unwinding mechanism described under abort().
See include(), directory functions, and Request delegation.
Runs another resource on the server without marking the call as a forward. Standard directory authentication and authorization checks apply when the response is still an initial request. This is an internal dispatch; use sendredirect() to send a redirect to the browser. Call before response headers have been sent. Buffered response body data is discarded. The destination LSP page shares the caller's request environment.
Parameters
Return values
Native operational failures return nil, error, code even with return2caller=false, unless a request stop from the destination propagates. Check the return value to handle a failed dispatch; code after the call can now run on failure. Returning to the caller does not restore an object already invalidated by the destination. Check response:valid() before using request/response methods again.
Throws
Throws for an invalid or expired object, invalid argument types, a missing destination resource, an already-committed response, or a native delegation/output misuse error. Normal request termination uses the internal Lua unwinding mechanism described under abort().
See include(), directory functions, and Request delegation.
Includes another resource's output in the current response without discarding the buffered body. The included LSP page shares the caller's request environment. Inclusion preserves the request path and parameters.
An included page's setstatus() and setmaxage() calls are ignored. Header changes are not generally ignored: setheader() and setcontenttype() can change headers before the response is committed. Coordinate headers with the caller.
Parameters
Return values
An included resource can invalidate the request/response object. Returning with true does not restore it; check response:valid() before using other methods. With return2caller=false, a stop raised by the included resource propagates through the caller.
Throws
Throws for an invalid or expired object, invalid argument types, a missing resource, more than 10 active includes, or a native delegation/output misuse error. A propagated request stop uses the internal Lua unwinding mechanism described under abort(). Native operational errors return nil, error, code when no request stop is propagated.
See forward(), ba.parselsp(), directory functions, Request delegation, and the Dynamic Navigation Menu Tutorial.
Checks whether response headers have been sent.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Gets the command environment associated with this request.
Parameters
None, apart from the response object.
Return values
Throws
Throws if the request object is invalid or expired.
Checks whether processing is outside a forward or include.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Gets the current forward state.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Gets the current include state.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Gets a copy of the body currently held in the default response buffer.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Gets the stored HTTP response status.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
Encodes one or more Lua tables as JSON and sends the result. One table is encoded directly; multiple tables form an outer JSON array. The method discards previously buffered body data, sets Content-Type to application/json and Content-Length to the encoded size, and sets Cache-Control to no-store, no-cache, must-revalidate, max-age=0. It preserves the HTTP status code.
Parameters
Return values
Native buffer allocation, header setup, and output failures are reported. No further output step is attempted after a failed step. A failure may already have changed response headers or sent some data; stop response processing instead of attempting to send another body. The method does not invalidate the request/response object on a returned failure, so the caller can end the request explicitly.
Throws
Throws for an invalid or expired response object, an already-committed response, invalid argument types, or a JSON encoding error such as an unsupported table key or invalid UTF-8. The default successful request termination uses the same internal Lua unwinding mechanism as response:abort(); it is not an output failure.
local ok, err, code = response:json({message="ready"}, true)
if not ok then
-- Output may be partial. Log the error and end the request.
trace("JSON response failed", err, code)
request:abort()
end
-- Success invalidates request and response; do not use their methods here.
To receive JSON from a client, see the JSON Echo LSP Example.
Checks the actual request connection. If it is already secure, returns false without changing the response. Otherwise, prepares a 301 redirect to the HTTPS version of the current URL. Call before committing the response.
An explicit port in the Host header selects a 403 error response instead. For example, example.com:8080 and [::1]:8080 select 403, while [::1] and [2001:db8::1] can redirect. The method does not infer a corresponding HTTPS port. Unbracketed IPv6 hosts also select 403.
Parameters
Return values
A returned failure does not invalidate the Lua object, but the native operation can already have changed the response or connection state. Handle the failure and end request processing.
Throws
Throws for an invalid or expired request/response object, or a non-boolean return2caller value when that option is read. Native failures, including a committed-response error reported by the native operation, return nil, error, code. Default successful termination uses the internal Lua unwinding mechanism described under abort().
See also dir:redirect2tls().
Clears response headers, buffered body data, or both before the response is committed. All modes preserve the HTTP status code.
Parameters
"all" when omitted or nil. "headers" clears headers and preserves the buffered body. "buffer" clears the buffered body and preserves headers. "all" clears both.Return values
Throws
Throws for an invalid or expired response object, an invalid mode, or an already-committed response. A rejected reset leaves the response unchanged.
Sends body data directly to the connection, bypassing the response writer and its filters. Set the total body length with response:setcontentlength() before sending. This method does not select chunked framing or check that the supplied data matches that length. Do not mix it with buffered output.
Parameters
Return values
A failed call may already have sent headers or part of the data. Stop sending after failure. For a HEAD request, the native method counts the data without sending body bytes.
Throws
Throws for an invalid or expired response object, or if the current response writer has buffered data. Native output failures return nil, error, code.
Builds a simple HTML error response using the specified HTTP status. Call before committing the response. The method prepares the status and error headers before formatting the body, so a message larger than the response buffer uses the correct status when output starts.
Replaces buffered body data and disables connection keep-alive. Sets Content-Type to text/html only if no Content-Type is already present, and sets Cache-Control to prevent caching. Other headers are retained. The method can send data while formatting; a short response can remain buffered until normal response completion. It does not end Lua execution or invalidate the request/response object.
Parameters
Return values
A failure can occur after the response has changed or some output has been sent. Handle the error and end request processing.
Throws
Throws for an invalid or expired request/response object, invalid argument types, or an already-committed response. A committed call is rejected before changing response data. Native header-storage and output failures return nil, error, nativeCode.
Prepares an HTTP redirect to the specified URL. Call before response headers have been sent. The method discards buffered body data, sets Location and Content-Length: 0, and sets status 302 or 301. Relative URLs are converted using encoderedirecturl(). Existing unrelated headers are retained. The method prepares the response; it does not itself flush it to the connection.
Parameters
Return values
A returned failure leaves the request/response object available, but the native method marks the connection terminated. It can already have changed the response. End request processing after handling the failure.
Throws
Throws for an invalid or expired object, invalid argument types, or an already-committed response. Allocation and header-storage failures return nil, error, code. Default successful termination uses the internal Lua unwinding mechanism described under abort().
Example:
response:sendredirect"../start.html";
-- Send a permanent redirect request
response:sendredirect("https://realtimelogic.com", true);
Prepares an HTTP Basic authentication challenge in WWW-Authenticate and sets status 401. Call before committing the response. Does not send the response or end execution. During inclusion, the call has no effect.
Parameters
Return values
No values on success, including an ignored call during inclusion. Failure returns the following three values:
If header storage fails, the method returns nil, error, code and leaves the status code and existing headers unchanged. Successful calls return no values, so check for the error string rather than treating a missing first result as failure.
Throws
Throws for an invalid or expired request/response object, an invalid realm type, or an already-committed response. Header-storage failures are returned.
Typically used in a response message handler with an auth type authenticator.
Prepares an HTTP Digest authentication challenge in WWW-Authenticate and sets status 401. Call before committing the response. Does not send the response or end execution. During inclusion, the call has no effect.
Parameters
Return values
No values on success, including an ignored call during inclusion. Failure returns the following three values:
If header storage fails, the method returns nil, error, code and leaves the status code and existing headers unchanged. Successful calls return no values, so check for the error string rather than treating a missing first result as failure.
Throws
Throws for an invalid or expired request/response object, an invalid realm type, or an already-committed response. Header-storage failures are returned.
Typically used in a response message handler with an auth type authenticator.
Sets Content-Length and disables automatic chunked transfer selection. Call before committing the response.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Throws for an invalid length type or an already-committed response. Native allocation failures return nil, error, code.
Sets the Content-Type response header, optionally preserving an existing value.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Setting an invalid value or changing an already-committed response throws. Preserving an existing header returns false without changing or validating its value.
Formats a Unix timestamp as an HTTP date and stores it in the response header database. Call before committing the response; this native helper does not reject calls after commitment, but cannot change headers already sent.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Invalid argument types throw. Native allocation failures return nil, error, code.
Installs the default HTML content type if none exists and sets Cache-Control to no-store, no-cache, must-revalidate, max-age=0. Does nothing in an included response.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object. Throws if headers are already committed outside an include. Native allocation failures return nil, error, code.
Sets or removes a response header before the response is committed. Setting a header replaces its previous value. Header names are matched without regard to case.
Parameters
Content-Length: A nonempty value uses a separate numeric conversion and calls response:setcontentlength() internally. Prefer response:setcontentlength() when setting a body length. Removing Content-Length preserves buffered body data, removes any Transfer-Encoding header, and immediately restores automatic framing. The default writer selects chunked transfer for a keep-alive response other than HEAD; otherwise it leaves chunking disabled. A custom response writer remains responsible for its output handling. Passing "0" sets an explicit zero length; it does not remove the header.
Return values
Throws
Throws for an invalid or expired response object, invalid argument types, or an already-committed response. A committed response is rejected before its headers or buffered body are changed. Storage failures are returned as nil, error, code, including failure to store Transfer-Encoding when restoring automatic framing; stop response processing if this fails.
Sets Cache-Control to max-age followed by the supplied duration. Does nothing in an included response.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Invalid argument types throw. Outside an include, an already-committed response throws; native allocation failure returns nil, error, code.
Installs a response writer that compresses buffered output or passes it to a Lua callback. Install it before writing body data. It applies to buffered output such as write(), _emit(), and print(). Direct send() output bypasses it.
Parameters
Return values
Successful installation clears existing response headers and preserves the status code. Keep the object until you finalize or abort it, and use it only while its underlying request is active. Set response headers after installation.
Throws
Throws for an invalid or expired request/response object, an already-committed response, or a zlib initialization error. Zlib initialization failure currently raises an exception even when its cause is allocation failure.
The callback runs in a Lua coroutine and receives one argument:
These methods belong to the object returned by setresponse(), not the request/response object. Use it only during its request. Once released, it cannot affect a subsequently installed writer.
Discards the filter or compression writer without flushing it, restores the default response writer, clears response headers, and releases the object's resources. The HTTP status is preserved. This method returns normally; it is different from response:abort().
Parameters
None.
Return values
Throws
Throws for an invalid filter-object argument. A committed response or repeated abort returns false.
Flushes buffered input through the installed filter or compressor, restores the default writer, and releases the object. Finalization consumes the object even when it returns nil. It does not invalidate the request/response object.
Parameters
Return values
Callback mode flushes pending data without the final nil notification used during automatic cleanup. Its success does not mean the callback sent an HTTP response. A failed output operation may already have sent some bytes; do not send a second body after failure.
Throws
Throws for an invalid filter-object argument. Lua allocation while assembling the compressed return string can also throw. Callback errors and yields are logged and become filter failures; native flush/output failures return nil.
Finalize or abort the object before leaving its request. A Lua <close> variable invokes cleanup at scope exit: compression attempts to send its output, while callback mode flushes pending bytes and then calls the callback with nil. During server-driven request termination, request/response methods may already be unavailable. Automatic cleanup cannot return a result to the caller; use explicit finalization when you need to check its result.
In addition to the examples below, see the Light Dashboard for a real-world example of how to use 'setresponse'. In the dashboard, compression is enabled in function cmsfunc(), which is found in cms.lua.
The following examples are intended to serve as .preload scripts that can be executed using the Mako Server or Xedge. To understand the examples provided below, it is recommended that you review the Command Environment and the functionality of the Resource Reader (resrdr).
-- The global 'dir' is the .preload's Resource Reader
local dir=dir -- convert to closure so it works in serviceFunc()
local function serviceFunc(_ENV,path)
local ae = request:header("Accept-Encoding")
-- If requesting an LSP file and the client accepts deflate compression
if path:find("%.lsp$") and ae and ae:find("deflate") then
trace"Using compression"
local xrsp <close> = response:setresponse() -- Activate compression
-- Calling finalize() below is for illustration purposes only;
-- we do not need to call it since we declared the object using
-- local xrsp <close> , meaning it finalizes automatically
-- when the object goes out of scope.
-- Run the resource manager's service function
local found = dir:service(request,path)
if found then
response:setcontenttype("text/html")
xrsp:finalize(true) -- Send compressed data to client
-- Above sets Content-Encoding and Content-Length before sending data
return true -- LSP page (resource) found
end
-- Not found, but we must clean up.
xrsp:finalize()
return false -- Resource not found
end
-- Service request without using compression
trace"Not using compression"
return dir:service(request,path)
end
dir:setfunc(serviceFunc) -- Install
In the example above, a directory function is created and installed within the Resource Reader, acting as a filter. This filter analyzes incoming requests and enables compression if the client supports deflate compression. Since compression cannot be applied to non-LSP resources, the function checks whether the request is for an LSP page by verifying if the requested resource ends with .lsp.
The call to xrsp:finalize(true) after the Resource Manager's service function renders the response, compiles all data, and sends it to the client. By default, the finalize method returns the data without sending it to the client. The following example demonstrates a modified service function that fetches compressed data and sends it to the client using response:write.
local dir=dir
local function serviceFunc(_ENV,path)
local ae = request:header("Accept-Encoding")
-- If requesting an LSP file and the client accepts deflate compression
if path:find("%.lsp$") and ae and ae:find("deflate") then
local xrsp = response:setresponse() -- Activate compression
-- Run the resource manager's service function
local found = dir:service(request,path)
if found then
local data=xrsp:finalize() -- Fetch compressed data
response:setcontenttype("text/html")
response:setcontentlength(#data)
response:setheader("Content-Encoding", "deflate")
response:write(data) -- Write is now the standard socket write
return true -- LSP page (resource) found
end
xrsp:finalize() -- Not found, but we must clean up
return false -- Resource not found
end
-- Service request without using compression
dir:service(request,path)
end
dir:setfunc(serviceFunc) -- Install
Fetching data by calling finalize() without sending it immediately (as opposed to using finalize(true)) is beneficial in applications that implement caching. This allows a service function to be designed in a way that it can handle the caching of dynamically generated LSP data.
As an example, a cache can be implemented by using a table.
local function serviceFunc(_ENV,path)
if pageCacheTable[path] then
sendCachedPage(pageCacheTable[path])
return true -- found
end
-- Not in cache
.
.
The most common use of HTTP filters is to compress response data, and the methods described above are optimized for this functionality. However, if you require filtering for purposes other than compression, a generic filter function can be installed. The following example demonstrates how to install a filter by calling response:setresponse(myRespFilter).
local dir=dir
local function serviceFunc(_ENV,path)
-- If requesting an LSP page
if path:find("%.lsp$") then
-- Create a table for storing response data and a function to collect
local dataTable={}
local function myRespFilter(data)
if data then
table.insert(dataTable, data)
else
trace"response:abort() or similar"
end
end
-- Activate response filter
local xrsp = response:setresponse(myRespFilter)
-- Run the resource manager's service function
local found = dir:service(request,path)
xrsp:finalize() -- Cleanup
if found then
local data
local ae = request:header("Accept-Encoding")
-- If client accepts deflate compression
if ae and ae:find("deflate") then
response:setheader("Content-Encoding", "deflate")
data = ba.deflate(dataTable) -- Compress and assemble response data
else
data = table.concat(dataTable) -- Assemble response data
end
response:setcontenttype("text/html")
response:setcontentlength(#data)
response:write(data) -- Write compressed or non compressed data
return true -- LSP page (resource) found
end
return false -- Resource not found
end
return dir:service(request,path)
end
dir:setfunc(serviceFunc) -- Install
In this example, the myRespFilter callback function is invoked when the internal web-server buffer reaches capacity. The frequency of these calls depends on the ratio of the LSP data size to the internal web-server buffer size. At a minimum, the callback is triggered once when finalize() is called. It is important to note that the buffer size can be configured through C/C++ code at startup.
Response data is collected into a table at line 8, which is then assembled into compressed data if the client supports compression, or left uncompressed if the client does not support it.
Beyond the examples provided, the HTTP filter can also be applied to resources that are either included or forwarded using response:include and response:forward. The filter operates with any resource that dynamically generates response data, such as CSP and CGI resources.
Sets the HTTP response status. Does nothing in an included response.
Parameters
Return values
Throws
Throws for an invalid or expired request/response object. Invalid argument types throw. Outside an include, an already-committed response throws.
Checks whether this Lua request/response handle still has its native command.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an object of the wrong type. An expired handle returns false.
Appends data to the current response writer. The default writer buffers data and sends it when space is needed or the response is flushed. It selects automatic framing unless an explicit content length has already been set. A custom response writer receives the data instead.
Parameters
Return values
A failed call may already have accepted or sent some data. Stop writing after failure.
Throws
Throws for an invalid or expired response object or if the required Lua stack space cannot be obtained. Native writer failures return nil, error, code.
example:
<?lsp
response:write"hello world"
-- create a convenience function for writing data
local fmt = string.format
local function prt(...) response:write(...) end
local function prtf(...) prt(fmt(...)) end
prt("<br>as ","many ", "strings as you like<br>")
prtf("You can format numbers %d", 1234)
?>
Gets the capacity of the current response writer buffer.
Parameters
None, apart from the response object.
Return values
Throws
Throws for an invalid or expired request/response object.
A deferred response is returned by methods such as upload:response() after the response is detached from its original request. It wraps the C HttpAsynchResp object and is normally used from a thread.
Set an optional status and any headers before starting the body. Then choose one body-writing mode:
Do not mix write() with setcontentlength()/send(). Starting either body mode commits the headers. Finish with close(). Check operation results before sending more data; a failed operation can already have changed the response state or sent part of the response.
Sets the response status before any status line is generated. If omitted, the underlying response uses 200 OK.
Parameters
Return values
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. Invalid status or protocol arguments throw when the status line has not yet been generated. A repeated status call returns nil, error before checking its arguments. Lua allocation can also throw.
Adds a response header before body transmission starts. Generates the default status line if none has been set.
Parameters
Return values
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. Invalid name or value arguments throw while headers can still be added. After headers have been sent, this returns nil, error before checking those arguments. Lua allocation can also throw.
Writes buffered body data in the unknown-length mode. The first call starts this mode even if no data is supplied.
Parameters
Return values
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. Invalid data arguments throw after the writer has been obtained, potentially after earlier arguments were written. Lua allocation can also throw. State and backend failures use the return values above.
Starts a fixed-length response and sends its headers immediately. Set other headers before this call.
Parameters
Return values
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. A length that cannot be converted to an integer throws. A valid argument in the wrong response state returns nil, error. Lua allocation can also throw.
Sends fixed-length body data. The binding does not track or enforce the sum of the bytes sent; the caller must send exactly the declared total length.
Parameters
Return values
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. Invalid data throws. On the first send(), a missing or non-integer length, or a converted length smaller than the first data string, throws. Wrong body mode returns nil, error. Lua allocation can also throw.
Closes the response, flushing buffered output. The object is then expired; closing it again throws. This method provides no status for a flush or connection failure.
Parameters
Return values
None.
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. A supplied closeconnection value other than boolean or nil throws.
Alias for close(), with the same flushing, argument, return, and error behavior.
Parameters
Return values
None.
Throws
Throws for an invalid deferred-response object or an object already closed through this binding. A supplied closeconnection value other than boolean or nil throws.
Checks whether the underlying deferred response is still valid. It can become invalid after a connection failure even before close() is called.
Parameters
None.
Return values
Throws
Throws for an invalid object type. A closed deferred-response object returns false.
-- Send a known-size body using an existing deferred response.
local body="Completed"
assert(defresp:setheader("Content-Type", "text/plain"))
assert(defresp:setcontentlength(#body))
assert(defresp:send(body))
defresp:close()
A cookie is used for exchanging a small amount of information between a page and a web browser.
A cookie's value can uniquely identify a client, so cookies are commonly used for session management.
A cookie has a name, a single value, and optional attributes such as a comment, path and domain qualifiers, a maximum age, and a version number.
Typical usage:
cookie = request:cookie"myCookie"
print("Cookie:",cookie and "yes" or "no")
if not cookie then -- If no cookie set for this page
print"Creating session cookie"
cookie = response:createcookie"myCookie"
cookie:value"Hello World" -- Set
-- Active cookie i.e. send cookie to client
cookie:activate()
end
-- This should never fail
assert("Hello World" == request:cookie"myCookie":value())
Marks the cookie for inclusion in the response. Call before response headers are committed; activation does not itself send the response. The binding does not check whether headers have already been committed.
Parameters
None.
Return values
None.
Throws
Throws for an invalid cookie object or an expired owning request.
Marks the cookie for expiration in the browser. Set the same path and domain used when creating it, and activate it before response headers are committed. This method does not destroy the Lua cookie object.
Parameters
None.
Return values
None.
Throws
Throws for an invalid cookie object or an expired owning request.
Reads or replaces the cookie comment.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request. A supplied value that cannot be converted to a string throws. Lua allocation can throw while returning a string. Native allocation failures are returned as nil, error, code.
Reads or replaces the cookie domain.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request. A supplied value that cannot be converted to a string throws. Lua allocation can throw while returning a string. Native allocation failures are returned as nil, error, code.
Reads or sets cookie lifetime. A newly created cookie has lifetime 0 without a deletion flag, so no expiration date is sent. Explicitly setting 0 marks the cookie for deletion.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request. A supplied time that cannot be converted to an integer throws.
Reads the cookie name.
Parameters
None.
Return values
Throws
Throws for an invalid cookie object or an expired owning request. Lua allocation can throw while returning the name.
Reads or replaces the cookie path.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request. A supplied value that cannot be converted to a string throws. Lua allocation can throw while returning a string. Native allocation failures are returned as nil, error, code.
Reads or changes the Secure flag, requesting transport over a secure connection.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request.
Reads or changes the HttpOnly flag, requesting that browser scripts cannot access the cookie.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request.
Reads or replaces the cookie value.
Parameters
Return values
Throws
Throws for an invalid cookie object or an expired owning request. A supplied value that cannot be converted to a string throws. Lua allocation can throw while returning a string. Native allocation failures are returned as nil, error, code.
HTTP is a stateless protocol, however, many web applications require persistent state information stored at the server side. The session object provides a way to identify a HTTP client across requests.
Modern web applications may use a combination of stateless requests such as HTTP/REST and persistent connections using WebSockets. The session object provides methods that enable seamless state information integration between HTTP/REST and WebSockets. The session logic is also integrated with the authentication logic and enables a modern Single Page Application to initially authenticate and create a session object using HTTP, when the application initially loads. The session/authentication information is then made available when the client initiates the WebSocket connection. The session is also available for server side SMQ code that may require identification of a user that was authenticated using HTTP.
The session management is handled by the server and is in C code available via the HttpSession class. The Lua interface enables HttpSession interaction as depicted in the following figure:
ref1 = request:session()
+----+
|ref1+-----+ +---------+ +-------------+
+----+ +---> Session | | HttpSession |
| +-------->+ |
+----+ +---> table | | (C object) |
|ref2+-----+ +---------+ +-------------+
+----+
ref2 = ba.session()
The Lua session table references the HttpSession C object as shown in the figure above and provides Lua bindings for the HttpSession C methods. The session table allows you to:
The session table is accessed via session table reference object(s) (depicted as ref1 and ref2 in the figure above). All session methods, except session:lock() and session:release(), operate indirectly on the session table via a session reference object. A session reference object is for example created by calling method request:session(true).
Note:
session = request:session() -- returns nil/false if there is no session
if session then
print("we have a session ", session)
session:maxinactiveinterval(60);
print("id", session:id());
print("creationtime" ,os.date("%c",session:creationtime()))
print("lastaccessedtime" ,os.date("%c",session:lastaccessedtime()))
print("maxinactiveinterval" ,session:maxinactiveinterval())
print("usecounter" ,session:usecounter())
session.attr1="val1"
session.attr2="val2"
-- print 'attr1=val1' and 'attr2=val2'
for k,v in pairs(session:attributes()) do
print(string.format("%s=%s",k,v))
end
else
print"No session: run example below first"
end
-- Using session variables
local session = request:session()
if not session then -- no session ?
print"you must first login using a valid username and password"
request:login"my-username" -- simulate login and create session
else
-- no basket? - create it
session.basket = session.basket or {}
-- add an item to the basket table
session.basket[#session.basket +1] = "something new"
print("We have ", #session.basket, " items in the shopping basket")
end
You may set your own attributes on the session and persistently store the attributes for the lifetime of the session.
local session=request:session(true)
session.myattr1=val1
session["myattr2"]=val2
Returns the actual session attribute table, not a copy. It is created when an attribute is first assigned.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
The following example creates attributes before iterating over their table.
local session=request:session(true)
session.key1="val1" -- Indirect session table access
session["key2"]="val2"
for key,value in pairs(session:attributes()) do
print(string.format("%s=%s",key,value))
end
Returns the session identifier.
Parameters
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Returns when the session was created.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Reads the last-access time and optionally refreshes it.
Parameters
Return values
Throws
Throws for an invalid session reference. Looking up this method on an expired session throws; a previously cached method function returns -1 instead.
Reads the inactivity timeout and optionally replaces it.
Parameters
Return values
Throws
Throws for an invalid or expired session reference or a supplied interval that cannot be converted to an integer.
Returns the client IP address associated with the session.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Reads the session usage counter.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Requests session termination regardless of its lock count. Destruction and attribute cleanup can be deferred while C-side references remain.
Parameters
None.
Return values
Throws
Throws for an invalid session reference. Looking up this method on an expired session throws; a previously cached method function returns false instead. Errors in onterminate are logged by its callback handler.
Returns the user associated with this session.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Optional callback installed by assigning a function to session.onterminate. Called with no arguments when the underlying session is destroyed. Non-function values are ignored.
Parameters
None.
Return values
None. Return values are ignored.
Throws
Callback errors are logged and do not propagate to the caller that triggered destruction. The callback must finish without yielding; a yielded callback is reported as a failure and is not resumed.
The server calls onterminate when the server destroys the session object and if this attribute is set to a function.
local s=request:session(true)
function s.onterminate()
ba.thread.run(function()
trace"Do the work here!"
end)
end
Prevents inactivity timeout while this session reference holds a lock. Repeated calls on the same reference do not add locks.
Parameters
None.
Return values
Throws
Throws for an invalid or expired session reference. Lua allocation can also throw.
Lock a session and prevent the session timer from terminating the session when the session:maxinactiveinterval() expires. Locking a session is useful when designing certain web applications using persistent connections such as WebSockets and SMQ. persistent WebSocket and SMQ connections do not terminate when the session expires and locking the session makes it easier for certain types of applications to maintain a consistent state.
As an alternative, you may invert the application's logic by installing a session.onterminate callback that terminates any persistent WebSocket or SMQ connection when the server's session object expires.
Note: a session will be terminated when session:terminate() is called, regardless of lock state.
Method request:session() returns a session reference object that lets you interact with the session, but the object itself is not the session. A new object is returned for each request:session() call, thus the following construction creates three locks:
local s1=request:session(true) s1:lock() local s2=request:session() s2:lock() local s3=request:session() s3:lock()
Releases the lock held by this particular session reference. Garbage collection of the reference also releases its lock.
Parameters
None.
Return values
Throws
Throws for an invalid session reference. Looking up this method on an expired session throws; a previously cached method function returns false instead.
Looks up a stored credential in a JSON-backed or Lua-backed user database. This method does not check a submitted password, authenticate the client, or create a login session.
Parameters
Return values
A successful lookup always returns all four values. Lua callbacks use the credential and optional-value rules described under ba.create.authuser().
Throws
Throws for an invalid user-database object, invalid username argument, or an invalid or expired request object. Errors raised by a Lua user-database callback propagate to this caller, including when request is supplied; use pcall() if the application needs to handle them. Lua allocation can also throw. Missing or unusable credentials return nil.
For a Lua-backed database, the callback runs synchronously on the calling Lua state. With request, it receives (username, nil, commandEnvironment). Without request, it receives (username, nil, nil); the binding does not infer a request from the calling page. The client-password argument is always nil because this is a credential lookup. A callback that supports standalone lookups must handle a nil command environment. Normal authentication continues to supply its request environment and use its request error handler.
-- This credential lookup works with and without a request environment.
local users=ba.create.authuser(function(username, upasswd, _ENV)
if username == "alice" then
return "example-password", 3, false, 0
end
end)
local password, maxusers, recycle, inactive=users:getpwd("alice")
-- Inside an LSP page or directory callback, supply its request when needed.
local password, maxusers, recycle, inactive=users:getpwd("alice", request)
Authenticates the client. A failed attempt may send a login response.
Parameters
Return values
Throws
Throws for an invalid authenticator, invalid or expired request object, or invalid path argument. Lua allocation can also throw. Rejected credentials return nil; errors in Lua authentication callbacks are handled by the request error handler.
local function myDirectoryService(_ENV,relpath)
if authenticator:authenticate(request, relpath) then
response:write"You are authenticated"
else
-- The response was sent by the
-- authenticator's Response Message Handler
end
return true -- True means resource found and response is committed
end
Checks access for the user associated with a request or upload.
Parameters
Return values
Throws
Throws for an invalid authorizer or request/upload-node object. With an authenticated user, invalid method or path arguments throw; without one, the binding returns false before checking those arguments. Lua allocation can also throw. Errors in a Lua authorization callback are caught and deny access.
Replaces the authorization constraints. Pass the database directly, with one record per string constraint name. Names are labels and do not affect authorization; v has no special meaning.
Parameters
Return values
Throws
Throws for an invalid JSON authorizer object or a constraintdb argument that is neither a table nor convertible to a string. Lua allocation or errors from table conversion can also throw. JSON syntax and constraint-schema errors normally return nil, error.
JSON parsing failures leave the old constraints intact. After parsing, the old constraints are removed before the new records are validated; a later error can leave an empty or partially populated replacement. Always check the result. Duplicate exact paths keep the first installed constraint for that path.
-- Allow the reader role to read resources under this directory.
local az=ju:authorizer()
assert(az:set{read={urls={'/*'},methods={'GET'},roles={'reader'}}})
Reads or changes case sensitivity for directory-prefix constraints. Newly created authorizers are case sensitive. Exact-path constraints always use case-sensitive matching in the current implementation, even when this flag is false.
Parameters
Return values
Throws
Throws for an invalid JSON authorizer or a supplied enabled value other than boolean or nil.
The HTTP directory object is returned by a number of functions such as the ba.create.xxx functions.
The Lua directory object is a wrapper for the HttpDir "C" class or any class that inherits from HttpDir such as HttpResRdr.
Returns the directory's absolute virtual-file-system path with a trailing slash.
Parameters
None.
Return values
Throws
Throws for an invalid directory object. Lua allocation can also throw.
Inserts this directory as a root in the virtual file system. Keep a Lua reference while installed.
Parameters
None.
Return values
Throws
Throws for an invalid or already-linked directory. Lua allocation can also throw.
Inserts an unlinked child directory. See constructing a virtual file system tree.
Parameters
Return values
Throws
Throws for invalid objects, an already-linked child, insertion into itself, or an invalid reference argument. Reference validation follows insertion, so an invalid reference argument can leave the child inserted. Lua allocation can also throw.
Returns the directory name.
Parameters
None.
Return values
Throws
Throws for an invalid directory object. Lua allocation can also throw.
Sets the page used when the directory's authorizer denies access.
Parameters
Return values
None.
Throws
Throws for an invalid directory or path argument. The underlying C string-copy allocation failure is not reported by this binding.
Replaces the authentication and authorization objects. Calling without arguments, or with nil, removes both.
Parameters
Return values
Throws
Throws for invalid directory, authenticator, or authorizer objects. Lua allocation can also throw.
Enables authentication and optionally authorization for this directory. The authenticator is created by ba.create.authenticator() and the authorizer is created by ba.create.authorizer() or jauthenticator:authorizer(). Returns true on success.Note: when setting an authenticator for a Resource Reader, the authenticator logic enables bypassing of authentication for any resource stored in the "public" directory, if such a directory exists. This construction makes it possible to load resources used by a form-based HTML authenticator page.
Installs automatic redirection of non-TLS requests to HTTPS.
Parameters
None.
Return values
Throws
Throws for an invalid directory, or if a Lua service callback or TLS redirect is already installed. Use a service callback that performs the redirect itself when custom handling is needed.
local function myservice(_ENV,relpath)
-- Automatically returns if client needs to be redirected
response:redirect2tls()
-- We get here if secure
end
dir:setfunc(myservice)
Calls this directory's service function. From its own Lua service callback, calls the original service function instead.
Parameters
Return values
Throws
Throws for invalid directory/request objects, an expired request, invalid relpath, or a sim-forward argument other than boolean or nil. Errors in a Lua directory callback are managed by the request error handler.
Installs or removes a Lua directory service callback.
Parameters
Return values
Throws
Throws for an invalid directory or a supplied value other than function or nil. Lua allocation can also throw.
Sets the directory service function.A directory function is the directory's service callback function which is activated by the server's virtual file system when searching for resources. All directory types have a default service function implemented in C code. The Lua code can install a new directory function that either replaces the original service function or extends the functionality of the original service function. The original "C" service function can be called from within the Lua service function by calling dir:service().
The directory function must be declared as follows:
local function myservice(_ENV,relpath)
The _ENV variable is the command environment. The relpath variable is constructed from the URL and is the relative URL path component for the directory branch.
The directory function must return true if the resource was found and a response was sent to the client. The function must return false if the resource was not found and no response was sent to the client. The virtual file system will continue its search for a suitable resource if the directory function returns false. A no return value is interpreted as returning true.
See ba.create.dir for example code.
Directory service callback installed by dir:setfunc().
Parameters
Return values
Throws
Callback errors are caught and reported by the request error handler, and directory searching stops.
Unlinks this directory from its parent or server and releases the parent's optional reference to it.
Parameters
None.
Return values
Throws
Throws for an invalid directory object. Lua allocation can also throw.
All of the standard Lua libraries are implemented with the two exceptions that the io library is only supported when the target platform supports ANSI I/O (MAC, Windows, POSIX) and the os library functions are implemented when it is appropriate on the target platform. os.exit() is not implemented on any Barracuda platform.
Platform independence is achieved by using the ba library.
When called from the command environment, print() sends response data to the client. Otherwise, print() behaves like the standard Lua print() function. To call the standard console-printing function from the command environment, use the global scope variable, e.g., _G.print().
print() differs from response:write() in that it calls Lua tostring() on each parameter passed to it. print() is useful for diagnostics and small amounts of output, but response:write() is usually preferred for response content.
Note: the global _G.print() function (console output) may not be available on some embedded systems. Use trace() as a replacement.
Parameters
Return values
Throws
Throws if the global tostring function fails or returns a value that cannot be converted to a string. Errors from a value's __tostring metamethod propagate. Lua allocation failure can also throw. Command-environment print also throws when the request/response has expired. Native response write failures return nil, error, code; earlier output is not rolled back.
Example:
<?lsp
print("hello", "world")
?>
This example would emit "hello\tworld\n".
Writes values to the server trace log at priority 0, with function and line information.
Parameters
Return values
Throws
Throws if the global tostring function fails or returns a value that cannot be converted to a string. Errors from a value's __tostring metamethod propagate. Lua allocation failure can also throw.
Writes values to the server trace log at the selected priority.
Parameters
Return values
Throws
Throws if the global tostring function fails or returns a value that cannot be converted to a string. Errors from a value's __tostring metamethod propagate. Lua allocation failure can also throw. Also throws for a missing priority or a non-string priority that cannot be converted to an integer.
Recommended priority names are emergency (0), alert (1), critical (2), error (3), warning (4), notice (5), informational (6), and debug (7). The implementation examines only the first character, ignoring its case. For e/E, a lowercase m as the second character selects 0; otherwise it selects 3. Unrecognized strings, including an empty string, select 7. Names are not validated as complete words.
Both trace functions require the trace library to be initialized by the C startup code. See TraceLogger and Logging for Testing and Production Mode for configuration.
Writes a string to the current response. Available in the command environment. The LSP parser generates calls to this function for literal page content and expression output.
Parameters
Return values
Throws
Throws for a missing argument, an argument other than a string or number, or an expired request/response. Lua allocation failure can also throw. Native write failures return nil, error, code. Generated LSP calls do not inspect these return values.
A standalone executable Lua interpreter is delivered with the Barracuda Server's SDK. The executable, called xlua, is found in the SDK's bin directory.
The executable xlua is an extended version of the standard standalone executable Lua interpreter and includes many BAS APIs in addition to the original Lua APIs.
The standalone interpreter makes it easy to create standalone applications for sending (secure) E-mail, using the HTTP(S) client libraries, and creating (secure) client and server socket applications in Lua.
Note that the Mako Server can also execute a script and exit. See the Mako script option for details.
The extended executable includes:
"/") and NetIo is uninitialized. DiskIo is returned when calling ba.openio"disk", and NetIo is returned when calling ba.openio"net". A new NetIo instance is typically created (cloned) and initialized by calling ba.mkio().require"socket/mail" loads the SMTP libraries from the embedded ZIP file. You can also open the ZIP I/O directly by calling ba.openio"vm".