首页 > 解决方案 > Lua如何从远程http请求文件

问题描述

我想通过 http 访问一个文件,然后拥有可用的功能,就好像我“需要”一个本地文件一样。

local file_url = "http://127.0.0.1:800/myfile.lua"

local http = require("socket.http")
local remote = http.request(file_url) 
require "remote"

我该怎么做

标签: lua

解决方案


加载包require的实际行为是由存储在表中的一系列函数package.searchers执行的(用 Lua 5.2+ 的说法。5.1 使用package.loaders,但它是相同的想法)。您需要做的就是添加一个搜索器函数,该函数可以处理名称为 URL 的“包”:

local http = require("socket.http")

local function http_loader(module_uri)

    --I don't know what this function does, so I assume it returns the actual text of the file.
    --If not, feel free to insert whatever the `socket` module needs to retrieve the text at the URI.
    local module_text = http.request(module_uri) 

    --Always do error checking.
    if --[[did the request succeed?]] then
        return loadstring(module_text)
    else
        return "could not find HTTP module name " .. module_uri
    end
end

table.insert(package.searchers, http_loader)

有了这个,你应该可以require "http://127.0.0.1:800/myfile.lua"直接执行了。

相反,如果您想预加载网络上的某些特定模块,则可以使用packages.preloadtable。例如,如果你想http://127.0.0.1:800/myfile.lua使用模块名“remote”预加载一个 Lua 文件,你可以这样做:

local http = require("socket.http")

local function http_preload(module_uri, module_name)
    local module_text = http.request(module_uri) --Again, assuming this is the text.

    --Always do error checking.
    if --[[did the request succeed?]] then
        package.preload[module_name] = loadstring(module_text)
        return true
    else
        return nil, "could not find HTTP module name " .. module_uri
    end
end

assert(http_preload("http://127.0.0.1:800/myfile.lua", "remote"))

require "remote" --Includes the loaded file.

现在,这些方法都不会神奇地允许任何模块myfile.lua访问网络资源。如果您使用第一种方法,并且myfile.lua需要一些本地资源(即:在服务器上),那么它将必须通过 HTTP 访问它们,就像它在客户端上一样(因为它是从那里加载的)。

如果您使用第二种方法,则必须按 http_preload顺序加载模块,以便没有模块尝试加载尚未预加载的资源。


推荐阅读