Description
One of the limitation in lua-https
is that it's not possible for application to create download progress bars on it (if the Content-Length
header is available). This is because https.request
will wait until all the response data is retrieved.
My proposal is to add optional 3rd and 4th parameter callback
and context
. Callback is defined as these fields:
local callback = {
-- `context` in here means user-supplied data (4th-parameter), which can be anything.
response = function(context, status, headers)
-- Called when HTTP status code and headers has been retrieved. Called once.
-- `status` is HTTP status code
-- `headers` is HTTP headers in **all lowercase** for the keys.
end,
body = function(context, data)
-- Called when new HTTP body data arrives. Called multiple times as new data arrives.
-- `data` is response data as Lua string.
-- Return "falsy" value and additional error message (default is "aborted") to abort the request
return true -- success
return false, "aborted" -- failure
end,
complete = function(context, err)
-- Called when data has been transferred, or an error occurs.
-- `err` will be the error message, or `nil` if everything worked as intended.
end,
}
Example usage:
local data = {current = 0, length = 0}
https.request("https://love2d.org", {}, {
-- `context` in here means user-supplied data (4th-parameter), which can be anything.
response = function(context, status, headers)
print("HTTP status code", status)
if headers["content-length"] then
context.length = tonumber(headers["content-length"]) or 0
end
end,
body = function(context, data)
context.current = context.current + #data
if context.length > 0 then
print(string.format("Received data %d bytes (%.2f)", #data, context.current * 100 / context.length))
else
print(string.format("Received data %d bytes", #data))
end
end,
complete = function(context, err)
if err then
print("Download error", err)
else
print("Download completed!")
end
end,
}, data)
As an additional feature/requirement, the callback
table can be a class object (not instance) by retrieving the function list using Lua C function that invokes metamethod and the context
can be the class instance itself such that when a class is declared like this:
local MyDownloader = class "MyDownloader"
function MyDownloader:response(status, headers)
end
function MyDownloader:body(data)
return true
end
function MyDownloader:complete(err)
end
Doing something like this simply works and calls the appropriate functions.
local dlinstance = MyDownloader() -- new class instance
https.request("https://love2d.org", {}, MyDownloader, dlinstance)
The return value of https.request
when using this variant would be questionable.
- Returning the status code, body, and the headers will preserve backward compatibility, but at same time make things redundant (the library has to keep everything until the function returns instead of discarding them).
- Returning only
true
orfalse
+ error message (assert
-compatible style) means less redundancy, but breaks backward compatibility.
I probably can do this, but the question becomes "should this is be done?" and/or "is this valid usecase to justify the feature addition?".