UNPKG

bwip-js

Version:

JavaScript barcode generator supporting over 100 types and standards.

136 lines (122 loc) 3.96 kB
// bwip-js/examples/threaded.js // // Threaded node.js HTTP server that renders bar code images using bwip-js. // // Node 10.5+ only. // // Node 10.5 Usage: // node --experimental-worker threaded [address:port] ... // // Node 11+ // node threaded [address:port] ... // // To specify all interfaces, use * as the address // // If no address:port are specified, the default is: *:3030 "use strict"; const Worker = require('worker_threads').Worker; const http = require('http'); const ncpus = require('os').cpus().length; // Use arrays for simplicity. They shouldn't get so big as to make O(n) perf matter. const workers = []; const queue = []; // Create the worker threads for (let i = 0, n = ncpus-1 || 1; i < n; i++) { createWorker(); } const server = http.createServer(function(req, res) { // If the url does not begin /?bcid= then 404. Otherwise, we end up // returning 400 on requests like favicon.ico. if (req.url.indexOf('/?bcid=') != 0) { res.writeHead(404, { 'Content-Type':'text/plain' }); res.end('BWIP-JS: Unknown request format.', 'utf8'); } else { // Some arbitrary limit... if (queue.length > 16) { st.res.writeHead(503, { 'Content-Type':'text/plain' }); st.res.end('HTTP ERROR 503 - Service Unavailable'); } else if (!workers.length) { queue.push({ res:res, req:req }); } else { let worker = workers.pop(); worker.workerState = { res:res, req:req }; worker.postMessage(req.url); } } }) let binds = 0; for (let i = 2; i < process.argv.length; i++) { let a = /^([^:]+):(\d+)$/.exec(process.argv[i]); if (a) { if (a[1] == '*') { server.listen(+a[2]); } else { server.listen(+a[2], a[1]); } } else { console.log(process.argv[i] + ': option ignored...'); } console.log('listening on ' + process.argv[i]); binds++; } if (!binds) { server.listen(process.env.PORT || 3030); console.log('listening on *:' + (process.env.PORT || 3030)); } function createWorker() { let worker = new Worker(workerCode(), { eval:true }); worker.on('error', (err) => { console.log(err); setTimeout(createWorker, 500) }); worker.on('close', () => setTimeout(createWorker, 500)); worker.on('online', () => workers.push(worker)); worker.on('message', (msg) => { let st = worker.workerState; if (msg.err) { st.res.writeHead(400, { 'Content-Type':'text/plain' }); st.res.end('' + msg.err, 'utf-8'); } else if (msg.png) { st.res.writeHead(200, { 'Content-Type':'image/png' }); st.res.end(Buffer.from(msg.png), 'binary'); } else { // ??? } worker.workerState = null; if (queue.length) { worker.workerState = queue.shift(); worker.postMessage(worker.workerState.req.url); } }); } function workerCode() { return ` const worker = require('worker_threads'); const url = require('url'); const bwipjs = (function() { try { return require('bwip-js'); // for installed usage } catch (e) { return require('..'); // for development use only } })(); worker.parentPort.on('message', (requestUrl) => { let opts = url.parse(requestUrl, true).query; // Convert empty parameters to true. // Convert empty !parameters to false. for (let id in opts) { if (opts[id] === '') { if (id[0] == '!') { opts[id.substr(1)] = false; } else { opts[id] = true; } } } bwipjs.toBuffer(opts, function(err, png) { if (err) { worker.parentPort.postMessage({ err:'' + (err.stack || err) }); } else { worker.parentPort.postMessage({ png:png.buffer }, [ png.buffer ]); } }); }); `; }