diff --git a/services/web/app/coffee/Features/Compile/CompileController.coffee b/services/web/app/coffee/Features/Compile/CompileController.coffee index 054c6f5aaf..b95a8ed82c 100755 --- a/services/web/app/coffee/Features/Compile/CompileController.coffee +++ b/services/web/app/coffee/Features/Compile/CompileController.coffee @@ -25,12 +25,13 @@ module.exports = CompileController = if req.body?.compiler options.compiler = req.body.compiler logger.log {options, project_id}, "got compile request" - CompileManager.compile project_id, user_id, options, (error, status, outputFiles) -> + CompileManager.compile project_id, user_id, options, (error, status, outputFiles, output, limits) -> return next(error) if error? res.contentType("application/json") res.send 200, JSON.stringify { status: status outputFiles: outputFiles + compileGroup: limits?.compileGroup } downloadPdf: (req, res, next = (error) ->)-> @@ -69,18 +70,30 @@ module.exports = CompileController = CompileController.proxyToClsi(req.params.Project_id, req.url, req, res, next) proxyToClsi: (project_id, url, req, res, next = (error) ->) -> - CompileManager.getProjectCompileLimits project_id, (error, limits) -> - return next(error) if error? - if limits.compileGroup == "priority" - compilerUrl = Settings.apis.clsi_priority.url - else - compilerUrl = Settings.apis.clsi.url - url = "#{compilerUrl}#{url}" - logger.log url: url, "proxying to CLSI" - oneMinute = 60 * 1000 - proxy = request(url: url, method: req.method, timeout: oneMinute) - proxy.pipe(res) - proxy.on "error", (error) -> - logger.warn err: error, url: url, "CLSI proxy error" + if req.query?.compileGroup + CompileController.proxyToClsiWithLimits(project_id, url, {compileGroup: req.query.compileGroup}, req, res, next) + else + CompileManager.getProjectCompileLimits project_id, (error, limits) -> + return next(error) if error? + CompileController.proxyToClsiWithLimits(project_id, url, limits, req, res, next) - + proxyToClsiWithLimits: (project_id, url, limits, req, res, next = (error) ->) -> + if limits.compileGroup == "priority" + compilerUrl = Settings.apis.clsi_priority.url + else + compilerUrl = Settings.apis.clsi.url + url = "#{compilerUrl}#{url}" + logger.log url: url, "proxying to CLSI" + oneMinute = 60 * 1000 + # pass through If-* and Range headers for byte serving pdfs + # do not send any others, potential proxying loop if Host: is passed! + if req.query?.pdfng + newHeaders = {} + for h, v of req.headers + newHeaders[h] = req.headers[h] if h.match /^(If-|Range)/i + proxy = request(url: url, method: req.method, timeout: oneMinute, headers: newHeaders) + else + proxy = request(url: url, method: req.method, timeout: oneMinute) + proxy.pipe(res) + proxy.on "error", (error) -> + logger.warn err: error, url: url, "CLSI proxy error" diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index d35322077b..0089eb7b34 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -39,7 +39,7 @@ module.exports = CompileManager = ClsiManager.sendRequest project_id, options, (error, status, outputFiles, output) -> return callback(error) if error? logger.log files: outputFiles, "output files" - callback(null, status, outputFiles, output) + callback(null, status, outputFiles, output, limits) deleteAuxFiles: (project_id, callback = (error) ->) -> CompileManager.getProjectCompileLimits project_id, (error, limits) -> diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index ee898dd8f7..610009bf8c 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -38,7 +38,12 @@ define [ $scope.pdf.failure = true fetchLogs() else if response.status == "success" - $scope.pdf.url = "/project/#{$scope.project_id}/output/output.pdf?cache_bust=#{Date.now()}" + if response.compileGroup? + $scope.pdf.compileGroup = response.compileGroup + $scope.pdf.url = "/project/#{$scope.project_id}/output/output.pdf?cache_bust=#{Date.now()}" + + "&compileGroup=#{$scope.pdf.compileGroup}" + else + $scope.pdf.url = "/project/#{$scope.project_id}/output/output.pdf?cache_bust=#{Date.now()}" fetchLogs() IGNORE_FILES = ["output.fls", "output.fdb_latexmk"] diff --git a/services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee b/services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee index c9c696d087..7f3ac48250 100644 --- a/services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee +++ b/services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee @@ -26,7 +26,8 @@ define [ $scope.document.destroy() if $scope.document? - $scope.document = new PDFRenderer($scope.pdfSrc, { + # TODO need a proper url manipulation library to add to query string + $scope.document = new PDFRenderer($scope.pdfSrc + '&pdfng=true' , { scale: 1, navigateFn: (ref) -> # this function captures clicks on the annotation links diff --git a/services/web/test/UnitTests/coffee/Compile/CompileControllerTests.coffee b/services/web/test/UnitTests/coffee/Compile/CompileControllerTests.coffee index e2cbec4cb8..fae9dec23f 100644 --- a/services/web/test/UnitTests/coffee/Compile/CompileControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/CompileControllerTests.coffee @@ -137,46 +137,149 @@ describe "CompileController", -> statusCode: 204 headers: { "mock": "header" } @req.method = "mock-method" + @req.headers = { + 'Mock': 'Headers', + 'Range': '123-456' + 'If-Range': 'abcdef' + 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT' + } + + describe "old pdf viewer", -> + describe "user with standard priority", -> + beforeEach -> + @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "standard"}) + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + + it "should open a request to the CLSI", -> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi.url}#{@url}", + timeout: 60 * 1000 + ) + .should.equal true + + it "should pass the request on to the client", -> + @proxy.pipe + .calledWith(@res) + .should.equal true + + it "should bind an error handle to the request proxy", -> + @proxy.on.calledWith("error").should.equal true + + describe "user with priority compile", -> + beforeEach -> + @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "priority"}) + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + + it "should proxy to the priority url if the user has the feature", ()-> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi_priority.url}#{@url}", + timeout: 60 * 1000 + ) + .should.equal true + + describe "user with standard priority via query string", -> + beforeEach -> + @req.query = {compileGroup: 'standard'} + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + + it "should open a request to the CLSI", -> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi.url}#{@url}", + timeout: 60 * 1000 + ) + .should.equal true + + it "should pass the request on to the client", -> + @proxy.pipe + .calledWith(@res) + .should.equal true + + it "should bind an error handle to the request proxy", -> + @proxy.on.calledWith("error").should.equal true + + describe "user with priority compile via query string", -> + beforeEach -> + @req.query = {compileGroup: 'priority'} + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + + it "should proxy to the priority url if the user has the feature", ()-> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi_priority.url}#{@url}", + timeout: 60 * 1000 + ) + .should.equal true + + describe "user with non-existent priority via query string", -> + beforeEach -> + @req.query = {compileGroup: 'foobar'} + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + + it "should proxy to the standard url", ()-> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi.url}#{@url}", + timeout: 60 * 1000 + ) + .should.equal true - describe "user with standard priority", -> - + describe "new pdf viewer", -> beforeEach -> - @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "standard"}) - @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + @req.query = {pdfng: true} + describe "user with standard priority", -> + beforeEach -> + @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "standard"}) + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) + it "should open a request to the CLSI", -> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi.url}#{@url}", + timeout: 60 * 1000 + headers: { + 'Range': '123-456' + 'If-Range': 'abcdef' + 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT' + } + ) + .should.equal true - it "should open a request to the CLSI", -> - @request - .calledWith( - method: @req.method - url: "#{@settings.apis.clsi.url}#{@url}", - timeout: 60 * 1000 - ) - .should.equal true + it "should pass the request on to the client", -> + @proxy.pipe + .calledWith(@res) + .should.equal true - it "should pass the request on to the client", -> - @proxy.pipe - .calledWith(@res) - .should.equal true + it "should bind an error handle to the request proxy", -> + @proxy.on.calledWith("error").should.equal true - it "should bind an error handle to the request proxy", -> - @proxy.on.calledWith("error").should.equal true + describe "user with priority compile", -> + beforeEach -> + @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "priority"}) + @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) - describe "user with priority compile", -> - - beforeEach -> - @CompileManager.getProjectCompileLimits = sinon.stub().callsArgWith(1, null, {compileGroup: "priority"}) - @CompileController.proxyToClsi(@project_id, @url = "/test", @req, @res, @next) - - it "should proxy to the priorty url if the user has the feature", ()-> - @request - .calledWith( - method: @req.method - url: "#{@settings.apis.clsi_priority.url}#{@url}", - timeout: 60 * 1000 - ) - .should.equal true + it "should proxy to the priority url if the user has the feature", ()-> + @request + .calledWith( + method: @req.method + url: "#{@settings.apis.clsi_priority.url}#{@url}", + timeout: 60 * 1000 + headers: { + 'Range': '123-456' + 'If-Range': 'abcdef' + 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT' + } + ) + .should.equal true describe "deleteAuxFiles", ->