var spawn = require('child_process').spawn; var fs = require('fs'); var path = require('path'); var os = require('os'); var request = require('request'); function waitForJavaScript() { if(window.MathJax) { // Amazon EC2: fix TeX font detection MathJax.Hub.Register.StartupHook("HTML-CSS Jax Startup",function () { var HTMLCSS = MathJax.OutputJax["HTML-CSS"]; HTMLCSS.Font.checkWebFont = function (check,font,callback) { if (check.time(callback)) { return; } if (check.total === 0) { HTMLCSS.Font.testFont(font); setTimeout(check,200); } else { callback(check.STATUS.OK); } }; }); MathJax.Hub.Queue(function () { window.status = 'done'; }); } else { setTimeout(function() { window.status = 'done'; }, 2000); } } var authorizedPageSizes = [ 'A3', 'A4', 'Legal', 'Letter' ]; exports.export = function(req, res, next) { function onError(err) { next(err); } function onUnknownError() { res.statusCode = 400; res.end('Unknown error'); } function onUnauthorizedError() { res.statusCode = 401; res.end('Unauthorized'); } function onTimeout() { res.statusCode = 408; res.end('Request timeout'); } request({ uri: 'https://monetizejs.com/api/payments', qs: { access_token: req.query.token }, json: true }, function (err, paymentsRes, payments) { var authorized = payments && payments.app == 'ESTHdCYOi18iLhhO' && ( (payments.chargeOption && payments.chargeOption.alias == 'once') || (payments.subscriptionOption && payments.subscriptionOption.alias == 'yearly')); if(err || paymentsRes.statusCode != 200 || !authorized) { return onUnauthorizedError(); } var options, params = []; try { options = JSON.parse(req.query.options); } catch(e) { options = {}; } // Margins var marginTop = parseInt(options.marginTop); params.push('-T', isNaN(marginTop) ? 25 : marginTop); var marginRight = parseInt(options.marginRight); params.push('-R', isNaN(marginRight) ? 25 : marginRight); var marginBottom = parseInt(options.marginBottom); params.push('-B', isNaN(marginBottom) ? 25 : marginBottom); var marginLeft = parseInt(options.marginLeft); params.push('-L', isNaN(marginLeft) ? 25 : marginLeft); // Header options.headerCenter && params.push('--header-center', options.headerCenter); options.headerLeft && params.push('--header-left', options.headerLeft); options.headerRight && params.push('--header-left', options.headerRight); options.headerFontName && params.push('--header-font-name ', options.headerFontName); options.headerFontSize && params.push('--header-font-size ', options.headerFontSize); // Footer options.footerCenter && params.push('--footer-center', options.footerCenter); options.footerLeft && params.push('--footer-left', options.footerLeft); options.footerRight && params.push('--footer-left', options.footerRight); options.footerFontName && params.push('--footer-font-name ', options.footerFontName); options.footerFontSize && params.push('--footer-font-size ', options.footerFontSize); // Page size params.push('--page-size', authorizedPageSizes.indexOf(options.pageSize) === -1 ? 'A4' : options.pageSize); // Use a temp file as wkhtmltopdf can't access /dev/stdout on Amazon EC2 for some reason var filePath = path.join(os.tmpDir(), Date.now() + '.pdf'); var binPath = process.env.WKHTMLTOPDF_PATH || 'wkhtmltopdf'; params.push('--run-script', waitForJavaScript.toString() + 'waitForJavaScript()'); params.push('--window-status', 'done'); var wkhtmltopdf = spawn(binPath, params.concat('-', filePath), { stdio: [ 'pipe', 'ignore', 'ignore' ] }); var timeoutId = setTimeout(function() { timeoutId = undefined; wkhtmltopdf.kill(); }, 30000); wkhtmltopdf.on('error', onError); wkhtmltopdf.stdin.on('error', onError); wkhtmltopdf.on('close', function(code) { if(!timeoutId) { return onTimeout(); } clearTimeout(timeoutId); if(code) { return onUnknownError(); } var readStream = fs.createReadStream(filePath); readStream.on('open', function() { readStream.pipe(res); }); readStream.on('close', function() { fs.unlink(filePath, function() { }); }); readStream.on('error', onUnknownError); }); req.pipe(wkhtmltopdf.stdin); }); };