Replace kiosk SignalR with polling — Azure App Service blocks anonymous hub handshakes
SignalR WebSocket and SSE both receive immediate 'Handshake was canceled' from the server-side hub context. The 15-second delay between negotiate and SSE connect reveals the handshake timer has expired before the transport opens — caused by Azure App Service's ingress proxy resetting anonymous long-lived connections. Replacement: /Kiosk/PollSession (anonymous GET, no-cache) queried every 3 seconds. Returns the most recent Active InPerson session created in the last 60 seconds. The kiosk navigates when hasSession=true. Status dot: gray->green on first success, yellow on network error, blue when navigating. Removed signalr.min.js from kiosk layout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
// Polls /Kiosk/PollSession every 3 seconds and navigates when staff triggers an intake.
|
||||
// SignalR was replaced with polling because Azure App Service's ingress proxy cancels
|
||||
// anonymous WebSocket and SSE handshakes before the SignalR protocol exchange completes.
|
||||
(function () {
|
||||
const el = document.getElementById("kiosk-welcome-root");
|
||||
if (!el) return;
|
||||
|
||||
const companyId = el.dataset.companyId;
|
||||
const dot = document.getElementById("kiosk-conn-dot");
|
||||
const label = document.getElementById("kiosk-conn-label");
|
||||
|
||||
@@ -13,51 +15,28 @@
|
||||
if (label) label.textContent = text;
|
||||
}
|
||||
|
||||
if (!companyId) {
|
||||
setStatus("#ef4444", "Not configured (no company ID)");
|
||||
console.error("KioskHub: data-company-id is empty — kiosk activation may be invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus("#94a3b8", "Connecting…");
|
||||
|
||||
// Skip WebSocket — anonymous WebSocket upgrades are blocked by the Azure App Service
|
||||
// ingress proxy before the SignalR handshake completes. Server-Sent Events and
|
||||
// long polling work fine for the low-frequency "StartIntake" push this hub needs.
|
||||
const connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl(`/hubs/kiosk?companyId=${companyId}`, {
|
||||
transport: signalR.HttpTransportType.ServerSentEvents | signalR.HttpTransportType.LongPolling
|
||||
})
|
||||
.withAutomaticReconnect([2000, 5000, 10000, 30000])
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
.build();
|
||||
let active = true;
|
||||
|
||||
connection.on("StartIntake", function (sessionToken) {
|
||||
setStatus("#2563eb", "Starting…");
|
||||
window.location.href = `/Kiosk/Intake/${sessionToken}/Contact`;
|
||||
});
|
||||
|
||||
async function startConnection() {
|
||||
async function poll() {
|
||||
if (!active) return;
|
||||
try {
|
||||
await connection.start();
|
||||
const res = await fetch("/Kiosk/PollSession", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error("HTTP " + res.status);
|
||||
const data = await res.json();
|
||||
setStatus("#16a34a", "Ready");
|
||||
console.info("KioskHub connected, group kiosk-" + companyId);
|
||||
} catch (err) {
|
||||
setStatus("#ef4444", "Connection failed — retrying…");
|
||||
console.warn("KioskHub connect failed, retrying in 10s…", err);
|
||||
setTimeout(startConnection, 10000);
|
||||
if (data.hasSession && data.sessionToken) {
|
||||
active = false;
|
||||
setStatus("#2563eb", "Starting…");
|
||||
window.location.href = `/Kiosk/Intake/${data.sessionToken}/Contact`;
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
setStatus("#f59e0b", "Connection issue — retrying…");
|
||||
}
|
||||
if (active) setTimeout(poll, 3000);
|
||||
}
|
||||
|
||||
startConnection();
|
||||
|
||||
connection.onreconnecting(() => setStatus("#f59e0b", "Reconnecting…"));
|
||||
connection.onreconnected(() => {
|
||||
setStatus("#16a34a", "Ready");
|
||||
console.info("KioskHub reconnected");
|
||||
});
|
||||
connection.onclose(() => {
|
||||
setStatus("#ef4444", "Disconnected — retrying…");
|
||||
setTimeout(startConnection, 10000);
|
||||
});
|
||||
setTimeout(poll, 500); // first poll quickly; subsequent every 3s
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user