github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/docs/examples/example-nodejs-app/node_modules/httpdispatcher/httpdispatcher.js (about) 1 var util = require('util'); 2 var HttpDispatcher = function() { 3 this.listeners = { get: [ ], post: [ ] }; 4 this.filters = { before: [ ], after: [ ] }; 5 this.errorListener = function(req, res) { 6 res.writeHead(404); 7 res.end(); 8 } 9 this.staticFolderPrefix = '/static'; 10 this.staticDirname; 11 } 12 HttpDispatcher.prototype.on = function(method, url, cb) { 13 this.listeners[method].push({ 14 cb: cb, 15 url: url 16 }); 17 } 18 HttpDispatcher.prototype.filter = function(method, url, cb) { 19 this.filters[method].push({ 20 cb: cb, 21 url: url 22 }); 23 } 24 HttpDispatcher.prototype.onGet = function(url, cb) { 25 this.on('get', url, cb); 26 } 27 HttpDispatcher.prototype.onPost = function(url, cb) { 28 this.on('post', url, cb); 29 } 30 HttpDispatcher.prototype.onError = function(cb) { 31 this.errorListener = cb; 32 } 33 HttpDispatcher.prototype.setStatic = function(folder) { 34 this.on('get', new RegExp("\/"+folder), this.staticListener.bind(this)); 35 } 36 HttpDispatcher.prototype.setStaticDirname = function(dirname) { 37 this.staticDirname = dirname; 38 } 39 HttpDispatcher.prototype.beforeFilter = function(url, cb) { 40 this.filter('before', url, cb); 41 } 42 HttpDispatcher.prototype.afterFilter = function(url, cb) { 43 this.filter('after', url, cb); 44 } 45 HttpDispatcher.prototype.dispatch = function(req, res) { 46 var url = require('url').parse(req.url, true); 47 var method = req.method.toLowerCase(); 48 var dispatcher = this; 49 var doDispatch = function() { 50 var httpChain = new HttpChain(); 51 var beforeFilters = this.getFilters(url.pathname, 'before'); 52 httpChain.addAll(beforeFilters); 53 var listener = this.getListener(url.pathname, method); 54 var listenerCb = listener ? listener : this.errorListener; 55 httpChain.add(httpChain.getWrapped(listenerCb)); 56 var afterFilters = this.getFilters(url.pathname, 'after'); 57 httpChain.addAll(afterFilters); 58 httpChain.next(req, res); 59 } 60 if(method == 'post') { 61 var body = ''; 62 req.on('data', function(data) { 63 body += data; 64 }); 65 req.on('end', function() { 66 var post = require('querystring').parse(body); 67 req.body = body; 68 req.params = post; 69 doDispatch.call(dispatcher); 70 }); 71 } else { 72 var url_parts = require('url').parse(req.url, true); 73 req.params = url_parts.query; 74 doDispatch.call(dispatcher); 75 } 76 } 77 HttpDispatcher.prototype.staticListener = function(req, res) { 78 var url = require('url').parse(req.url, true); 79 var filename = "." + require('path').join(this.staticDirname, url.pathname); 80 var errorListener = this.errorListener; 81 require('fs').readFile(filename, function(err, file) { 82 if(err) { 83 errorListener(req, res); 84 return; 85 } 86 res.writeHeader(200, { 87 "Content-Type": require('mime').lookup(filename) 88 }); 89 res.write(file, 'binary'); 90 res.end(); 91 }); 92 } 93 HttpDispatcher.prototype.getListener = function(url, method) { 94 for(var i = 0, listener; i<this.listeners[method].length; i++) { 95 listener = this.listeners[method][i]; 96 if(this.urlMatches(listener.url, url)) return listener.cb; 97 } 98 } 99 HttpDispatcher.prototype.getFilters = function(url, type) { 100 var filters = []; 101 for(var i = 0, filter; i<this.filters[type].length; i++) { 102 filter = this.filters[type][i]; 103 if(this.urlMatches(filter.url, url)) filters.push(filter.cb); 104 } 105 return filters; 106 } 107 HttpDispatcher.prototype.urlMatches = function(config, url) { 108 if(config instanceof RegExp) return config.test(url); 109 if(util.inspect(config) == "[Function]") return config(url); 110 return config == url; 111 } 112 var HttpChain = function() { 113 this.queue = []; 114 } 115 HttpChain.prototype.add = function(cb) { 116 this.queue.push(cb); 117 } 118 HttpChain.prototype.addAll = function(cbs) { 119 for(var i = 0; i<cbs.length; i++) this.add(cbs[i]); 120 } 121 HttpChain.prototype.next = function(req, res) { 122 var cb = this.queue.shift(); 123 if(cb) cb(req, res, this); 124 } 125 HttpChain.prototype.stop = function(req, res) { 126 res.end(); 127 } 128 HttpChain.prototype.getWrapped = function(cb) { 129 return function(req, res, chain) { 130 cb(req, res); 131 chain.next(req, res); 132 } 133 } 134 module.exports = new HttpDispatcher();