| Luacurl = {} |
| Luacurl.__index = Luacurl |
| setmetatable(Luacurl, { |
| __call = function (cls, ...) |
| return cls.new(...) |
| end, |
| }) |
| function Luacurl.new(server, port, ssl) |
| local self = setmetatable({}, Luacurl) |
| self.sockconnected = false |
| self.server = server |
| self.port = port |
| self.ssl = ssl |
| self.cookies = {} |
| return self |
| end |
| |
| function Luacurl:get(method,url,headers,data) |
| core.Info("MAKING SOCKET") |
| if self.sockconnected == false then |
| self.sock = core.tcp() |
| if self.ssl then |
| local r = self.sock:connect_ssl(self.server,self.port) |
| else |
| local r = self.sock:connect(self.server,self.port) |
| end |
| self.sockconnected = true |
| end |
| core.Info("SOCKET MADE") |
| local request = method.." "..url.." HTTP/1.1" |
| if data ~= nil then |
| request = request .. "\r\nContent-Length: "..string.len(data) |
| end |
| if headers ~= null then |
| for h,v in pairs(headers) do |
| request = request .. "\r\n"..h..": "..v |
| end |
| end |
| cookstring = "" |
| for cook,cookval in pairs(self.cookies) do |
| cookstring = cookstring .. cook.."="..cookval.."; " |
| end |
| if string.len(cookstring) > 0 then |
| request = request .. "\r\nCookie: "..cookstring |
| end |
| |
| request = request .. "\r\n\r\n" |
| if data and string.len(data) > 0 then |
| request = request .. data |
| end |
| --print(request) |
| core.Info("SENDING REQUEST") |
| self.sock:send(request) |
| |
| -- core.Info("PROCESSING RESPONSE") |
| return processhttpresponse(self.sock) |
| end |
| |
| function processhttpresponse(socket) |
| local res = {} |
| core.Info("1") |
| res.status = socket:receive("*l") |
| core.Info("2") |
| |
| if res.status == nil then |
| core.Info(" processhttpresponse RECEIVING status: NIL") |
| return res |
| end |
| core.Info(" processhttpresponse RECEIVING status:"..res.status) |
| res.headers = {} |
| res.headerslist = {} |
| repeat |
| core.Info("3") |
| local header = socket:receive("*l") |
| if header == nil then |
| return "error" |
| end |
| local valuestart = header:find(":") |
| if valuestart ~= nil then |
| local head = header:sub(1,valuestart-1) |
| local value = header:sub(valuestart+2) |
| table.insert(res.headerslist, {head,value}) |
| res.headers[head] = value |
| end |
| until header == "" |
| local bodydone = false |
| if res.headers["Connection"] ~= nil and res.headers["Connection"] == "close" then |
| -- core.Info("luacurl processresponse with connection:close") |
| res.body = "" |
| repeat |
| core.Info("4") |
| local d = socket:receive("*a") |
| if d ~= nil then |
| res.body = res.body .. d |
| end |
| until d == nil or d == 0 |
| bodydone = true |
| end |
| if bodydone == false and res.headers["Content-Length"] ~= nil then |
| res.contentlength = tonumber(res.headers["Content-Length"]) |
| if res.contentlength == nil then |
| core.Warning("res.contentlength ~NIL = "..res.headers["Content-Length"]) |
| end |
| -- core.Info("luacur, contentlength="..res.contentlength) |
| res.body = "" |
| repeat |
| local d = socket:receive(res.contentlength) |
| if d == nil then |
| -- core.Info("luacurl, ERROR?: received NIL, expecting "..res.contentlength.." bytes only got "..string.len(res.body).." sofar") |
| return |
| else |
| res.body = res.body..d |
| -- core.Info("luacurl, COMPLETE?: expecting "..res.contentlength.." bytes, got "..string.len(res.body)) |
| if string.len(res.body) >= res.contentlength then |
| -- core.Info("luacurl, COMPLETE?: expecting "..res.contentlength.." bytes, got "..string.len(res.body)) |
| break |
| end |
| end |
| -- core.Info("processhttpresponse, Loopy, get more body data! to receive complete contentlenght") |
| until false |
| end |
| if res.headers["Transfer-Encoding"] ~= nil and res.headers["Transfer-Encoding"] == "chunked" then |
| local chunksize = 0 |
| res.contentlength = 0 |
| res.body = "" |
| repeat |
| core.Info("5") |
| local chunksizestr = socket:receive("*l") |
| if chunksizestr == nil then |
| break |
| end |
| chunksize = tonumber("0x"..chunksizestr) |
| if chunksize ~= nil then |
| res.contentlength = res.contentlength + chunksize |
| if chunksize ~= 0 then |
| local chunk = socket:receive(chunksize) |
| res.body = res.body .. chunk |
| chunksizestr = socket:receive("*l") |
| if chunksizestr ~= "" then |
| return "ERROR Chunk-end expected." |
| end |
| end |
| else |
| break |
| end |
| until false |
| end |
| core.Info("6") |
| return res |
| end |
| |
| function Luacurl:close() |
| if self.sockconnected == true then |
| self.sock:close() |
| self.sockconnected = false |
| end |
| end |
| |
| function print_r_string(object) |
| local res = "" |
| print_r(object,false,function(x) res = res .. x end) |
| return res |
| end |
| |
| core.register_service("fakeserv", "http", function(applet) |
| core.Info("APPLET START") |
| local mc = Luacurl("127.0.0.1",8443, true) |
| local headers = {} |
| local body = "" |
| core.Info("APPLET GET") |
| local res = mc:get("GET", "/", headers, body) |
| core.Info("APPLET GET done") |
| local response = print_r_string(res) |
| applet:add_header("Server", "haproxy/webstats") |
| applet:add_header("Content-Length", string.len(response)) |
| applet:add_header("Content-Type", "text/html") |
| applet:start_response() |
| applet:send(response) |
| core.Info("APPLET DONE") |
| end) |