diff --git a/mathoid/engine.js b/mathoid/engine.js index 4320c43..09dd4ea 100644 --- a/mathoid/engine.js +++ b/mathoid/engine.js @@ -57,7 +57,7 @@ window.engine = (new (function() { // displayed like an image on some different page. this.merge = function(svg) { var uses, - copied, + copied = {}, k, id, texts, @@ -69,19 +69,18 @@ window.engine = (new (function() { // clone and copy all used paths into local defs. // xlink:href in uses FIX uses = svg.getElementsByTagName('use'); - copied = {}; for ( k = 0; k < uses.length; ++k) { id = uses[k].getAttribute('href'); - if (id && copied[id]) { - uses[k].setAttribute('xlink:href', id); - // Already copied, skip - continue; - } + if (id && copied[id]) { + uses[k].setAttribute('xlink:href', id); + // Already copied, skip + continue; + } defs.appendChild( - document.getElementById(id.substr(1)).cloneNode(true) - ); + document.getElementById(id.substr(1)).cloneNode(true) + ); uses[k].setAttribute('xlink:href', id); - copied[id] = true; + copied[id] = true; } // check for errors in svg. @@ -94,6 +93,7 @@ window.engine = (new (function() { svg.style.position = 'static'; tmpDiv = document.createElement('div'); + tmpDiv.appendChild(defs); tmpDiv.appendChild(svg); return tmpDiv.innerHTML; }; @@ -125,7 +125,7 @@ window.engine = (new (function() { }); })); } catch (err) { - cb([latex, err.message, '-']); + cb([latex, err, err]); } } }; diff --git a/mathoid/main.js b/mathoid/main.js index 6eba979..e9b3222 100644 --- a/mathoid/main.js +++ b/mathoid/main.js @@ -39,7 +39,8 @@ page.onCallback = function(data) { data[0].length + 'B query, ERR ' + data[1][0] + t; out = JSON.stringify({err:data[1][0],svg:data[1],mml:data[2],'log':log,'sucess':false}); resp.write(out); - //console.log(log); + console.log(log); + phantom.exit(1); } resp.close(); }; diff --git a/mathoid/mathoid-worker.js b/mathoid/mathoid-worker.js index dfedb3b..dc5fcb2 100644 --- a/mathoid/mathoid-worker.js +++ b/mathoid/mathoid-worker.js @@ -10,6 +10,7 @@ var express = require('express'), http = require('http'), fs = require('fs'), child_process = require('child_process'), + request = require('request'), querystring = require('querystring'); var config; @@ -40,28 +41,32 @@ console.log( ' - ' + instanceName + ' loading...' ); var restarts = 10; var backend, + backendStarting = false, backendPort, requestQueue = []; -var startBackend = function () { +// forward declaration +var handleRequests; + +var backendCB = function () { + backendStarting = false; + handleRequests(); +}; + +var startBackend = function (cb) { if (backend) { - backend.kill(); + backend.removeAllListeners(); + backend.kill('SIGKILL'); } - var backendCB = function (err, stdout, stderr) { - if (err) { - restarts--; - if (restarts > 0) { - startBackend(); - } - console.error(err.toString()); - process.exit(1); - } - }; backendPort = Math.floor(9000 + Math.random() * 50000); console.error(instanceName + ': Starting backend on port ' + backendPort); - backend = child_process.exec('phantomjs main.js ' + backendPort, backendCB); - backend.stdout.pipe(process.stdout); + backend = child_process.spawn('phantomjs', ['main.js', backendPort]); + backend.stdout.pipe(process.stderr); backend.stderr.pipe(process.stderr); + backend.on('close', startBackend); + backendStarting = true; + // give backend 1 seconds to start up + setTimeout(backendCB, 1000); }; startBackend(); @@ -86,57 +91,67 @@ app.get(/^\/robots.txt$/, function ( req, res ) { res.end( "User-agent: *\nDisallow: /\n" ); }); -var handleRequests = function() { - // Call the next request on the queue - if (requestQueue.length) { - requestQueue[0](); - } -}; function handleRequest(req, res, tex) { // do the backend request - var query = new Buffer(querystring.stringify({tex:tex})), + var reqbody = new Buffer(querystring.stringify({tex: tex})), options = { - hostname: 'localhost', - port: backendPort.toString(), - path: '/', - method: 'POST', - headers: { - 'Content-Length': query.length, - 'Content-Type': 'application/x-www-form-urlencoded', - 'Connection': 'close' - }, - agent: false - }; - var chunks = []; - //console.log(options); - var httpreq = http.request(options, function(httpres) { - httpres.on('data', function(chunk) { - chunks.push(chunk); - }); - httpres.on('end', function() { - var buf = Buffer.concat(chunks); - res.writeHead(200, - { - 'Content-type': 'application/json', - 'Content-length': buf.length - }); - res.write(buf); - res.end(); + method: 'POST', + uri: 'http://localhost:' + backendPort.toString() + '/', + body: reqbody, + // Work around https://github.com/ariya/phantomjs/issues/11421 by + // setting explicit upper-case headers (request sends them lowercase + // by default) and manually encoding the body. + headers: { + 'Content-Length': reqbody.length, + 'Content-Type': 'application/x-www-form-urlencoded' + }, + timeout: 2000 + }; + request(options, function (err, response, body) { + body = new Buffer(body); + if (err || response.statusCode !== 200) { + var errBuf; + if (err) { + errBuf = new Buffer(JSON.stringify({ + tex: tex, + log: err.toString(), + success: false + })); + } else { + errBuf = body; + } + res.writeHead(500, + { + 'Content-Type': 'application/json', + 'Content-Length': errBuf.length + }); + res.end(errBuf); + // don't retry the request requestQueue.shift(); - handleRequests(); - }); + startBackend(); + return handleRequests(); + } + res.writeHead(200, + { + 'Content-Type': 'application/json', + 'Content-length': body.length + }); + res.end(body); + requestQueue.shift(); + handleRequests(); }); - httpreq.on('error', function(err) { - console.log('error', err.toString()); - res.writeHead(500); - return res.end(JSON.stringify({error: "Backend error: " + err.toString()})); - }); - - httpreq.end(query); } +handleRequests = function() { + // Call the next request on the queue + if (!backendStarting && requestQueue.length) { + requestQueue[0](); + } +}; + + app.post(/^\/$/, function ( req, res ) { // First some rudimentary input validation if (!req.body.tex) { diff --git a/mathoid/package.json b/mathoid/package.json index cf630b5..fc697a0 100644 --- a/mathoid/package.json +++ b/mathoid/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "dependencies": { "querystring": "0.x.x", - "express": "2.5.x" + "express": "2.5.x", + "request": "2.x.x" } }