LuaSocket
Network support for the Lua language

home · download · introduction · reference


Callbacks

HTTP, FTP, and SMTP transfers sometimes involve large amounts of information. Sometimes an application needs to generate outgoing data in real time, or needs to process incoming information as it is being received. To address these problems, LuaSocket allows HTTP and SMTP message bodies and FTP file contents to be streamed through the callback mechanism outlined below.

Instead of returning the received contents as a big to the Lua application, the library allows the user to provide a receive callback that will be called with successive chunks of data, as the data becomes available. Conversely, the send callback mechanism can be used when the application wants to incrementally provide LuaSocket with the data to be sent.

receive_cb(chunk, err)

A receive callback will be repeatedly called by LuaSocket whenever new data is available. Each time it is called, the callback receives successive chunks of downloaded data.

Chunk contains the latest downloaded chunk of data. When the transmission is over, the function is called with an empty string (i.e. "") in chunk. If an error occurs, the function receives a nil chunk and an error message in err.

The callback can abort transmission by returning nil as its first return value, and an optional error message as the second return value. To continue receiving data, the function should return non-nil as its first return value. Optionally, in this case, it may return a second return value, with a new callback function to take its place.

send_cb()

A send callback will be called whenever LuaSocket needs more data to be sent.

Each time the callback is called, it should return the next chunk of data. It can optionally return, as it's second return value, a new callback to replace itself. The callback can abort the process at any time by returning nil followed by an optional error message.

Predefined Callbacks

The Callback module provides several predefined callbacks to perform the most common input/output operations. Callbacks are provided that send and receive contents of files and strings. Furthermore, composition functions are provided to chain callbacks with filters, such as the filters defined in the MIME module. Together, these two modules provide a powerful interface to send and receive information.

socket.callback.done()

This function creates and returns a callback that successfully terminates the transmission.

socket.callback.fail(message)

This function creates and returns a callback that aborts the transmission with a given error message.

socket.callback.receive.concat(cat)

This function creates a receive callback that stores whatever it receives into a concat object. When done, the application can get the contents received as a single string, directly from the concat object.

Cat is the target concat object, or nil. If cat is nil, the function creates its own concat object.

The function returns a receive callback for the file, and the concat object that will be used to store the received contents.

socket.callback.receive.file(file, io_err)

This function creates a receive callback that stores whatever it receives into a file. When done, the callback closes the file.

File is a file handle opened for writing. If file is nil, io_err can contain an error message. In this case, the function returns a callback that just aborts transmission with the error message.

The function returns a receive callback for the file.

Note: This function is designed so that it directly accepts the return values of Lua's IO io.open library function.

socket.callback.receive.chain(filter, receive_cb)

This function creates a receive callback that passes all received data through a filter, before handing it to a given receive callback.

Cat is the target concat object, or nil. If cat is nil, the function creates its own concat object.

The function returns a receive callback for the file, and the concat object that will be used to store the received contents.

Note: Several filters are defined in the MIME module. Below is an example that creates a receive callback that creates a string from the received contents, after decoding the Quoted-Printable transfer content encoding.

string_cb, concat = socket.callback.receive.concat()
receive_cb = socket.callback.receive.chain(
   socket.mime.decode("quoted-printable"),
   string_cb
)

The call to callback.chain creates a chained receive callback that decodes data using the mime.decode Quoted-Printable MIME filter and hands the decoded data to a concat receive callback. The concatenated decoded data can be retrieved later from the associated concat object.

socket.callback.send.file(file, io_err)

This function creates a send callback that returns the contents of a file, chunk by chunk, until the file has been entirely sent. When done, the callback closes the file.

File is a file handle opened for reading. If file is nil, io_err can contain an error message. In this case, the function returns a callback that just aborts transmission with the error message.

The function returns a send callback for the file.

Note: This function is designed so that it directly accepts the return values of Lua's IO io.open library function.

socket.callback.send.string(str, err)

This function creates a send callback that will send the contents of a string.

Str is the string to be sent.

It returns a send callback for the string, or nil if str is nil.

socket.callback.send.chain(send_cb, filter)

This function creates a send callback that will filter all the data it receives from another send callback, before sending it through.

Send_cb is the send callback to be chained to filter.

Returns a callback chained with the filter.

Note: Several filters are defined in the MIME module. Below is an example that creates a send callback that sends a file's contents encoded in the Base64 transfer content encoding.

send_cb = socket.callback.send.chain(
   socket.callback.send.file(io.open("input.bin"))
   socket.mime.chain(
       socket.mime.encode("base64"),
       socket.mime.wrap("base64")
   )
)

The call to mime.chain creates a chained filter that encodes it's input and then breaks it into lines. The call to callback.chain creates a chained send callback that reads the file from disk and passes it through the filter before sending it.