123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- require 'socket'
- require 'utils'
- module(..., package.seeall)
- local Content_type = {'application/x-www-form-urlencoded', 'application/json', 'application/octet-stream'}
- function urlencodeTab(params)
- local msg = {}
- for k, v in pairs(params) do
- table.insert(msg, string.urlEncode(k) .. '=' .. string.urlEncode(v))
- table.insert(msg, '&')
- end
- table.remove(msg)
- return table.concat(msg)
- end
- function request(method, url, timeout, params, data, ctype, basic, head, cert, fnc)
- local response_header, response_code, response_body = {}
- local _, idx, offset, ssl, auth, https, host, port, path
- local headers = {
- ['User-Agent'] = 'Mozilla/4.0',
- ['Accept'] = '*/*',
- ['Accept-Language'] = 'zh-CN,zh,cn',
- ['Content-Type'] = 'application/x-www-form-urlencoded',
- ['Connection'] = 'close',
- }
- if type(head) == "string" then
- log.info("user header:", basic, head)
- local tmp = {}
- for k, v in string.gmatch(head, "(.-):%s*(.-)\r\n") do tmp[k] = v end
-
- table.merge(headers, tmp)
- elseif type(head) == "table" then
- table.merge(headers, head)
- end
-
- _, offset, https = url:find("^(%a+)://")
- _, idx, auth = url:find("(.-:.-)@", (offset or 0) + 1)
- offset = idx or offset
-
- if url:match("^[^/]+:(%d+)", (offset or 0) + 1) then
- _, offset, host, port = url:find("^([^/]+):(%d+)", (offset or 0) + 1)
- elseif url:find("(.-)/", (offset or 0) + 1) then
- _, offset, host = url:find("(.-)/", (offset or 0) + 1)
- offset = offset - 1
- else
- offset, host = #url, url:sub((offset or 0) + 1, -1)
- end
- if not host then return '105', 'ERR_NAME_NOT_RESOLVED' end
- if not headers.Host then headers["Host"] = host end
- port = port or (https == "https" and 443 or 80)
- path = url:sub(offset + 1, -1)
- path = path == "" and "/" or path
-
- if params then path = path .. '?' .. (type(params) == 'table' and urlencodeTab(params) or params) end
-
- ctype = ctype or 2
- headers['Content-Type'] = Content_type[ctype]
- if ctype == 1 and type(data) == 'table' then
- data = urlencodeTab(data)
- headers['Content-Length'] = #data or 0
- elseif ctype == 2 and data ~= nil then
- data = type(data) == 'string' and data or (type(data) == 'table' and json.encode(data)) or ""
- headers['Content-Length'] = #data or 0
- elseif ctype == 3 and type(data) == 'string' then
- headers['Content-Length'] = io.fileSize(data) or 0
- elseif data and type(data) == "string" then
- headers['Content-Length'] = #data or 0
- end
-
- if auth then
- headers['Authorization'] = 'Basic ' .. crypto.base64_encode(auth, #auth)
- elseif type(basic) == 'string' and basic ~= "" then
- headers['Authorization'] = 'Basic ' .. crypto.base64_encode(basic, #basic)
- end
-
- local str = ""
- for k, v in pairs(headers) do str = str .. k .. ": " .. v .. "\r\n" end
-
- while not socket.isReady() do sys.wait(1000) end
- local c = socket.tcp(https == "https", cert)
- if not c:connect(host, port) then
- c:close()
- return '502', 'SOCKET_CONN_ERROR'
- end
- if ctype ~= 3 then
- str = method .. ' ' .. path .. ' HTTP/1.0\r\n' .. str .. '\r\n' .. (data and data .. "\r\n" or "")
- log.info("发送的http报文:", str)
- if not c:send(str) then
- c:close()
- return '426', 'SOCKET_SEND_ERROR'
- end
- else
- str = method .. ' ' .. path .. ' HTTP/1.0\r\n' .. str .. '\r\n'
- log.info("发送的http报文:", str)
- if not c:send(str) then
- c:close()
- return '426', 'SOCKET_SEND_ERROR'
- end
- local file = io.open(data, 'r')
- if file then
- while true do
- local dat = file:read(8192)
- if dat == nil then
- io.close(file)
- break
- end
- if not c:send(dat) then
- io.close(file)
- c:close()
- return '426', 'SOCKET_SEND_ERROR'
- end
- end
- end
- if not c:send('\r\n') then
- c:close()
- return '426', 'SOCKET_SEND_ERROR'
- end
- end
-
- local msg, str = {}, ""
- local r, s = c:recv(timeout)
- if not r then
- c:close()
- return '503', 'SOCKET_RECV_TIMOUT'
- end
-
- _, idx, response_code = s:find("%s(%d+)%s.-\r\n")
- _, offset = s:find('\r\n\r\n')
- if not idx or not offset then return '501', 'SERVER_NOT_RESPONSE' end
- log.info('httpv2.response code:', response_code)
-
- for k, v in string.gmatch(s:sub(idx + 1, offset), "(.-):%s*(.-)\r\n") do response_header[k] = v end
- local len = response_header["Content-Range"] and tonumber(response_header["Content-Range"]:match("/(%d+)")) or tonumber(response_header["Content-Length"]) or 2147483648
- s = s:sub((offset or 0) + 1, -1)
- local cnt = #s
- if tonumber(response_code) == 200 or tonumber(response_code) == 206 then
-
- while true do
- if type(fnc) == "function" then
- fnc(s, len)
- else
- table.insert(msg, s)
- end
- if cnt >= len then break end
- r, s = c:recv(timeout)
- if not r then break end
- cnt = cnt + #s
- end
- s = table.concat(msg) or ""
- end
- c:close()
- local gzip = response_header["Content-Encoding"] == "gzip"
- return response_code, response_header, gzip and ((zlib.inflate(s)):read()) or s
- end
|