Fix SVG glyphs and make the service more robust

Change-Id: I14d3ca2fdc89f8662b2e823b6c891c79db5bab5a
This commit is contained in:
Gabriel Wicke 2013-10-08 17:30:54 -07:00
parent fd8da050fb
commit 6c7f4e3b38
4 changed files with 86 additions and 69 deletions

View File

@ -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]);
}
}
};

View File

@ -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();
};

View File

@ -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) {

View File

@ -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"
}
}