Skip to content

Instantly share code, notes, and snippets.

@william-xue
Forked from Saul-Mirone/mini-express.js
Created July 6, 2017 03:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save william-xue/88149ed73e0462164df6a0770af699ad to your computer and use it in GitHub Desktop.
Save william-xue/88149ed73e0462164df6a0770af699ad to your computer and use it in GitHub Desktop.
Just An Express Style Framework
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mime = {
"html": "text/html",
"css": "text/css",
"js": "text/javascript",
"json": "application/json",
"gif": "image/gif",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"png": "image/png"
}
function handleStatic(res, pathname, ext) {
fs.exists(pathname, (exists) => {
if(!exists) {
res.writeHead(404, {'Content-Type': 'text/plain'})
res.write('The request url' + pathname + 'was not found on this server')
res.end()
} else {
fs.readFile(pathname, (err, file) => {
if(err) {
res.writeHead(500, {'Content-Type': 'text/plain'})
res.end(err)
} else {
const contentType = mime[ext] || 'text/plain'
res.writeHead(200, {'Content-Type': contentType})
res.write(file)
res.end()
}
})
}
})
}
const lazy = function* (arr) {
yield* arr;
}
const passRouter = (routes, method, path) => (req, res) => {
const replaceParams = (path) => new RegExp(`\^${path.replace(/:\w[^\/]+/g, '\\w[^\/]+')}\$`);
const lazyRoutes = lazy(routes);
(function next () {
const it = lazyRoutes.next().value;
if (!it) {
res.end(`Cannot ${method} ${path}`)
return;
} else if (it.method === 'use'
&& (it.path === '/'
|| it.path === path
|| path.startsWith(it.path.concat('/')))) {
it.fn(req, res, next);
} else if ((it.method === method
|| it.method === 'all')
&& (it.path === path
|| it.path === '*')) {
it.fn(req, res);
} else if ( it.path.includes(':')
&& (it.method === method
|| it.method === 'all')
&& (replaceParams(it.path).test(path))) {
let index = 0;
const param2Array = it.path.split('/');
const path2Array = path.split('/');
const params = {};
param2Array.forEach((path) => {
if(/\:/.test(path)) {
params[path.slice(1)] = path2Array[index]
}
index++
})
req.params = params
it.fn(req, res);
} else {
next();
}
}());
};
function core() {
let _static = 'static'
let app = (req, res) => {
const method = req.method.toLowerCase()
const urlObj = url.parse(req.url, true)
const pathname = urlObj.pathname
const ext = path.extname(pathname).slice(1)
if(ext) {
handleStatic(res, _static + pathname, ext)
} else {
passRouter(app.routes, method, pathname)(req, res)
}
}
app.setStatic = (path) => {
_static = path
}
app.routes = []
const methods = ['get', 'post', 'put', 'options', 'delete', 'all', 'use']
methods.forEach((method) => {
app[method] = (path, fn) => {
app.routes.push({
method: method,
path: path,
fn: fn
})
}
})
app.use = (path, fn) => {
app.routes.push({
method: 'use',
path: path,
fn: fn
})
}
app.listen = (port=3000, host='localhost') => {
http.createServer(app).listen(port, host, () => {
console.log(`Server running at ${host}\:${port}.`)
process.setMaxListeners(0)
process.on('uncaughtException', function(err) {
console.log(err.stack)
})
process.stdin.resume()
process.on('SIGINT', function() {
console.log('\n')
console.log('Good Day!')
process.exit(2)
})
})
}
return app
}
module.exports = core
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment