Fix WebSocket reconnect: refused upgrades are 1006 not 1008, back off, prompt once
This commit is contained in:
parent
1f1544bab1
commit
821f0a0a8f
1 changed files with 21 additions and 5 deletions
|
|
@ -5,9 +5,17 @@ const { createApp, ref, computed, watch, onMounted, onUnmounted } = Vue;
|
|||
const TOKEN_KEY = 'chart-token';
|
||||
let authToken = localStorage.getItem(TOKEN_KEY) || '';
|
||||
|
||||
// Reconnects and the status poll both hit 401s, so without this a visitor
|
||||
// who cancels gets asked again every couple of seconds.
|
||||
let promptDeclined = false;
|
||||
|
||||
function promptForToken() {
|
||||
if (promptDeclined) return false;
|
||||
const entered = window.prompt('Access token for this chart', '');
|
||||
if (entered === null) return false;
|
||||
if (entered === null) {
|
||||
promptDeclined = true;
|
||||
return false;
|
||||
}
|
||||
authToken = entered.trim();
|
||||
localStorage.setItem(TOKEN_KEY, authToken);
|
||||
return true;
|
||||
|
|
@ -55,6 +63,7 @@ createApp({
|
|||
const now = ref(Date.now());
|
||||
let chartApi = null;
|
||||
let socket = null;
|
||||
let retryDelay = 2000;
|
||||
let timer = null;
|
||||
|
||||
const barAge = computed(() => {
|
||||
|
|
@ -76,6 +85,7 @@ createApp({
|
|||
const query = authToken ? `?token=${encodeURIComponent(authToken)}` : '';
|
||||
socket = new WebSocket(`${protocol}://${location.host}/ws${query}`);
|
||||
socket.onopen = () => {
|
||||
retryDelay = 2000;
|
||||
socket.send(JSON.stringify({ type: 'subscribe', tf: timeframe.value }));
|
||||
sendPrefs();
|
||||
};
|
||||
|
|
@ -102,11 +112,17 @@ createApp({
|
|||
playAlert();
|
||||
}
|
||||
};
|
||||
socket.onclose = event => {
|
||||
socket.onclose = async () => {
|
||||
status.value.stream = 'disconnected';
|
||||
// 1008 is the server rejecting our token; ask once, then reconnect.
|
||||
if (event.code === 1008 && !promptForToken()) return;
|
||||
setTimeout(connect, 2000);
|
||||
// A refused upgrade reaches the browser as 1006, not 1008: the server
|
||||
// rejects the handshake with HTTP 403 before any close frame exists.
|
||||
// So the close code cannot distinguish "bad token" from "server
|
||||
// restarting". Re-check over HTTP instead — apiFetch prompts for a
|
||||
// token when that is what is actually wrong — and back off so a
|
||||
// visitor without one is not reconnecting twice a second forever.
|
||||
await refreshStatus();
|
||||
retryDelay = Math.min(retryDelay * 2, 30000);
|
||||
setTimeout(connect, retryDelay);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue