This commit is contained in:
Matt Van Horn 2026-10-06 01:20:58 -04:00 • committed by GitHub
commit a7558accdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 1 deletions

View file

@ -90,8 +90,49 @@ local function rejectWrongPlaceId(infoResponseBody)
return Promise.resolve(infoResponseBody) return Promise.resolve(infoResponseBody)
end end
local LOST_CONNECTION_MESSAGE = "Lost connection to the Rojo server. Make sure `rojo serve` is still running."
local LOST_CONNECTION_ERRORS = {
{
code = 400,
messagePatterns = {
"failed ws recv",
"failure when receiving data from the peer",
"connection reset",
},
},
}
local function matchesWebSocketError(errorInfo, code, message)
if errorInfo.code ~= nil and tostring(errorInfo.code) ~= tostring(code) then
return false
end
for _, pattern in ipairs(errorInfo.messagePatterns) do
if string.find(message, pattern, 1, true) ~= nil then
return true
end
end
return false
end
local function formatWebSocketError(code, msg)
local message = if msg == nil then "" else tostring(msg)
local normalizedMessage = string.lower(message)
for _, errorInfo in ipairs(LOST_CONNECTION_ERRORS) do
if matchesWebSocketError(errorInfo, code, normalizedMessage) then
return LOST_CONNECTION_MESSAGE
end
end
return ("WebSocket error: %s - %s"):format(tostring(code), message)
end
local ApiContext = {} local ApiContext = {}
ApiContext.__index = ApiContext ApiContext.__index = ApiContext
ApiContext.__formatWebSocketError = formatWebSocketError
function ApiContext.new(baseUrl) function ApiContext.new(baseUrl)
assert(type(baseUrl) == "string", "baseUrl must be a string") assert(type(baseUrl) == "string", "baseUrl must be a string")
@ -275,7 +316,7 @@ function ApiContext:connectWebSocket(packetHandlers)
errored:Disconnect() errored:Disconnect()
received:Disconnect() received:Disconnect()
reject("WebSocket error: " .. code .. " - " .. msg) reject(formatWebSocketError(code, msg))
end) end)
end) end)
end end

View file

@ -0,0 +1,42 @@
return function()
local ApiContext = require(script.Parent.ApiContext)
local formatWebSocketError = ApiContext.__formatWebSocketError
local lostConnectionMessage = "Lost connection to the Rojo server. Make sure `rojo serve` is still running."
describe("__formatWebSocketError", function()
it("should return a friendly message for failed WebSocket receives", function()
local message = 'Failed ws recv - err: 0 "No error", curlErrBuf: ""'
expect(formatWebSocketError(400, message)).to.equal(lostConnectionMessage)
end)
it("should return a friendly message for peer receive failures", function()
local message = 'err: 56 "Failure when receiving data from the peer"'
expect(formatWebSocketError(400, message)).to.equal(lostConnectionMessage)
end)
it("should return a friendly message for connection resets", function()
local message = 'Failed ws recv - err: 54 "Connection reset by peer", curlErrBuf: ""'
expect(formatWebSocketError(400, message)).to.equal(lostConnectionMessage)
end)
it("should preserve unexpected WebSocket errors", function()
expect(formatWebSocketError(500, "Something else failed")).to.equal(
"WebSocket error: 500 - Something else failed"
)
end)
it("should handle empty or missing messages", function()
expect(formatWebSocketError(500, "")).to.equal("WebSocket error: 500 - ")
expect(formatWebSocketError(500, nil)).to.equal("WebSocket error: 500 - ")
end)
it("should always return a string", function()
expect(typeof(formatWebSocketError(400, "connection reset by peer"))).to.equal("string")
expect(typeof(formatWebSocketError(500, nil))).to.equal("string")
end)
end)
end