Move some functions out of bios into their own APIs

This removes the patching of fs and http, and replaces them with their
own standard Lua APIs. This makes the bios a little simpler, and means
we can move the documentation in line.
This commit is contained in:
Jonathan Coates 2022-11-21 22:47:07 +00:00
parent 3a96aea894
commit ee2670d53b
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
7 changed files with 467 additions and 487 deletions

View File

@ -1,64 +0,0 @@
--- @module fs
--- Returns true if a path is mounted to the parent filesystem.
--
-- The root filesystem "/" is considered a mount, along with disk folders and
-- the rom folder. Other programs (such as network shares) can exstend this to
-- make other mount types by correctly assigning their return value for getDrive.
--
-- @tparam string path The path to check.
-- @treturn boolean If the path is mounted, rather than a normal file/folder.
-- @throws If the path does not exist.
-- @see getDrive
-- @since 1.87.0
function isDriveRoot(path) end
--[[- Provides completion for a file or directory name, suitable for use with
@{_G.read}.
When a directory is a possible candidate for completion, two entries are
included - one with a trailing slash (indicating that entries within this
directory exist) and one without it (meaning this entry is an immediate
completion candidate). `include_dirs` can be set to @{false} to only include
those with a trailing slash.
@tparam[1] string path The path to complete.
@tparam[1] string location The location where paths are resolved from.
@tparam[1,opt=true] boolean include_files When @{false}, only directories will
be included in the returned list.
@tparam[1,opt=true] boolean include_dirs When @{false}, "raw" directories will
not be included in the returned list.
@tparam[2] string path The path to complete.
@tparam[2] string location The location where paths are resolved from.
@tparam[2] {
include_dirs? = boolean, include_files? = boolean,
include_hidden? = boolean
} options
This table form is an expanded version of the previous syntax. The
`include_files` and `include_dirs` arguments from above are passed in as fields.
This table also accepts the following options:
- `include_hidden`: Whether to include hidden files (those starting with `.`)
by default. They will still be shown when typing a `.`.
@treturn { string... } A list of possible completion candidates.
@since 1.74
@changed 1.101.0
@usage Complete files in the root directory.
read(nil, nil, function(str)
return fs.complete(str, "", true, false)
end)
@usage Complete files in the root directory, hiding hidden files by default.
read(nil, nil, function(str)
return fs.complete(str, "", {
include_files = true,
include_dirs = false,
included_hidden = false,
})
end)
]]
function complete(path, location, include_files, include_dirs) end

View File

@ -1,177 +0,0 @@
--- Make HTTP requests, sending and receiving data to a remote web server.
--
-- @module http
-- @since 1.1
-- @see local_ips To allow accessing servers running on your local network.
--- Asynchronously make a HTTP request to the given url.
--
-- This returns immediately, a @{http_success} or @{http_failure} will be queued
-- once the request has completed.
--
-- @tparam string url The url to request
-- @tparam[opt] string body An optional string containing the body of the
-- request. If specified, a `POST` request will be made instead.
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of this request.
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
-- the body will not be UTF-8 encoded, and the received response will not be
-- decoded.
--
-- @tparam[2] {
-- url = string, body? = string, headers? = { [string] = string },
-- binary? = boolean, method? = string, redirect? = boolean,
-- } request Options for the request.
--
-- This table form is an expanded version of the previous syntax. All arguments
-- from above are passed in as fields instead (for instance,
-- `http.request("https://example.com")` becomes `http.request { url =
-- "https://example.com" }`).
--
-- This table also accepts several additional options:
--
-- - `method`: Which HTTP method to use, for instance `"PATCH"` or `"DELETE"`.
-- - `redirect`: Whether to follow HTTP redirects. Defaults to true.
--
-- @see http.get For a synchronous way to make GET requests.
-- @see http.post For a synchronous way to make POST requests.
--
-- @changed 1.63 Added argument for headers.
-- @changed 1.80pr1 Added argument for binary handles.
-- @changed 1.80pr1.6 Added support for table argument.
-- @changed 1.86.0 Added PATCH and TRACE methods.
function request(...) end
--- Make a HTTP GET request to the given url.
--
-- @tparam string url The url to request
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of this request.
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
-- the body will not be UTF-8 encoded, and the received response will not be
-- decoded.
--
-- @tparam[2] {
-- url = string, headers? = { [string] = string },
-- binary? = boolean, method? = string, redirect? = boolean,
-- } request Options for the request. See @{http.request} for details on how
-- these options behave.
--
-- @treturn Response The resulting http response, which can be read from.
-- @treturn[2] nil When the http request failed, such as in the event of a 404
-- error or connection timeout.
-- @treturn string A message detailing why the request failed.
-- @treturn Response|nil The failing http response, if available.
--
-- @changed 1.63 Added argument for headers.
-- @changed 1.80pr1 Response handles are now returned on error if available.
-- @changed 1.80pr1 Added argument for binary handles.
-- @changed 1.80pr1.6 Added support for table argument.
-- @changed 1.86.0 Added PATCH and TRACE methods.
--
-- @usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
-- and print the returned page.
-- ```lua
-- local request = http.get("https://example.tweaked.cc")
-- print(request.readAll())
-- -- => HTTP is working!
-- request.close()
-- ```
function get(...) end
--- Make a HTTP POST request to the given url.
--
-- @tparam string url The url to request
-- @tparam string body The body of the POST request.
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of this request.
-- @tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
-- the body will not be UTF-8 encoded, and the received response will not be
-- decoded.
--
-- @tparam[2] {
-- url = string, body? = string, headers? = { [string] = string },
-- binary? = boolean, method? = string, redirect? = boolean,
-- } request Options for the request. See @{http.request} for details on how
-- these options behave.
--
-- @treturn Response The resulting http response, which can be read from.
-- @treturn[2] nil When the http request failed, such as in the event of a 404
-- error or connection timeout.
-- @treturn string A message detailing why the request failed.
-- @treturn Response|nil The failing http response, if available.
--
-- @since 1.31
-- @changed 1.63 Added argument for headers.
-- @changed 1.80pr1 Response handles are now returned on error if available.
-- @changed 1.80pr1 Added argument for binary handles.
-- @changed 1.80pr1.6 Added support for table argument.
-- @changed 1.86.0 Added PATCH and TRACE methods.
function post(...) end
--- Asynchronously determine whether a URL can be requested.
--
-- If this returns `true`, one should also listen for @{http_check} which will
-- container further information about whether the URL is allowed or not.
--
-- @tparam string url The URL to check.
-- @treturn true When this url is not invalid. This does not imply that it is
-- allowed - see the comment above.
-- @treturn[2] false When this url is invalid.
-- @treturn string A reason why this URL is not valid (for instance, if it is
-- malformed, or blocked).
--
-- @see http.checkURL For a synchronous version.
function checkURLAsync(url) end
--- Determine whether a URL can be requested.
--
-- If this returns `true`, one should also listen for @{http_check} which will
-- container further information about whether the URL is allowed or not.
--
-- @tparam string url The URL to check.
-- @treturn true When this url is valid and can be requested via @{http.request}.
-- @treturn[2] false When this url is invalid.
-- @treturn string A reason why this URL is not valid (for instance, if it is
-- malformed, or blocked).
--
-- @see http.checkURLAsync For an asynchronous version.
--
-- @usage
-- ```lua
-- print(http.checkURL("https://example.tweaked.cc/"))
-- -- => true
-- print(http.checkURL("http://localhost/"))
-- -- => false Domain not permitted
-- print(http.checkURL("not a url"))
-- -- => false URL malformed
-- ```
function checkURL(url) end
--- Open a websocket.
--
-- @tparam string url The websocket url to connect to. This should have the
-- `ws://` or `wss://` protocol.
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of the initial websocket connection.
--
-- @treturn Websocket The websocket connection.
-- @treturn[2] false If the websocket connection failed.
-- @treturn string An error message describing why the connection failed.
-- @since 1.80pr1.1
-- @changed 1.80pr1.3 No longer asynchronous.
-- @changed 1.95.3 Added User-Agent to default headers.
function websocket(url, headers) end
--- Asynchronously open a websocket.
--
-- This returns immediately, a @{websocket_success} or @{websocket_failure}
-- will be queued once the request has completed.
--
-- @tparam string url The websocket url to connect to. This should have the
-- `ws://` or `wss://` protocol.
-- @tparam[opt] { [string] = string } headers Additional headers to send as part
-- of the initial websocket connection.
-- @since 1.80pr1.3
-- @changed 1.95.3 Added User-Agent to default headers.
function websocketAsync(url, headers) end

View File

@ -3,7 +3,7 @@
-- Ideally we'd use require, but that is part of the shell, and so is not
-- available to the BIOS or any APIs. All APIs load this using dofile, but that
-- has not been defined at this point.
local expect, field
local expect
do
local h = fs.open("rom/modules/main/cc/expect.lua", "r")
@ -11,8 +11,7 @@ do
h.close()
if not f then error(err) end
local res = f()
expect, field = res.expect, res.field
expect = f().expect
end
if _VERSION == "Lua 5.1" then
@ -584,257 +583,28 @@ function os.reboot()
end
end
-- Install the lua part of the HTTP api (if enabled)
if http then
local nativeHTTPRequest = http.request
local bAPIError = false
local methods = {
GET = true, POST = true, HEAD = true,
OPTIONS = true, PUT = true, DELETE = true,
PATCH = true, TRACE = true,
}
local function load_apis(dir)
if not fs.isDir(dir) then return end
local function checkKey(options, key, ty, opt)
local value = options[key]
local valueTy = type(value)
if (value ~= nil or not opt) and valueTy ~= ty then
error(("bad field '%s' (expected %s, got %s"):format(key, ty, valueTy), 4)
end
end
local function checkOptions(options, body)
checkKey(options, "url", "string")
if body == false then
checkKey(options, "body", "nil")
else
checkKey(options, "body", "string", not body)
end
checkKey(options, "headers", "table", true)
checkKey(options, "method", "string", true)
checkKey(options, "redirect", "boolean", true)
if options.method and not methods[options.method] then
error("Unsupported HTTP method", 3)
end
end
local function wrapRequest(_url, ...)
local ok, err = nativeHTTPRequest(...)
if ok then
while true do
local event, param1, param2, param3 = os.pullEvent()
if event == "http_success" and param1 == _url then
return param2
elseif event == "http_failure" and param1 == _url then
return nil, param2, param3
for _, file in ipairs(fs.list(dir)) do
if file:sub(1, 1) ~= "." then
local path = fs.combine(dir, file)
if not fs.isDir(path) then
if not os.loadAPI(path) then
bAPIError = true
end
end
end
return nil, err
end
http.get = function(_url, _headers, _binary)
if type(_url) == "table" then
checkOptions(_url, false)
return wrapRequest(_url.url, _url)
end
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
expect(3, _binary, "boolean", "nil")
return wrapRequest(_url, _url, nil, _headers, _binary)
end
http.post = function(_url, _post, _headers, _binary)
if type(_url) == "table" then
checkOptions(_url, true)
return wrapRequest(_url.url, _url)
end
expect(1, _url, "string")
expect(2, _post, "string")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
return wrapRequest(_url, _url, _post, _headers, _binary)
end
http.request = function(_url, _post, _headers, _binary)
local url
if type(_url) == "table" then
checkOptions(_url)
url = _url.url
else
expect(1, _url, "string")
expect(2, _post, "string", "nil")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
url = _url.url
end
local ok, err = nativeHTTPRequest(_url, _post, _headers, _binary)
if not ok then
os.queueEvent("http_failure", url, err)
end
return ok, err
end
local nativeCheckURL = http.checkURL
http.checkURLAsync = nativeCheckURL
http.checkURL = function(_url)
expect(1, _url, "string")
local ok, err = nativeCheckURL(_url)
if not ok then return ok, err end
while true do
local _, url, ok, err = os.pullEvent("http_check")
if url == _url then return ok, err end
end
end
local nativeWebsocket = http.websocket
http.websocketAsync = nativeWebsocket
http.websocket = function(_url, _headers)
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
local ok, err = nativeWebsocket(_url, _headers)
if not ok then return ok, err end
while true do
local event, url, param = os.pullEvent( )
if event == "websocket_success" and url == _url then
return param
elseif event == "websocket_failure" and url == _url then
return false, param
end
end
end
end
-- Install the lua part of the FS api
local tEmpty = {}
function fs.complete(sPath, sLocation, bIncludeFiles, bIncludeDirs)
expect(1, sPath, "string")
expect(2, sLocation, "string")
local bIncludeHidden = nil
if type(bIncludeFiles) == "table" then
bIncludeDirs = field(bIncludeFiles, "include_dirs", "boolean", "nil")
bIncludeHidden = field(bIncludeFiles, "include_hidden", "boolean", "nil")
bIncludeFiles = field(bIncludeFiles, "include_files", "boolean", "nil")
else
expect(3, bIncludeFiles, "boolean", "nil")
expect(4, bIncludeDirs, "boolean", "nil")
end
bIncludeHidden = bIncludeHidden ~= false
bIncludeFiles = bIncludeFiles ~= false
bIncludeDirs = bIncludeDirs ~= false
local sDir = sLocation
local nStart = 1
local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash == 1 then
sDir = ""
nStart = 2
end
local sName
while not sName do
local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash then
local sPart = string.sub(sPath, nStart, nSlash - 1)
sDir = fs.combine(sDir, sPart)
nStart = nSlash + 1
else
sName = string.sub(sPath, nStart)
end
end
if fs.isDir(sDir) then
local tResults = {}
if bIncludeDirs and sPath == "" then
table.insert(tResults, ".")
end
if sDir ~= "" then
if sPath == "" then
table.insert(tResults, bIncludeDirs and ".." or "../")
elseif sPath == "." then
table.insert(tResults, bIncludeDirs and "." or "./")
end
end
local tFiles = fs.list(sDir)
for n = 1, #tFiles do
local sFile = tFiles[n]
if #sFile >= #sName and string.sub(sFile, 1, #sName) == sName and (
bIncludeHidden or sFile:sub(1, 1) ~= "." or sName:sub(1, 1) == "."
) then
local bIsDir = fs.isDir(fs.combine(sDir, sFile))
local sResult = string.sub(sFile, #sName + 1)
if bIsDir then
table.insert(tResults, sResult .. "/")
if bIncludeDirs and #sResult > 0 then
table.insert(tResults, sResult)
end
else
if bIncludeFiles and #sResult > 0 then
table.insert(tResults, sResult)
end
end
end
end
return tResults
end
return tEmpty
end
function fs.isDriveRoot(sPath)
expect(1, sPath, "string")
-- Force the root directory to be a mount.
return fs.getDir(sPath) == ".." or fs.getDrive(sPath) ~= fs.getDrive(fs.getDir(sPath))
end
-- Load APIs
local bAPIError = false
local tApis = fs.list("rom/apis")
for _, sFile in ipairs(tApis) do
if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine("rom/apis", sFile)
if not fs.isDir(sPath) then
if not os.loadAPI(sPath) then
bAPIError = true
end
end
end
end
if turtle and fs.isDir("rom/apis/turtle") then
-- Load turtle APIs
local tApis = fs.list("rom/apis/turtle")
for _, sFile in ipairs(tApis) do
if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine("rom/apis/turtle", sFile)
if not fs.isDir(sPath) then
if not os.loadAPI(sPath) then
bAPIError = true
end
end
end
end
end
if pocket and fs.isDir("rom/apis/pocket") then
-- Load pocket APIs
local tApis = fs.list("rom/apis/pocket")
for _, sFile in ipairs(tApis) do
if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine("rom/apis/pocket", sFile)
if not fs.isDir(sPath) then
if not os.loadAPI(sPath) then
bAPIError = true
end
end
end
end
end
load_apis("rom/apis")
if http then load_apis("rom/apis/http") end
if turtle then load_apis("rom/apis/turtle") end
if pocket then load_apis("rom/apis/pocket") end
if commands and fs.isDir("rom/apis/command") then
-- Load command APIs

View File

@ -0,0 +1,147 @@
--- @module fs
local expect = dofile("rom/modules/main/cc/expect.lua")
local expect, field = expect.expect, expect.field
local native = fs
local fs = _ENV
for k, v in pairs(native) do fs[k] = v end
--[[- Provides completion for a file or directory name, suitable for use with
@{_G.read}.
When a directory is a possible candidate for completion, two entries are
included - one with a trailing slash (indicating that entries within this
directory exist) and one without it (meaning this entry is an immediate
completion candidate). `include_dirs` can be set to @{false} to only include
those with a trailing slash.
@tparam[1] string path The path to complete.
@tparam[1] string location The location where paths are resolved from.
@tparam[1,opt=true] boolean include_files When @{false}, only directories will
be included in the returned list.
@tparam[1,opt=true] boolean include_dirs When @{false}, "raw" directories will
not be included in the returned list.
@tparam[2] string path The path to complete.
@tparam[2] string location The location where paths are resolved from.
@tparam[2] {
include_dirs? = boolean, include_files? = boolean,
include_hidden? = boolean
} options
This table form is an expanded version of the previous syntax. The
`include_files` and `include_dirs` arguments from above are passed in as fields.
This table also accepts the following options:
- `include_hidden`: Whether to include hidden files (those starting with `.`)
by default. They will still be shown when typing a `.`.
@treturn { string... } A list of possible completion candidates.
@since 1.74
@changed 1.101.0
@usage Complete files in the root directory.
read(nil, nil, function(str)
return fs.complete(str, "", true, false)
end)
@usage Complete files in the root directory, hiding hidden files by default.
read(nil, nil, function(str)
return fs.complete(str, "", {
include_files = true,
include_dirs = false,
included_hidden = false,
})
end)
]]
function fs.complete(sPath, sLocation, bIncludeFiles, bIncludeDirs)
expect(1, sPath, "string")
expect(2, sLocation, "string")
local bIncludeHidden = nil
if type(bIncludeFiles) == "table" then
bIncludeDirs = field(bIncludeFiles, "include_dirs", "boolean", "nil")
bIncludeHidden = field(bIncludeFiles, "include_hidden", "boolean", "nil")
bIncludeFiles = field(bIncludeFiles, "include_files", "boolean", "nil")
else
expect(3, bIncludeFiles, "boolean", "nil")
expect(4, bIncludeDirs, "boolean", "nil")
end
bIncludeHidden = bIncludeHidden ~= false
bIncludeFiles = bIncludeFiles ~= false
bIncludeDirs = bIncludeDirs ~= false
local sDir = sLocation
local nStart = 1
local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash == 1 then
sDir = ""
nStart = 2
end
local sName
while not sName do
local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash then
local sPart = string.sub(sPath, nStart, nSlash - 1)
sDir = fs.combine(sDir, sPart)
nStart = nSlash + 1
else
sName = string.sub(sPath, nStart)
end
end
if fs.isDir(sDir) then
local tResults = {}
if bIncludeDirs and sPath == "" then
table.insert(tResults, ".")
end
if sDir ~= "" then
if sPath == "" then
table.insert(tResults, bIncludeDirs and ".." or "../")
elseif sPath == "." then
table.insert(tResults, bIncludeDirs and "." or "./")
end
end
local tFiles = fs.list(sDir)
for n = 1, #tFiles do
local sFile = tFiles[n]
if #sFile >= #sName and string.sub(sFile, 1, #sName) == sName and (
bIncludeHidden or sFile:sub(1, 1) ~= "." or sName:sub(1, 1) == "."
) then
local bIsDir = fs.isDir(fs.combine(sDir, sFile))
local sResult = string.sub(sFile, #sName + 1)
if bIsDir then
table.insert(tResults, sResult .. "/")
if bIncludeDirs and #sResult > 0 then
table.insert(tResults, sResult)
end
else
if bIncludeFiles and #sResult > 0 then
table.insert(tResults, sResult)
end
end
end
end
return tResults
end
return {}
end
--- Returns true if a path is mounted to the parent filesystem.
--
-- The root filesystem "/" is considered a mount, along with disk folders and
-- the rom folder. Other programs (such as network shares) can exstend this to
-- make other mount types by correctly assigning their return value for getDrive.
--
-- @tparam string path The path to check.
-- @treturn boolean If the path is mounted, rather than a normal file/folder.
-- @throws If the path does not exist.
-- @see getDrive
-- @since 1.87.0
function fs.isDriveRoot(sPath)
expect(1, sPath, "string")
-- Force the root directory to be a mount.
return fs.getDir(sPath) == ".." or fs.getDrive(sPath) ~= fs.getDrive(fs.getDir(sPath))
end

View File

@ -0,0 +1,303 @@
--[[- Make HTTP requests, sending and receiving data to a remote web server.
@module http
@since 1.1
@see local_ips To allow accessing servers running on your local network.
]]
local expect = dofile("rom/modules/main/cc/expect.lua").expect
local native = http
local nativeHTTPRequest = http.request
local methods = {
GET = true, POST = true, HEAD = true,
OPTIONS = true, PUT = true, DELETE = true,
PATCH = true, TRACE = true,
}
local function checkKey(options, key, ty, opt)
local value = options[key]
local valueTy = type(value)
if (value ~= nil or not opt) and valueTy ~= ty then
error(("bad field '%s' (expected %s, got %s"):format(key, ty, valueTy), 4)
end
end
local function checkOptions(options, body)
checkKey(options, "url", "string")
if body == false then
checkKey(options, "body", "nil")
else
checkKey(options, "body", "string", not body)
end
checkKey(options, "headers", "table", true)
checkKey(options, "method", "string", true)
checkKey(options, "redirect", "boolean", true)
if options.method and not methods[options.method] then
error("Unsupported HTTP method", 3)
end
end
local function wrapRequest(_url, ...)
local ok, err = nativeHTTPRequest(...)
if ok then
while true do
local event, param1, param2, param3 = os.pullEvent()
if event == "http_success" and param1 == _url then
return param2
elseif event == "http_failure" and param1 == _url then
return nil, param2, param3
end
end
end
return nil, err
end
--[[- Make a HTTP GET request to the given url.
@tparam string url The url to request
@tparam[opt] { [string] = string } headers Additional headers to send as part
of this request.
@tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
the body will not be UTF-8 encoded, and the received response will not be
decoded.
@tparam[2] {
url = string, headers? = { [string] = string },
binary? = boolean, method? = string, redirect? = boolean,
} request Options for the request. See @{http.request} for details on how
these options behave.
@treturn Response The resulting http response, which can be read from.
@treturn[2] nil When the http request failed, such as in the event of a 404
error or connection timeout.
@treturn string A message detailing why the request failed.
@treturn Response|nil The failing http response, if available.
@changed 1.63 Added argument for headers.
@changed 1.80pr1 Response handles are now returned on error if available.
@changed 1.80pr1 Added argument for binary handles.
@changed 1.80pr1.6 Added support for table argument.
@changed 1.86.0 Added PATCH and TRACE methods.
@usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
and print the returned page.
```lua
local request = http.get("https://example.tweaked.cc")
print(request.readAll())
-- => HTTP is working!
request.close()
```
]]
function get(_url, _headers, _binary)
if type(_url) == "table" then
checkOptions(_url, false)
return wrapRequest(_url.url, _url)
end
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
expect(3, _binary, "boolean", "nil")
return wrapRequest(_url, _url, nil, _headers, _binary)
end
--[[- Make a HTTP POST request to the given url.
@tparam string url The url to request
@tparam string body The body of the POST request.
@tparam[opt] { [string] = string } headers Additional headers to send as part
of this request.
@tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
the body will not be UTF-8 encoded, and the received response will not be
decoded.
@tparam[2] {
url = string, body? = string, headers? = { [string] = string },
binary? = boolean, method? = string, redirect? = boolean,
} request Options for the request. See @{http.request} for details on how
these options behave.
@treturn Response The resulting http response, which can be read from.
@treturn[2] nil When the http request failed, such as in the event of a 404
error or connection timeout.
@treturn string A message detailing why the request failed.
@treturn Response|nil The failing http response, if available.
@since 1.31
@changed 1.63 Added argument for headers.
@changed 1.80pr1 Response handles are now returned on error if available.
@changed 1.80pr1 Added argument for binary handles.
@changed 1.80pr1.6 Added support for table argument.
@changed 1.86.0 Added PATCH and TRACE methods.
]]
function post(_url, _post, _headers, _binary)
if type(_url) == "table" then
checkOptions(_url, true)
return wrapRequest(_url.url, _url)
end
expect(1, _url, "string")
expect(2, _post, "string")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
return wrapRequest(_url, _url, _post, _headers, _binary)
end
--[[- Asynchronously make a HTTP request to the given url.
This returns immediately, a @{http_success} or @{http_failure} will be queued
once the request has completed.
@tparam string url The url to request
@tparam[opt] string body An optional string containing the body of the
request. If specified, a `POST` request will be made instead.
@tparam[opt] { [string] = string } headers Additional headers to send as part
of this request.
@tparam[opt] boolean binary Whether to make a binary HTTP request. If true,
the body will not be UTF-8 encoded, and the received response will not be
decoded.
@tparam[2] {
url = string, body? = string, headers? = { [string] = string },
binary? = boolean, method? = string, redirect? = boolean,
} request Options for the request.
This table form is an expanded version of the previous syntax. All arguments
from above are passed in as fields instead (for instance,
`http.request("https://example.com")` becomes `http.request { url =
"https://example.com" }`).
This table also accepts several additional options:
- `method`: Which HTTP method to use, for instance `"PATCH"` or `"DELETE"`.
- `redirect`: Whether to follow HTTP redirects. Defaults to true.
@see http.get For a synchronous way to make GET requests.
@see http.post For a synchronous way to make POST requests.
@changed 1.63 Added argument for headers.
@changed 1.80pr1 Added argument for binary handles.
@changed 1.80pr1.6 Added support for table argument.
@changed 1.86.0 Added PATCH and TRACE methods.
]]
function request(_url, _post, _headers, _binary)
local url
if type(_url) == "table" then
checkOptions(_url)
url = _url.url
else
expect(1, _url, "string")
expect(2, _post, "string", "nil")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
url = _url.url
end
local ok, err = nativeHTTPRequest(_url, _post, _headers, _binary)
if not ok then
os.queueEvent("http_failure", url, err)
end
return ok, err
end
local nativeCheckURL = native.checkURL
--[[- Asynchronously determine whether a URL can be requested.
If this returns `true`, one should also listen for @{http_check} which will
container further information about whether the URL is allowed or not.
@tparam string url The URL to check.
@treturn true When this url is not invalid. This does not imply that it is
allowed - see the comment above.
@treturn[2] false When this url is invalid.
@treturn string A reason why this URL is not valid (for instance, if it is
malformed, or blocked).
@see http.checkURL For a synchronous version.
]]
checkURLAsync = nativeCheckURL
--[[- Determine whether a URL can be requested.
If this returns `true`, one should also listen for @{http_check} which will
container further information about whether the URL is allowed or not.
@tparam string url The URL to check.
@treturn true When this url is valid and can be requested via @{http.request}.
@treturn[2] false When this url is invalid.
@treturn string A reason why this URL is not valid (for instance, if it is
malformed, or blocked).
@see http.checkURLAsync For an asynchronous version.
@usage
```lua
print(http.checkURL("https://example.tweaked.cc/"))
-- => true
print(http.checkURL("http://localhost/"))
-- => false Domain not permitted
print(http.checkURL("not a url"))
-- => false URL malformed
```
]]
function checkURL(_url)
expect(1, _url, "string")
local ok, err = nativeCheckURL(_url)
if not ok then return ok, err end
while true do
local _, url, ok, err = os.pullEvent("http_check")
if url == _url then return ok, err end
end
end
local nativeWebsocket = native.websocket
--[[- Open a websocket.
@tparam string url The websocket url to connect to. This should have the
`ws://` or `wss://` protocol.
@tparam[opt] { [string] = string } headers Additional headers to send as part
of the initial websocket connection.
@treturn Websocket The websocket connection.
@treturn[2] false If the websocket connection failed.
@treturn string An error message describing why the connection failed.
@since 1.80pr1.1
@changed 1.80pr1.3 No longer asynchronous.
@changed 1.95.3 Added User-Agent to default headers.
]]
websocketAsync = nativeWebsocket
--[[- Asynchronously open a websocket.
This returns immediately, a @{websocket_success} or @{websocket_failure}
will be queued once the request has completed.
@tparam string url The websocket url to connect to. This should have the
`ws://` or `wss://` protocol.
@tparam[opt] { [string] = string } headers Additional headers to send as part
of the initial websocket connection.
@since 1.80pr1.3
@changed 1.95.3 Added User-Agent to default headers.
]]
function websocket(_url, _headers)
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
local ok, err = nativeWebsocket(_url, _headers)
if not ok then return ok, err end
while true do
local event, url, param = os.pullEvent( )
if event == "websocket_success" and url == _url then
return param
elseif event == "websocket_failure" and url == _url then
return false, param
end
end
end

View File

@ -6,7 +6,7 @@ end
--- The builtin turtle API, without any generated helper functions.
--
-- @deprecated Historically this table behaved differently to the main turtle API, but this is no longer the base. You
-- @deprecated Historically this table behaved differently to the main turtle API, but this is no longer the case. You
-- should not need to use it.
native = turtle.native or turtle

View File

@ -247,6 +247,7 @@ val lintLua by tasks.registering(IlluaminateExec::class) {
inputs.files(luaJavadoc)
args = listOf("lint")
workingDir = rootProject.projectDir
doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") }
doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") }