diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 661273c976..712b2444f7 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -275,6 +275,10 @@ module.exports = ProjectController = project_id = req.params.Project_id logger.log project_id:project_id, anonymous:anonymous, user_id:user_id, "loading editor" + # record failures to load the custom websocket + if req.query?.ws is 'fallback' + metrics.inc "load-editor-ws-fallback" + async.auto { project: (cb)-> ProjectGetter.getProject( diff --git a/services/web/public/src/ide.js b/services/web/public/src/ide.js index 60a227fa44..13ffe8ca36 100644 --- a/services/web/public/src/ide.js +++ b/services/web/public/src/ide.js @@ -185,7 +185,13 @@ define([ ide.validFileRegex = '^[^*/]*$' // Don't allow * and / - ide.wsUrl = window.sharelatex.wsUrl || null // websocket url (if defined) + let 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/public/src/ide/connection/ConnectionManager.js b/services/web/public/src/ide/connection/ConnectionManager.js index b952d4ff44..7f67f51797 100644 --- a/services/web/public/src/ide/connection/ConnectionManager.js +++ b/services/web/public/src/ide/connection/ConnectionManager.js @@ -103,6 +103,23 @@ define([], function() { } ) + // handle network-level websocket errors (e.g. failed dns lookups) + + this.ide.socket.on('error', err => { + sl_console.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 { + this.connected = false + return this.$scope.$apply(() => { + return (this.$scope.state.error = + "Unable to connect, please view the connection problems guide to fix the issue.") + }) + } + }) + // The "connect" event is the first event we get back. It only // indicates that the websocket is connected, we still need to // pass authentication to join a project.