The module handlers are refactored to make them similar to the HTTP
ones. This change is not backward compatible with the existing njs code.
To allow asynchronous operations the model of evaluation of njs handlers
is changed. A handler function (which is set for a corresponding nginx
directive) is invoked only once. It can register a callback if more data
is necessary, by calling s.on(<event_name>, <callback>). Available
events:
upload - new data from a client.
download - new data from an upstream.
Callback prototype:
callback(data, flags).
data - string.
flags - object.
Available properties:
last - boolean, data is a last buffer.
A callback can be deregistered by s.off(<event_name>).
Return codes are replaced with special methods: s.allow(), s.deny(),
s.done().
s.done([code]) (s.OK), can be used to return arbitrary code.
s.allow() (s.OK)
s.deny() (s.ABORT)
In addition, s.decline() method is added to allow handlers to stop
processing of the current handler and pass control to the next
handler of the current phase.
A handler is expected to invoke one of these methods when the
processing is done.
For example js_preread can wait for additional data by registering
a callback which will be called whenever new incoming data appears.
function js_preread(s) {
s.on('upload', function(data, flags) {
// process data
// to proceed to the next phase
s.done()
// to proceed to next handler
// of the current phase
s.decline()
})
}
js_filter handler is refactored.
1) The current data chunk is moved from s.buffer to
the callback argument.
2) s.fromUpstream is removed.
3) The properties related to the current data chunk
(s.eof) are put into the second callback argument.
s.eof is renamed to flags.last.
3) s.send(data[, opts]) is added to replace s.buffer = data;
opts - object, can be used to override nginx buffer flags
derived from an incoming data chunk buffer.
It can contain boolean flags: last, flush.
4) data toward corresponding direction is not forwarded
if a callback is active, a callback is expected to
call s.send(data, flags) if it wants to pass data
as is.
5) s.send() can be called multiple times per callback invocation.
function stream_filter(s) {
s.on('upload', function (data, flags) {
// process a data chunk from a client
// stop filtering data
s.off('upload')
})
s.on('download', function (data, flags) {
// process data from upstream
// send my_data as the last buffer.
s.send(my_data, {last:1});
})
}