Channel.data(channel[, offset[, length]])
This function returns length bytes of incoming data from the channel buffer, starting at the
offset offset. The data are not removed from the buffer.
By default, if no length is provided, all incoming data found, starting at the given offset, are
returned. If length is set to -1, the function tries to retrieve a maximum of data and, if
called by an action, it yields if necessary. It also waits for more data if the requested
length exceeds the available amount of incoming data. Not providing an offset is the same as
setting it to 0. A positive offset is relative to the beginning of incoming data of the channel
buffer while negative offset is relative to the end.
If there is no incoming data and the channel can’t receive more data, a ‘nil’ value is
returned.
Arguments channel (class_channel) – The manipulated Channel.
offset (integer) – optional The offset in incoming data to start to get data. 0 by
default. May be negative to be relative to the end of incoming data.
length (integer) – optional The expected length of data to retrieve. All incoming data
by default. May be set to -1 to get a maximum of data.
Returns a string containing the data found or nil.
Specifically in my Lua code the calls like txn.req:data() or txn.req:data(0,10) (with required length specified) frequently return empty string rather than nil or some data.
According to the description it should never return empty string, specifically it should wait for data if the length specified. Or I misunderstood?
How to wait for some data in buffer explicitly? core.yield() in loop does not look right.
Ok, I’ve finally found the code of the responsible function:
But regardless of the function’s comments and brief code review the lua function still sometimes returns empty string rather than nil or some data.
So, looks like the code error…
UPD:
Seems so, I’ve found related (latest) commit for that function:
commit 0ae2e63d85d1da9c20b2a8b511cd8ced8558e769
Author: Christopher Faulet <cfaulet@haproxy.com>
Date: Tue Jan 10 15:29:54 2023 +0100
BUG/MINOR: hlua: Fix Channel.line and Channel.data behavior regarding the doc
These both functions are buggy and don't respect the documentation. They
must wait for more data, if possible.
For Channel.data(), it must happen if not enough data was received orf if no
length was specified and no data was received. The first case is properly
handled but not the second one. An empty string is return instead. In
addition, if there is no data and the channel can't receive more data, 'nil'
value must be returned.
In the same spirit, for Channel.line(), we must try to wait for more data
when no line is found if not enough data was received or if no length was
specified. Here again, only the first case is properly handled. And for this
function too, 'nil' value must be returned if there is no data and the
channel can't receive more data.
This patch is related to the issue #1993. It must be backported as far as
2.5.
And the fix was backported to haproxy version I use. Seems the issue was not fully fixed if it appears for both with and without length passed.
Noticed that it happens (empty string returned) mostly (always?) when the channel got closed (if explicitly checked by txn.req:may_recv()).