Browse Source

Move syzoj-renderer to a child process

master
Menci 6 years ago
parent
commit
a03d305507
  1. 5
      app.js
  2. 8
      libs/highlight.js
  3. 33
      libs/markdown.js
  4. 32
      libs/renderer.js
  5. 61
      libs/rendererd.js
  6. 8
      utility.js

5
app.js

@ -58,6 +58,8 @@ global.syzoj = {
let winstonLib = require('./libs/winston'); let winstonLib = require('./libs/winston');
winstonLib.configureWinston(!syzoj.production); winstonLib.configureWinston(!syzoj.production);
this.utils = require('./utility');
// Set assets dir // Set assets dir
app.use(Express.static(__dirname + '/static', { maxAge: syzoj.production ? '1y' : 0 })); app.use(Express.static(__dirname + '/static', { maxAge: syzoj.production ? '1y' : 0 }));
@ -260,8 +262,7 @@ global.syzoj = {
res.locals.res = res; res.locals.res = res;
next(); next();
}); });
}, }
utils: require('./utility')
}; };
syzoj.run(); syzoj.run();

8
libs/highlight.js

@ -1,8 +0,0 @@
const { highlight } = require('syzoj-renderer');
const objectHash = require('object-hash');
module.exports = async (code, lang, cb) => {
highlight(code, lang, syzoj.redisCache, {
wrapper: null
}).then(cb);
}

33
libs/markdown.js

@ -1,33 +0,0 @@
const { markdown } = require('syzoj-renderer');
const XSS = require('xss');
const CSSFilter = require('cssfilter');
const xssWhiteList = Object.assign({}, require('xss/lib/default').whiteList);
delete xssWhiteList.audio;
delete xssWhiteList.video;
for (const tag in xssWhiteList) {
xssWhiteList[tag] = xssWhiteList[tag].concat(['style', 'class']);
}
const xss = new XSS.FilterXSS({
whiteList: xssWhiteList,
stripIgnoreTag: true,
onTagAttr: (tag, name, value, isWhiteAttr) => {
if (tag.toLowerCase() === 'img' && name.toLowerCase() === 'src' && value.startsWith('data:image/')) {
return name + '="' + XSS.escapeAttrValue(value) + '"';
}
}
});
function filter(html) {
html = xss.process(html);
if (html) {
html = `<div style="position: relative; overflow: hidden; ">${html}</div>`;
}
return html;
};
module.exports = (markdownCode, callback) => {
markdown(markdownCode, syzoj.redisCache, filter).then(callback);
};

32
libs/renderer.js

@ -0,0 +1,32 @@
const child_process = require('child_process');
const rendererd = child_process.fork(__dirname + '/rendererd', [syzoj.config.redis]);
const resolver = {};
let currentId = 0;
rendererd.on('message', msg => {
resolver[msg.id](msg.result);
delete resolver[msg.id];
});
exports.markdown = (markdownCode, callback) => {
resolver[++currentId] = callback;
rendererd.send({
id: currentId,
type: 'markdown',
source: markdownCode
});
}
exports.highlight = (code, lang, callback) => {
resolver[++currentId] = callback;
rendererd.send({
id: currentId,
type: 'highlight',
source: {
code,
lang
}
});
}

61
libs/rendererd.js

@ -0,0 +1,61 @@
const renderer = require('syzoj-renderer');
const XSS = require('xss');
const xssWhiteList = Object.assign({}, require('xss/lib/default').whiteList);
delete xssWhiteList.audio;
delete xssWhiteList.video;
for (const tag in xssWhiteList) {
xssWhiteList[tag] = xssWhiteList[tag].concat(['style', 'class']);
}
const xss = new XSS.FilterXSS({
whiteList: xssWhiteList,
stripIgnoreTag: true,
onTagAttr: (tag, name, value, isWhiteAttr) => {
if (tag.toLowerCase() === 'img' && name.toLowerCase() === 'src' && value.startsWith('data:image/')) {
return name + '="' + XSS.escapeAttrValue(value) + '"';
}
}
});
const Redis = require('redis');
const util = require('util');
const redis = Redis.createClient(process.argv[2]);
const redisCache = {
get: util.promisify(redis.get).bind(redis),
set: util.promisify(redis.set).bind(redis)
};
async function highlight(code, lang) {
return await renderer.highlight(code, lang, redisCache, {
wrapper: null
});
}
async function markdown(markdownCode) {
function filter(html) {
html = xss.process(html);
if (html) {
html = `<div style="position: relative; overflow: hidden; ">${html}</div>`;
}
return html;
};
return await renderer.markdown(markdownCode, redisCache, filter);
}
process.on('message', async msg => {
if (msg.type === 'markdown') {
process.send({
id: msg.id,
result: await markdown(msg.source)
});
} else if (msg.type === 'highlight') {
process.send({
id: msg.id,
result: await highlight(msg.source.code, msg.source.lang)
});
}
});
process.on('disconnect', () => process.exit());

8
utility.js

@ -19,7 +19,6 @@ let Promise = require('bluebird');
let path = require('path'); let path = require('path');
let fs = Promise.promisifyAll(require('fs-extra')); let fs = Promise.promisifyAll(require('fs-extra'));
let util = require('util'); let util = require('util');
let markdownRenderer = require('./libs/markdown');
let moment = require('moment'); let moment = require('moment');
let url = require('url'); let url = require('url');
let querystring = require('querystring'); let querystring = require('querystring');
@ -27,6 +26,7 @@ let gravatar = require('gravatar');
let filesize = require('file-size'); let filesize = require('file-size');
let AsyncLock = require('async-lock'); let AsyncLock = require('async-lock');
let JSDOM = require('jsdom').JSDOM; let JSDOM = require('jsdom').JSDOM;
let renderer = require('./libs/renderer');
module.exports = { module.exports = {
resolvePath(s) { resolvePath(s) {
@ -56,13 +56,13 @@ module.exports = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!keys) { if (!keys) {
if (!obj || !obj.trim()) resolve(""); if (!obj || !obj.trim()) resolve("");
else markdownRenderer(obj, s => { else renderer.markdown(obj, s => {
resolve(replaceUI(s)); resolve(replaceUI(s));
}); });
} else { } else {
let res = obj, cnt = keys.length; let res = obj, cnt = keys.length;
for (let key of keys) { for (let key of keys) {
markdownRenderer(res[key], (s) => { renderer.markdown(res[key], (s) => {
res[key] = replaceUI(s); res[key] = replaceUI(s);
if (!--cnt) resolve(res); if (!--cnt) resolve(res);
}); });
@ -133,7 +133,7 @@ module.exports = {
}, },
highlight(code, lang) { highlight(code, lang) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
require('./libs/highlight')(code, lang, res => { renderer.highlight(code, lang, res => {
resolve(res); resolve(res);
}); });
}); });

Loading…
Cancel
Save