From 6cdd59afe559e22e9540cc6579776673b14db9db Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Thu, 1 Feb 2024 11:37:16 +0000 Subject: [PATCH] Merge pull request #16808 from overleaf/jpa-wsUrl [web] move wsUrl into meta tag GitOrigin-RevId: c94638759b79b8090b8b3cfa81baa718a69839e1 --- services/web/app/views/layout-base.pug | 1 - .../web/app/views/project/editor/meta.pug | 1 + .../connection/connection-manager.ts | 32 +++++++++--- services/web/frontend/js/ide.js | 7 --- .../js/ide/connection/ConnectionManager.js | 51 +++++++------------ services/web/frontend/js/utils/meta.js | 2 +- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/services/web/app/views/layout-base.pug b/services/web/app/views/layout-base.pug index 44ed791df2..fe2e0f4113 100644 --- a/services/web/app/views/layout-base.pug +++ b/services/web/app/views/layout-base.pug @@ -41,7 +41,6 @@ html( meta(name="ol-usersEmail" content=getUserEmail()) meta(name="ol-sharelatex" data-type="json" content={ siteUrl: settings.siteUrl, - wsUrl, }) meta(name="ol-ab" data-type="json" content={}) meta(name="ol-user_id" content=getLoggedInUserId()) diff --git a/services/web/app/views/project/editor/meta.pug b/services/web/app/views/project/editor/meta.pug index c34ffcd635..3ca59df463 100644 --- a/services/web/app/views/project/editor/meta.pug +++ b/services/web/app/views/project/editor/meta.pug @@ -15,6 +15,7 @@ meta(name="ol-compilesUserContentDomain" content=settings.compilesUserContentDom //- enable doc hash checking for all projects //- used in public/js/libs/sharejs.js meta(name="ol-useShareJsHash" data-type="boolean" content=true) +meta(name="ol-wsUrl" data-type="string" content=wsUrl) meta(name="ol-wsRetryHandshake" data-type="json" content=settings.wsRetryHandshake) meta(name="ol-pdfjsVariant" content=pdfjsVariant) meta(name="ol-debugPdfDetach" data-type="boolean" content=debugPdfDetach) diff --git a/services/web/frontend/js/features/ide-react/connection/connection-manager.ts b/services/web/frontend/js/features/ide-react/connection/connection-manager.ts index 98a474f350..e46bfec803 100644 --- a/services/web/frontend/js/features/ide-react/connection/connection-manager.ts +++ b/services/web/frontend/js/features/ide-react/connection/connection-manager.ts @@ -57,7 +57,12 @@ export class ConnectionManager extends EventTarget { this.userIsLeavingPage = true }) - const socket = SocketIoShim.connect('', { + const parsedURL = new URL( + getMeta('ol-wsUrl') || '/socket.io', + window.origin + ) + const socket = SocketIoShim.connect(parsedURL.origin, { + resource: parsedURL.pathname.slice(1), 'auto connect': false, 'connect timeout': 30 * 1000, 'force new connection': true, @@ -70,6 +75,7 @@ export class ConnectionManager extends EventTarget { // bail out if socket.io failed to load (e.g. the real-time server is down) if (typeof window.io !== 'object') { + this.switchToWsFallbackIfPossible() debugConsole.error( 'Socket.io javascript not loaded. Please check that the real-time service is running and accessible.' ) @@ -118,6 +124,18 @@ export class ConnectionManager extends EventTarget { ) } + private switchToWsFallbackIfPossible() { + const search = new URLSearchParams(window.location.search) + if (getMeta('ol-wsUrl') && search.get('ws') !== 'fallback') { + // if we tried to boot from a custom real-time backend and failed, + // try reloading and falling back to the siteUrl + search.set('ws', 'fallback') + window.location.search = search.toString() + return true + } + return false + } + private onOnline() { if (!this.state.inactiveDisconnect) this.ensureIsConnected() } @@ -170,11 +188,13 @@ export class ConnectionManager extends EventTarget { CONNECTION_ERROR_RECONNECT_DELAY ) } else { - this.disconnect() - this.changeState({ - ...this.state, - error: 'unable-to-connect', - }) + if (!this.switchToWsFallbackIfPossible()) { + this.disconnect() + this.changeState({ + ...this.state, + error: 'unable-to-connect', + }) + } } } diff --git a/services/web/frontend/js/ide.js b/services/web/frontend/js/ide.js index ca938e7229..cb331cadd7 100644 --- a/services/web/frontend/js/ide.js +++ b/services/web/frontend/js/ide.js @@ -172,13 +172,6 @@ App.controller('IdeController', [ ide.validFileRegex = '^[^*/]*$' // Don't allow * and / - const useFallbackWebsocket = - window.location && - window.location.search && - window.location.search.match(/ws=fallback/) - // if we previously failed to load the websocket fall back to null (the siteUrl) - ide.wsUrl = useFallbackWebsocket ? null : window.sharelatex.wsUrl || null // websocket url (if defined) - ide.project_id = $scope.project_id = window.project_id ide.$scope = $scope diff --git a/services/web/frontend/js/ide/connection/ConnectionManager.js b/services/web/frontend/js/ide/connection/ConnectionManager.js index d21dc4e289..3505ce0af9 100644 --- a/services/web/frontend/js/ide/connection/ConnectionManager.js +++ b/services/web/frontend/js/ide/connection/ConnectionManager.js @@ -8,8 +8,6 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -/* global io */ - import SocketIoShim from './SocketIoShim' import getMeta from '../../utils/meta' import { debugConsole, debugging } from '@/utils/debugging' @@ -34,13 +32,8 @@ export default ConnectionManager = (function () { constructor(ide, $scope) { this.ide = ide this.$scope = $scope - this.wsUrl = ide.wsUrl || null // websocket url (if defined) - if (typeof io === 'undefined' || io === null) { - if (this.wsUrl && !window.location.href.match(/ws=fallback/)) { - // if we tried to boot from a custom real-time backend and failed, - // try reloading and falling back to the siteUrl - window.location = window.location.href + '?ws=fallback' - } + if (typeof window.io !== 'object') { + this.switchToWsFallbackIfPossible() debugConsole.error( 'Socket.io javascript not loaded. Please check that the real-time service is running and accessible.' ) @@ -110,24 +103,10 @@ export default ConnectionManager = (function () { // initial connection attempt this.updateConnectionManagerState('connecting') - let parsedURL - try { - parsedURL = new URL(this.wsUrl || '/socket.io', window.location) - } catch (e) { - // hello IE11 - if ( - this.wsUrl && - this.wsUrl.indexOf('/') !== 0 && - !window.location.href.match(/ws=fallback/) - ) { - // do not even try parsing the wsUrl, use the fallback - window.location = window.location.href + '?ws=fallback' - } - parsedURL = { - origin: null, - pathname: this.wsUrl || '/socket.io', - } - } + const parsedURL = new URL( + getMeta('ol-wsUrl') || '/socket.io', + window.origin + ) const query = new URLSearchParams({ projectId: getMeta('ol-project_id'), }).toString() @@ -155,11 +134,7 @@ export default ConnectionManager = (function () { } this.updateConnectionManagerState('error') debugConsole.log('socket.io error', err) - if (this.wsUrl && !window.location.href.match(/ws=fallback/)) { - // if we tried to load a custom websocket location and failed - // try reloading and falling back to the siteUrl - window.location = window.location.href + '?ws=fallback' - } else { + if (!this.switchToWsFallbackIfPossible()) { this.connected = false return this.$scope.$apply(() => { return (this.$scope.state.error = @@ -296,6 +271,18 @@ The editor will refresh automatically in ${delay} seconds.\ }) } + switchToWsFallbackIfPossible() { + const search = new URLSearchParams(window.location.search) + if (getMeta('ol-wsUrl') && search.get('ws') !== 'fallback') { + // if we tried to boot from a custom real-time backend and failed, + // try reloading and falling back to the siteUrl + search.set('ws', 'fallback') + window.location.search = search.toString() + return true + } + return false + } + updateConnectionManagerState(state) { this.$scope.$apply(() => { this.$scope.connection.jobId += 1 diff --git a/services/web/frontend/js/utils/meta.js b/services/web/frontend/js/utils/meta.js index f6908a0f75..e355560f2b 100644 --- a/services/web/frontend/js/utils/meta.js +++ b/services/web/frontend/js/utils/meta.js @@ -39,7 +39,7 @@ function convertMetaToWindowAttributes() { Array.from(document.querySelectorAll('meta[name^="ol-"]')) .map(element => element.name) // process short labels before long ones: - // e.g. assign 'sharelatex' before 'sharelatex.templates' + // e.g. assign 'foo' before 'foo.bar' .sort() .forEach(nameWithNamespace => { const label = nameWithNamespace.slice('ol-'.length)