local date = require "luci.http.protocol.date"
local type, pairs, ipairs, tonumber = type, pairs, ipairs, tonumber
+local unpack = unpack
module "luci.httpclient"
options.depth = options.depth or 10
local headers = options.headers or {}
local protocol = options.protocol or "HTTP/1.1"
- local method = options.method or "GET"
headers["User-Agent"] = headers["User-Agent"] or "LuCI httpclient 0.1"
if headers.Connection == nil then
headers["Content-Length"] = headers["Content-Length"] or #options.body
headers["Content-Type"] = headers["Content-Type"] or
"application/x-www-form-urlencoded"
+ options.method = options.method or "POST"
end
+ if type(options.body) == "function" then
+ options.method = options.method or "POST"
+ end
+
-- Assemble message
- local message = {method .. " " .. path .. " " .. protocol}
+ local message = {(options.method or "GET") .. " " .. path .. " " .. protocol}
for k, v in pairs(headers) do
- if type(v) == "string" then
+ if type(v) == "string" or type(v) == "number" then
message[#message+1] = k .. ": " .. v
elseif type(v) == "table" then
for i, j in ipairs(v) do
if type(options.body) == "string" then
sock:sendall(options.body)
+ elseif type(options.body) == "function" then
+ local res = {options.body(sock)}
+ if not res[1] then
+ sock:close()
+ return unpack(res)
+ end
end
-- Create source and fetch response
local line, code, error = linesrc()
if not line then
+ sock:close()
return nil, code, error
end
- local protocol, status, msg = line:match("^(HTTP/[0-9.]+) ([0-9]+) (.*)")
+ local protocol, status, msg = line:match("^([%w./]+) ([0-9]+) (.*)")
if not protocol then
+ sock:close()
return nil, -3, "invalid response magic: " .. line
end
- local response = {status = line, headers = {}, code = 0, cookies = {}}
+ local response = {
+ status = line, headers = {}, code = 0, cookies = {}, uri = uri
+ }
line = linesrc()
while line and line ~= "" do
end
if not line then
+ sock:close()
return nil, -4, "protocol error"
end
if response.code and options.depth > 0 then
if response.code == 301 or response.code == 302 or response.code == 307
and response.headers.Location then
- local nexturi = response.headers.Location
- if not nexturi:find("https?://") then
- nexturi = pr .. "://" .. host .. ":" .. port .. nexturi
+ local nuri = response.headers.Location or response.headers.location
+ if not nuri then
+ return nil, -5, "invalid reference"
+ end
+ if not nuri:find("https?://") then
+ nuri = pr .. "://" .. host .. ":" .. port .. nuri
end
options.depth = options.depth - 1
sock:close()
- return request_raw(nexturi, options)
+ return request_raw(nuri, options)
end
end
end
return table.concat(cookiedata, "; ")
-end
\ No newline at end of file
+end