From d6a1493d52f6fd55093c3c584448028faae91ddd Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Wed, 22 Apr 2015 15:16:59 -0400 Subject: [PATCH] Fix build logs on Safari by having the client JS handle the redirect manually, rather than the browser itself; Safari doesn't support 302 redirects to another domain inside an XHR. --- endpoints/api/build.py | 6 ++- static/js/directives/ui/build-logs-view.js | 49 ++++++++++++++-------- static/js/pages/repo-build.js | 48 ++++++++++++++------- 3 files changed, 68 insertions(+), 35 deletions(-) diff --git a/endpoints/api/build.py b/endpoints/api/build.py index 2add3adc4..fcef923c5 100644 --- a/endpoints/api/build.py +++ b/endpoints/api/build.py @@ -288,9 +288,11 @@ class RepositoryBuildLogs(RepositoryParamResource): build.repository.namespace_user.username != namespace): raise NotFound() - # If the logs have been archived, just redirect to the completed archive + # If the logs have been archived, just return a URL of the completed archive if build.logs_archived: - return redirect(log_archive.get_file_url(build.uuid)) + return { + 'logs_url': log_archive.get_file_url(build.uuid) + } start = int(request.args.get('start', 0)) diff --git a/static/js/directives/ui/build-logs-view.js b/static/js/directives/ui/build-logs-view.js index bce65cd53..0bc9fb350 100644 --- a/static/js/directives/ui/build-logs-view.js +++ b/static/js/directives/ui/build-logs-view.js @@ -67,6 +67,28 @@ angular.module('quay').directive('buildLogsView', function () { return endIndex; }; + var handleLogsData = function(logsData, callback) { + // Process the logs we've received. + $scope.logStartIndex = processLogs(logsData['logs'], logsData['start'], logsData['total']); + + // If the build status is an error, open the last two log entries. + var currentBuild = $scope.currentBuild; + if (currentBuild['phase'] == 'error' && $scope.logEntries.length > 1) { + var openLogEntries = function(entry) { + if (entry.logs) { + entry.logs.setVisible(true); + } + }; + + openLogEntries($scope.logEntries[$scope.logEntries.length - 2]); + openLogEntries($scope.logEntries[$scope.logEntries.length - 1]); + } + + // If the build phase is an error or a complete, then we mark the channel + // as closed. + callback(currentBuild['phase'] != 'error' && currentBuild['phase'] != 'complete'); + } + var getBuildStatusAndLogs = function(build, callback) { var params = { 'repository': build.repository.namespace + '/' + build.repository.name, @@ -88,25 +110,18 @@ angular.module('quay').directive('buildLogsView', function () { }; ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) { - // Process the logs we've received. - $scope.logStartIndex = processLogs(resp['logs'], resp['start'], resp['total']); - - // If the build status is an error, open the last two log entries. - var currentBuild = $scope.currentBuild; - if (currentBuild['phase'] == 'error' && $scope.logEntries.length > 1) { - var openLogEntries = function(entry) { - if (entry.logs) { - entry.logs.setVisible(true); - } - }; - - openLogEntries($scope.logEntries[$scope.logEntries.length - 2]); - openLogEntries($scope.logEntries[$scope.logEntries.length - 1]); + // If we get a logs url back, then we need to make another XHR request to retrieve the + // data. + if (resp['logs_url']) { + $.ajax({ + url: resp['logs_url'], + }).done(function(r) { + handleLogsData(r, callback); + }); + return; } - // If the build phase is an error or a complete, then we mark the channel - // as closed. - callback(currentBuild['phase'] != 'error' && currentBuild['phase'] != 'complete'); + handleLogsData(resp, callback); }, function() { callback(false); }); diff --git a/static/js/pages/repo-build.js b/static/js/pages/repo-build.js index 3666b9270..e40613af3 100644 --- a/static/js/pages/repo-build.js +++ b/static/js/pages/repo-build.js @@ -186,6 +186,28 @@ return endIndex; }; + var handleLogsData = function(logsData, callback) { + // Process the logs we've received. + $scope.logStartIndex = processLogs(logsData['logs'], logsData['start'], logsData['total']); + + // If the build status is an error, open the last two log entries. + var currentBuild = $scope.currentBuild; + if (currentBuild['phase'] == 'error' && $scope.logEntries.length > 1) { + var openLogEntries = function(entry) { + if (entry.logs) { + entry.logs.setVisible(true); + } + }; + + openLogEntries($scope.logEntries[$scope.logEntries.length - 2]); + openLogEntries($scope.logEntries[$scope.logEntries.length - 1]); + } + + // If the build phase is an error or a complete, then we mark the channel + // as closed. + callback(currentBuild['phase'] != 'error' && currentBuild['phase'] != 'complete'); + }; + var getBuildStatusAndLogs = function(build, callback) { var params = { 'repository': namespace + '/' + name, @@ -217,24 +239,18 @@ ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) { if (build != $scope.currentBuild) { callback(false); return; } - // Process the logs we've received. - $scope.logStartIndex = processLogs(resp['logs'], resp['start'], resp['total']); - - // If the build status is an error, open the last two log entries. - if (currentBuild['phase'] == 'error' && $scope.logEntries.length > 1) { - var openLogEntries = function(entry) { - if (entry.logs) { - entry.logs.setVisible(true); - } - }; - - openLogEntries($scope.logEntries[$scope.logEntries.length - 2]); - openLogEntries($scope.logEntries[$scope.logEntries.length - 1]); + // If we get a logs url back, then we need to make another XHR request to retrieve the + // data. + if (resp['logs_url']) { + $.ajax({ + url: resp['logs_url'], + }).done(function(r) { + handleLogsData(r, callback); + }); + return; } - // If the build phase is an error or a complete, then we mark the channel - // as closed. - callback(currentBuild['phase'] != 'error' && currentBuild['phase'] != 'complete'); + handleLogsData(resp, callback); }, function() { callback(false); });