Last active
March 16, 2017 16:35
-
-
Save DoumanAsh/fa97a10d41705965d46520fcebc23895 to your computer and use it in GitHub Desktop.
koa2 static file service middleware
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 fs = require('fs'); | |
const path = require('path'); | |
function is_stat_error_bad(error) { | |
switch (error.code) { | |
case 'ENOENT': | |
case 'ENAMETOOLONG': | |
case 'ENOTDIR': | |
return false; | |
default: | |
return true; | |
} | |
} | |
/** | |
* Retrieves static file from served directory. | |
* | |
* @param {String} root Valid and existing directory from where to look for path. | |
* @param {String} request_path HTTP Request path. | |
* | |
* @returns {Promise} Promise resolves to object {stats, path} if file to serve is found. | |
* Otherwise it resolves to undefined i.e. no file to serve. | |
*/ | |
function get_static_file(root, request_path) { | |
return new Promise((resolve, reject) => { | |
const front_path = path.join(root, request_path); | |
fs.stat(front_path, (err, stat) => { | |
if (err) { | |
if (is_stat_error_bad(err)) reject(err); | |
else resolve(undefined); | |
} | |
else { | |
if (stat.isDirectory()) { | |
const index_path = path.join(front_path, "index.html"); | |
fs.stat(index_path, (err, stat) => { | |
if (err) { | |
if (is_stat_error_bad(err)) reject(err); | |
else resolve(undefined); | |
} | |
else { | |
resolve({ | |
stats: stat, | |
path: index_path | |
}); | |
} | |
}); | |
} | |
else { | |
resolve({ | |
stats: stat, | |
path: front_path | |
}); | |
} | |
} | |
}); | |
}); | |
} | |
const front_dir = "public"; | |
async function front_server(ctx, next) { | |
const front = await get_static_file(front_dir, ctx.request.path); | |
if (front) { | |
logger.debug("Serve static=%s", front.path); | |
ctx.response.length = front.stats.size; | |
ctx.response.type = path.extname(front.path); | |
ctx.response.lastModified = front.stats.mtime; | |
ctx.response.etag = `W/"${front.stats.size.toString(16)}-${front.stats.mtime.getTime().toString(16)}"`; | |
ctx.response.status = 200; | |
if (ctx.request.fresh) { | |
ctx.response.status = 304; | |
ctx.response.body = null; | |
} | |
else { | |
ctx.response.body = fs.createReadStream(front.path); | |
} | |
// we're done here so no need to propagate it to next middleware. | |
} | |
else { | |
await next(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment