-
-
Save Raynos/eaab3b4bffe5b211840e to your computer and use it in GitHub Desktop.
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
var zlib = require("zlib") | |
var crypto = require("crypto") | |
var isGzip = /\bgzip\b/ | |
module.exports = CompiledFiles | |
function CompiledFiles(config) { | |
config = config || {} | |
var contentType = config.contentType || "text/plain" | |
var sendError = config.sendError || defaultSendError | |
var compile = config.compile | |
var findResource = config.findResource | |
if (!config.findResource) { | |
throw new Error("Must pass in a resource finding function") | |
} | |
if (!config.compile) { | |
throw new Error("Must pass in a compile function") | |
} | |
return function ServeFile(opts) { | |
opts = opts || {} | |
var cache = opts.cache | |
var gzip = opts.gzip | |
var cacheControl = opts.cacheControl || "max-age=300, must-revalidate" | |
var compiledCache = {} | |
return function routeHandler(req, res) { | |
var location = findResource(req, opts) | |
res.setHeader("content-type", contentType) | |
if (cache && compiledCache[location]) { | |
return sendResource(req, res, compiledCache[location]) | |
} | |
compile(location, opts, prepareResource) | |
function prepareResource(err, payload) { | |
if (err) { | |
return sendError(req, res, err) | |
} | |
if (gzip) { | |
zlib.gzip(payload, function (err, buffer) { | |
if (err) { | |
return sendError(req, res, err) | |
} | |
sendGzipPlain({ plain: payload, gzip: buffer }) | |
}) | |
} else { | |
sendGzipPlain({ plain: payload }) | |
} | |
} | |
function sendGzipPlain(types) { | |
var hash = crypto | |
.createHash("md5") | |
.update(types.plain) | |
.digest("hex") | |
var chunk = new FileChunk(types.plain, types.gzip, hash) | |
if (cache) { | |
compiledCache[location] = chunk | |
} | |
sendResource(req, res, chunk) | |
} | |
} | |
function sendResource(req, res, chunk) { | |
var reqEtag = req.headers["if-none-match"] || "" | |
if (cache && reqEtag === chunk.hash) { | |
res.statusCode = 304 | |
return res.end() | |
} | |
res.statusCode = 200 | |
if (cache) { | |
res.setHeader("Etag", chunk.hash) | |
res.setHeader("Cache-Control", cacheControl) | |
} | |
var acceptEncoding = req.headers["accept-encoding"] || "" | |
if (gzip && chunk.gzip && acceptEncoding.match(isGzip)) { | |
res.setHeader("content-encoding", "gzip") | |
return res.end(chunk.gzip) | |
} | |
return res.end(chunk.plain) | |
} | |
} | |
} | |
function defaultSendError(req, res, err) { | |
res.statusCode = 500 | |
res.end(err.message) | |
} | |
/* findResource takes a Request, the opts passed to the ServeFile | |
function and a callback. | |
It's responsibility is to return a location on disk that the | |
Request is asking for. | |
*/ | |
function FileChunk(plain, gzip, hash) { | |
this.plain = plain || null | |
this.gzip = gzip || null | |
this.hash = hash || null | |
} | |
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
var resolve = require("resolve") | |
var path = require("path") | |
var url = require("url") | |
var bundle = require("./bundle") | |
var CompiledFiles = require("./lib/compiled-files") | |
// var getLocation = require("./lib/get-location") | |
// /js/:appName | |
module.exports = CompiledFiles({ | |
// this is the function to compile the resource. | |
// the location is the value returned by findResource | |
// you should pass a String to the callback | |
compile: function (location, opts, callback) { | |
resolve(location, function (err, fileUri) { | |
bundle(fileUri, opts, callback) | |
}) | |
}, | |
// This is the logic of how to display errors to the user | |
sendError: function sendError(req, res, err) { | |
return res.end("(" + function (err) { | |
throw new Error(err) | |
} + "(" + JSON.stringify(err.message) + "))") | |
}, | |
// CompiledFiles will set this content type on the response | |
contentType: "application/javascript", | |
/* | |
findResource takes a Request, the opts passed to the ServeFile | |
function and a callback. | |
It's responsibility is to return a location on disk that the | |
Request is asking for. | |
*/ | |
findResource: function findResource(req, res, opts) { | |
var pathname = url.parse(req.url).pathname | |
var parts = pathname.split("/") | |
return path.join(opts.root, parts[parts.length - 1]) | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment