1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-16 10:09:55 +00:00

A couple of fixes to the HTTP API

- Flip http.websocket and http.websocketAsync docs (fixes #1244)

 - Fix http.request queuing a http_failure event with no URL when
   passing a malformed URL

 - Fix http.websocketAsync not queuing websocket_failure events on
   immediate failure.
This commit is contained in:
Jonathan Coates 2022-12-07 21:14:33 +00:00
parent 9962ce1a5c
commit 3b42f22a4f
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
3 changed files with 72 additions and 15 deletions

View File

@ -193,13 +193,15 @@ function request(_url, _post, _headers, _binary)
expect(2, _post, "string", "nil")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
url = _url.url
url = _url
end
local ok, err = nativeHTTPRequest(_url, _post, _headers, _binary)
if not ok then
os.queueEvent("http_failure", url, err)
end
-- Return true/false for legacy reasons. Undocumented, as it shouldn't be relied on.
return ok, err
end
@ -257,6 +259,32 @@ end
local nativeWebsocket = native.websocket
--[[- 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)
expect(1, url, "string")
expect(2, headers, "table", "nil")
local ok, err = nativeWebsocket(url, headers)
if not ok then
os.queueEvent("websocket_failure", url, err)
end
-- Return true/false for legacy reasons. Undocumented, as it shouldn't be relied on.
return ok, err
end
--[[- Open a websocket.
@tparam string url The websocket url to connect to. This should have the
@ -271,20 +299,6 @@ of the initial websocket connection.
@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")

View File

@ -1,3 +1,5 @@
local timeout = require "test_helpers".timeout
describe("The http library", function()
describe("http.checkURL", function()
it("accepts well formed domains", function()
@ -18,4 +20,28 @@ describe("The http library", function()
expect({ http.checkURL("http://127.0.0.1") }):same({ false, "Domain not permitted" })
end)
end)
describe("http.websocketAsync", function()
it("queues an event for immediate failures", function()
timeout(1, function()
local url = "http://not.a.websocket"
http.websocketAsync(url)
local _, url2, message = os.pullEvent("websocket_failure")
expect(url2):eq(url)
expect(message):eq("Invalid scheme 'http'")
end)
end)
end)
describe("http.requestAsync", function()
it("queues an event for immediate failures", function()
timeout(1, function()
local url = "ws://not.a.request"
http.request(url)
local _, url2, message = os.pullEvent("http_failure")
expect(url2):eq(url)
expect(message):eq("Invalid protocol 'ws'")
end)
end)
end)
end)

View File

@ -70,8 +70,25 @@ local function with_window_lines(width, height, fn)
return out
end
local function timeout(time, fn)
local timer = os.startTimer(time)
local co = coroutine.create(fn)
local ok, result, event = true, nil, { n = 0 }
while coroutine.status(co) ~= "dead" do
if event[1] == "timer" and event[2] == timer then error("Timeout", 2) end
if result == nil or event[1] == result or event[1] == "terminated" then
ok, result = coroutine.resume(co, table.unpack(event, 1, event.n))
if not ok then error(result, 0) end
end
event = table.pack(coroutine.yield())
end
end
return {
capture_program = capture_program,
with_window = with_window,
with_window_lines = with_window_lines,
timeout = timeout,
}