require("socket.http")报错

local http = require(“socket.http”); 报错,如下

local ftp = (“socket.ftp”) 同样报错
local url = (“socket.url”) 同样报错

版本:cocos 3.14.1
运行平台mac simulator

然后报错:

LUA ERROR: module ‘socket.socket’ not found:
no field package.preload[‘socket.socket’]
no file ‘./socket/socket.lua’
no file ‘/usr/local/share/luajit-2.1.0-beta2/socket/socket.lua’
no file ‘/usr/local/share/lua/5.1/socket/socket.lua’
no file ‘/usr/local/share/lua/5.1/socket/socket/init.lua’
no file ‘/Users/xxx/work/shunwo/projects/swtest/src/socket/socket.lua’
no file ‘src/socket/socket.lua’
no file ‘./socket/socket.so’
no file ‘/usr/local/lib/lua/5.1/socket/socket.so’
no file ‘/usr/local/lib/lua/5.1/loadall.so’
no file ‘./socket.so’
no file ‘/usr/local/lib/lua/5.1/socket.so’
no file ‘/usr/local/lib/lua/5.1/loadall.so’

stack traceback:
[src/main.lua]:154 in function ``
3 C function
[-----------------------------------------------------------------------------
– HTTP/1.1 client support for the Lua language.
– LuaSocket toolkit.
– Author: Diego Nehab


– Declare module and import dependencies

local socket = require(“socket.socket”)
local url = require(“socket.url”)
local ltn12 = require(“socket.ltn12”)
local mime = require(“socket.mime”)
local string = require(“string”)
local headers = require(“socket.headers”)
local base = _G
local table = require(“table”)
socket.http = {}
local _M = socket.http


– Program constants

– connection timeout in seconds
TIMEOUT = 60
– default port for document retrieval
_M.PORT = 80
– user agent field sent in request
_M.USERAGENT = socket._VERSION


– Reads MIME headers from a connection, unfolding where needed

local function receiveheaders(sock, headers)
local line, name, value, err
headers = headers or {}
– get first line
line, err = sock:receive()
if err then return nil, err end
– headers go until a blank line is found
while line ~= “” do
– get field-name and value
name, value = socket.skip(2, string.find(line, “^(.-):%s*(.*)”))
if not (name and value) then return nil, “malformed reponse headers” end
name = string.lower(name)
– get next line (value might be folded)
line, err = sock:receive()
if err then return nil, err end
– unfold any folded values
while string.find(line, “^%s”) do
value = value … line
line = sock:receive()
if err then return nil, err end
end
– save pair in table
if headers[name] then headers[name] = headers[name] … ", " … value
else headers[name] = value end
end
return headers
end


– Extra sources and sinks

socket.sourcet[“http-chunked”] = function(sock, headers)
return base.setmetatable({
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end
}, {
__call = function()
– get chunk size, skip extention
local line, err = sock:receive()
if err then return nil, err end
local size = base.tonumber(string.gsub(line, “;.*”, “”), 16)
if not size then return nil, “invalid chunk size” end
– was it the last chunk?
if size > 0 then
– if not, get chunk and skip terminating CRLF
local chunk, err, part = sock:receive(size)
if chunk then sock:receive() end
return chunk, err
else
– if it was, read trailers into headers table
headers, err = receiveheaders(sock, headers)
if not headers then return nil, err end
end
end
})
end

socket.sinkt[“http-chunked”] = function(sock)
return base.setmetatable({
getfd = function() return sock:getfd() end,
dirty = function() return sock:dirty() end
}, {
__call = function(self, chunk, err)
if not chunk then return sock:send(“0\r\n\r\n”) end
local size = string.format("%X\r\n", string.len(chunk))
return sock:send(size … chunk … “\r\n”)
end
})
end


– Low level HTTP API

local metat = { __index = {} }

function _M.open(host, port, create)
– create socket with user connect function, or with default
local c = socket.try((create or socket.tcp)())
local h = base.setmetatable({ c = c }, metat)
– create finalized try
h.try = socket.newtry(function() h:close() end)
– set timeout before connecting
h.try(c:settimeout(_M.TIMEOUT))
h.try(c:connect(host, port or _M.PORT))
– here everything worked
return h
end

function metat.__index:sendrequestline(method, uri)
local reqline = string.format("%s %s HTTP/1.1\r\n", method or “GET”, uri)
return self.try(self.c:send(reqline))
end

function metat.__index:sendheaders(tosend)
local canonic = headers.canonic
local h = “\r\n”
for f, v in base.pairs(tosend) do
h = (canonic[f] or f) … ": " … v … “\r\n” … h
end
self.try(self.c:send(h))
return 1
end

function metat.__index:sendbody(headers, source, step)
source = source or ltn12.source.empty()
step = step or ltn12.pump.step
– if we don’t know the size in advance, send chunked and hope for the best
local mode = “http-chunked”
if headers[“content-length”] then mode = “keep-open” end
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
end

function metat.__index:receivestatusline()
local status = self.try(self.c:receive(5))
– identify HTTP/0.9 responses, which do not contain a status line
– this is just a heuristic, but is what the RFC recommends
if status ~= “HTTP/” then return nil, status end
– otherwise proceed reading a status line
status = self.try(self.c:receive(“l", status))
local code = socket.skip(2, string.find(status, "HTTP/d*.%d
(%d%d%d)”))
return self.try(base.tonumber(code), status)
end

function metat.__index:receiveheaders()
return self.try(receiveheaders(self.c))
end

function metat.__index:receivebody(headers, sink, step)
sink = sink or ltn12.sink.null()
step = step or ltn12.pump.step
local length = base.tonumber(headers[“content-length”])
local t = headers[“transfer-encoding”] – shortcut
local mode = “default” – connection close
if t and t ~= “identity” then mode = “http-chunked”
elseif base.tonumber(headers[“content-length”]) then mode = “by-length” end
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
sink, step))
end

function metat.__index:receive09body(status, sink, step)
local source = ltn12.source.rewind(socket.source(“until-closed”, self.c))
source(status)
return self.try(ltn12.pump.all(source, sink, step))
end

function metat.__index:close()
return self.c:close()
end


– High level HTTP API

local function adjusturi(reqt)
local u = reqt
– if there is a proxy, we need the full url. otherwise, just a part.
if not reqt.proxy and not PROXY then
u = {
path = socket.try(reqt.path, “invalid path ‘nil’”),
params = reqt.params,
query = reqt.query,
fragment = reqt.fragment
}
end
return url.build(u)
end

local function adjustproxy(reqt)
local proxy = reqt.proxy or PROXY
if proxy then
proxy = url.parse(proxy)
return proxy.host, proxy.port or 3128
else
return reqt.host, reqt.port
end
end

local function adjustheaders(reqt)
– default headers
local lower = {
[“user-agent”] = _M.USERAGENT,
[“host”] = reqt.host,
[“connection”] = “close, TE”,
[“te”] = “trailers”
}
– if we have authentication information, pass it along
if reqt.user and reqt.password then
lower[“authorization”] =
"Basic " … (mime.b64(reqt.user … “:” … reqt.password))
end
– override with user headers
for i,v in base.pairs(reqt.headers or lower) do
lower[string.lower(i)] = v
end
return lower
end

– default url parts
local default = {
host = “”,
port = _M.PORT,
path ="/",
scheme = “http”
}

local function adjustrequest(reqt)
– parse url if provided
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
– explicit components override url
for i,v in base.pairs(reqt) do nreqt[i] = v end
if nreqt.port == “” then nreqt.port = 80 end
socket.try(nreqt.host and nreqt.host ~= “”,
“invalid host '” … base.tostring(nreqt.host) … “’”)
– compute uri if user hasn’t overriden
nreqt.uri = reqt.uri or adjusturi(nreqt)
– ajust host and port if there is a proxy
nreqt.host, nreqt.port = adjustproxy(nreqt)
– adjust headers in request
nreqt.headers = adjustheaders(nreqt)
return nreqt
end

local function shouldredirect(reqt, code, headers)
return headers.location and
string.gsub(headers.location, “%s”, “”) ~= “” and
(reqt.redirect ~= false) and
(code == 301 or code == 302 or code == 303 or code == 307) and
(not reqt.method or reqt.method == “GET” or reqt.method == “HEAD”)
and (not reqt.nredirects or reqt.nredirects < 5)
end

local function shouldreceivebody(reqt, code)
if reqt.method == “HEAD” then return nil end
if code == 204 or code == 304 then return nil end
if code >= 100 and code < 200 then return nil end
return 1
end

– forward declarations
local trequest, tredirect

–[[local]] function tredirect(reqt, location)
local result, code, headers, status = trequest {
– the RFC says the redirect URL has to be absolute, but some
– servers do not respect that
url = url.absolute(reqt.url, location),
source = reqt.source,
sink = reqt.sink,
headers = reqt.headers,
proxy = reqt.proxy,
nredirects = (reqt.nredirects or 0) + 1,
create = reqt.create
}
– pass location header back as a hint we redirected
headers = headers or {}
headers.location = headers.location or location
return result, code, headers, status
end

–[[local]] function trequest(reqt)
– we loop until we get what we want, or
– until we are sure there is no way to get it
local nreqt = adjustrequest(reqt)
local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
– send request line and headers
h:sendrequestline(nreqt.method, nreqt.uri)
h:sendheaders(nreqt.headers)
– if there is a body, send it
if nreqt.source then
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
end
local code, status = h:receivestatusline()
– if it is an HTTP/0.9 server, simply get the body and we are done
if not code then
h:receive09body(status, nreqt.sink, nreqt.step)
return 1, 200
end
local headers
– ignore any 100-continue messages
while code == 100 do
headers = h:receiveheaders()
code, status = h:receivestatusline()
end
headers = h:receiveheaders()
– at this point we should have a honest reply from the server
– we can’t redirect if we already used the source, so we report the error
if shouldredirect(nreqt, code, headers) and not nreqt.source then
h:close()
return tredirect(reqt, headers.location)
end
– here we are finally done
if shouldreceivebody(nreqt, code) then
h:receivebody(headers, nreqt.sink, nreqt.step)
end
h:close()
return 1, code, headers, status
end

local function srequest(u, b)
local t = {}
local reqt = {
url = u,
sink = ltn12.sink.table(t)
}
if b then
reqt.source = ltn12.source.string(b)
reqt.headers = {
[“content-length”] = string.len(b),
[“content-type”] = “application/x-www-form-urlencoded”
}
reqt.method = “POST”
end
local code, headers, status = socket.skip(1, trequest(reqt))
return table.concat(t), code, headers, status
end

_M.request = socket.protect(function(reqt, body)
if base.type(reqt) == “string” then return srequest(reqt, body)
else return trequest(reqt) end
end)

return _M

]:10 in function 5 C function [clientcore/com/main/network/luasocket_ect/get.lua]:27 in function
7 C function
[clientcore/ClientCoreConfig.lua]:82 in function func
[app/Client.lua]:155 in function onCall
[app/Client.lua]:140 in function beginCall
[app/Client.lua]:118 in function run
[app/ClientLauncher.lua]:143 in function runGame
[app/ClientLauncher.lua]:132 in function launch
[src/main.lua]:121 in function launch
[src/main.lua]:124 in function run
[src/main.lua]:184 in function 17 C function [src/main.lua]:195 in function
19 C function
[require “src/main.lua”]:1 in function ``

我日哟。。。。只能这么恶心的解决了。。。
发现源代码luasocket_scripts.c应该是cocos引擎组的人写的
感觉升级了luasocket后,luasocket_scripts.c没有维护好
这个判断基于cocos引擎组做事一贯毛毛躁躁的作风猜测判断,虽然这个结论不一定正确,但是真不是空穴来风,如果我猜测错误,麻烦引擎组解析一下,我可以为我乱喷而道歉

解决方案:
local oldRequire = require

local function newRequire(path)
if path == “socket.socket” then
path = “socket”
elseif path == “socket.ltn12” then
path = “ltn12”
elseif path == “socket.mime” then
path = “mime”
end
return oldRequire(path)
end

require = newRequire

解决还是解决了,就是担心这样维护cocos的luasocket会有各种问题。。。
最后一句nnd