HTML5 target: subprotocol/header quirks #8
Labels
No labels
area:defold
area:docs
area:infra
area:protocol
area:testing
kind:bug
kind:chore
phase:breadth
phase:core
phase:hardening
phase:slice
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
yuris/spacetimedb-defold#8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
extension-websocket ignores custom headers on HTML5, and subprotocol negotiation has historical bugs there. The SDK is broken on HTML5 until verified.
Resolved on the SDK side; HTML5 is blocked on an upstream extension bug
Both checkboxes are answered, and the full smoke client now passes in a real headless Chromium. Two distinct failures, not one.
1. Headers are unusable, and
?token=is the replacementConfirmed against a live
clockworklabs/spacetime:v2.8.2, four transports, same URL:?token=authenticates to the same identity as the header. Stuffing the token into the subprotocol (as some clients do) does not — it yields a fresh identity, so that trick is out.Why this mattered more than it looked: a dropped header does not fail. The connection succeeds as a brand new anonymous identity, so an HTML5 build silently loses the player's identity with no error anywhere.
connectnow picks the transport per platform — query parameter on HTML5,Authorizationheader everywhere else, since a token in a URL can land in server access logs.stdb.with_tokenis pure and unit-tested (test/test_init.lua).2. extension-websocket 4.2.3 drops the subprotocol on HTML5
With the token fixed, the handshake still failed:
A node probe pins the cause exactly — 400 appears only when no subprotocol is sent; Origin and permessage-deflate are irrelevant.
Root cause is in the extension,
websocket/src/websocket.cpp:CreateConnection()callsCreateConnectionEmscripten(conn)LuaConnect()then assignsconn->m_Protocol = strdup(protocol)The socket is opened before the protocol is recorded.
connwasmemsetto zero, soemscripten_websocket_newsees a nullprotocolspointer and the glue takes itsnew WebSocket(url)branch:Native builds are unaffected — wslay writes the handshake later, from the update loop, when
m_Protocolis set. There is no Lua-side workaround: SpacetimeDB requires a subprotocol.Six-line fix (move socket creation to the end of
LuaConnect) is committed aspatches/extension-websocket-html5-subprotocol.patch. Verified by vendoring a patched copy and rebuilding:The identity matches the supplied token, so
?token=re-auth works on reconnect too.New: HTML5 conformance harness
tools/html5-conformance.sh+tools/html5-conformance.mjs— builds awasm-webbundle, serves it, drives Chromium over CDP, and reads the verdict off the console. Dependency-free (node's own globalWebSockettalks to devtools). It reports handshake request/response lines, which is what made this bug findable at all.Three environment traps it encodes, each a wasted run otherwise:
--variant releasestripsprint, so the verdict never reaches the console. Must bedebug._glGetStringbefore any script runs. Chromium 150+ requires--enable-unsafe-swiftshader, and--disable-gpuremoves the context entirely.Runtime/Logare silently no-ops.Remaining
Everything left is upstream or CI, tracked separately. The SDK code for HTML5 is done and proven.
Closing: all three checkboxes are answered with evidence, and the remaining work is not SDK code.
v1.json.spacetimedbnegotiate on HTML5? No — extension-websocket 4.2.3 never sends the subprotocol. Root-caused to a socket-creation ordering bug, patched, verified. Upstreaming tracked in #15.?token=authenticates to the same identity as the header, andconnectnow uses it on HTML5 only.tools/html5-conformance.shruns the same smoke client as native conformance in headless Chromium; it passes all four phases with the patched extension.Follow-ups: #15 (upstream the fix), #16 (this tier in CI), #17 (identity persistence, which
sys.saveon IDBFS makes genuinely doubtful).