2018-01-31 11:39:04 +00:00
|
|
|
local http = require("socket.http")
|
|
|
|
local logger = require("logger")
|
|
|
|
local ltn12 = require("ltn12")
|
2021-03-15 00:25:10 +00:00
|
|
|
local socket = require("socket")
|
|
|
|
local socketutil = require("socketutil")
|
2018-01-31 11:39:04 +00:00
|
|
|
|
|
|
|
local InternalDownloadBackend = {}
|
2022-09-16 22:08:00 +00:00
|
|
|
local max_redirects = 5 --prevent infinite redirects
|
2018-01-31 11:39:04 +00:00
|
|
|
|
2018-01-31 22:37:19 +00:00
|
|
|
function InternalDownloadBackend:getResponseAsString(url, redirectCount)
|
|
|
|
if not redirectCount then
|
|
|
|
redirectCount = 0
|
|
|
|
elseif redirectCount == max_redirects then
|
2022-09-16 22:08:00 +00:00
|
|
|
error("InternalDownloadBackend: reached max redirects:", redirectCount)
|
2018-01-31 22:37:19 +00:00
|
|
|
end
|
2022-09-16 22:08:00 +00:00
|
|
|
logger.dbg("InternalDownloadBackend: url:", url)
|
2021-03-15 00:25:10 +00:00
|
|
|
local sink = {}
|
|
|
|
socketutil:set_timeout(socketutil.LARGE_BLOCK_TIMEOUT, socketutil.LARGE_TOTAL_TIMEOUT)
|
|
|
|
local request = {
|
|
|
|
url = url,
|
|
|
|
sink = ltn12.sink.table(sink),
|
|
|
|
}
|
|
|
|
local code, headers, status = socket.skip(1, http.request(request))
|
|
|
|
socketutil:reset_timeout()
|
2018-01-31 22:37:19 +00:00
|
|
|
|
|
|
|
if code ~= 200 then
|
2022-09-16 22:08:00 +00:00
|
|
|
logger.dbg("InternalDownloadBackend: HTTP response code <> 200. Response status:", status or code)
|
|
|
|
if code and code > 299 and code < 400 and headers and headers.location then -- handle 301, 302...
|
|
|
|
local redirected_url = headers.location
|
|
|
|
logger.dbg("InternalDownloadBackend: Redirecting to url:", redirected_url)
|
|
|
|
return self:getResponseAsString(redirected_url, redirectCount + 1)
|
2018-01-31 22:37:19 +00:00
|
|
|
else
|
2022-09-16 22:08:00 +00:00
|
|
|
logger.dbg("InternalDownloadBackend: Unhandled response status:", status or code)
|
|
|
|
logger.dbg("InternalDownloadBackend: Response headers:", headers)
|
|
|
|
error("InternalDownloadBackend: Don't know how to handle HTTP response status:", status or code)
|
2018-01-31 22:37:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
return table.concat(sink)
|
2018-01-31 11:39:04 +00:00
|
|
|
end
|
|
|
|
|
2018-01-31 22:37:19 +00:00
|
|
|
function InternalDownloadBackend:download(url, path)
|
2022-09-16 22:08:00 +00:00
|
|
|
local response = self:getResponseAsString(url)
|
|
|
|
local file = io.open(path, 'w')
|
|
|
|
if file then
|
|
|
|
file:write(response)
|
|
|
|
file:close()
|
|
|
|
end
|
2018-01-31 11:39:04 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return InternalDownloadBackend
|