Created
March 17, 2018 11:51
-
-
Save nicholatian/6289f383a53cd1a9b6f77b5ed29cf1d6 to your computer and use it in GitHub Desktop.
Super-generic Express routing in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const router = Express.Router({ | |
caseSensitive: true, | |
strict: true | |
}) | |
exports.route = (uri, method, cb) => { | |
router[method.toLowerCase()](uri, cb) | |
} | |
/** ============================ F U N C T I O N ============================ * | |
* TITLE: Callback Generators | |
* DESCRIPTION: Functions that generate callback functions to be called by an | |
* Express router for a requested URI. While possibly confusing to | |
* some, this is a super-effective application of genericism in | |
* JavaScript. | |
* In our Express server, we map various routes using regular | |
* expressions, and couple them with code to serve an appropriate | |
* response. Writing this out long-hand is tedious, not nice for | |
* sysadmins, and bug-prone. | |
* Instead, we read in our collection of routes from a config | |
* file, and couple them with callbacks that Express recognises so | |
* we can send a response. On top of this, we make things not just | |
* DRY, but truly generic, by taking advantage of the fact that | |
* most routes often do the same or predictably similar tasks, | |
* which we categorise as actions such as `verbatim` or `redirect` | |
* or the like. | |
* When we run through the list of routes, we must create | |
* callbacks for each of them that have all of the right info to | |
* serve data. These route-specific callbacks are created by | |
* callback generators: there is one generator for each kind of | |
* route action to take. These generators hold all of the common | |
* context for their kind of routes, and all routes of that kind | |
* can share said data thanks to asynchronous control flow. | |
*/ | |
const cbGen = { | |
verbatim: opts => { | |
const cwd = process.cwd() | |
const realRoot = opts.fileRoot === 'live' ? path.join(cwd, dist) : | |
opts.fileRoot === 'project' ? cwd : | |
process.platform === 'win32' ? 'C:' : '/' | |
const realPath = process.platform === 'win32' ? | |
opts.filePath.replace('/', '\\') : opts.filePath | |
return (req, res) => { | |
const serve = (err, data) => { | |
if(err) { | |
console.error(err) | |
return | |
} | |
res.send(data) | |
} | |
fs.readFile(path.join(realRoot, realPath), | |
opts.text === true ? 'utf-8' : null, serve) | |
} | |
}, | |
redirect: opts => { | |
return (req, res) => { | |
res.redirect(307, opts.dest) | |
} | |
} | |
} | |
exports.loadConfig = () => { | |
const cfg = require('../config/routes') | |
for(let i = 0; i < cfg.length; i++) { | |
exports.route(cfg[i].uri, cfg[i].method, cbGen[cfg[i].action]()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment