mvcjs
Version:
Powerful lightweight mvc framework for nodejs
154 lines (136 loc) • 4.07 kB
JavaScript
;
var di = require('../di'),
Type = di.load('typejs'),
error = di.load('error'),
core = di.load('core'),
etag = di.load('etag'),
mime = di.load('mime-types'),
fs = di.load('fs'),
Promise = di.load('promise'),
component = di.load('core/component'),
logger = component.get('core/logger'),
hook = component.get('hooks/request'),
Assets;
/**
* @license Mit Licence 2014
* @since 0.0.1
* @author Igor Ivanovic
* @name Favicon
*
* @constructor
* @description
* Favicon is responsible for favicon display on route /favicon.ico
*/
Assets = Type.create({
buffer: Type.OBJECT,
config: Type.OBJECT,
cache: Type.OBJECT,
regex: Type.REGEX
}, {
_construct: function Favicon_construct(config) {
this.config = core.extend({
path: '@{basePath}/storage/',
skip: false,
hook: '^\\/assets'
}, config);
logger.info('Assets.construct:', config);
this.regex = new RegExp(this.config.hook);
hook.set(this.regex, this.onRequest.bind(this));
},
/**
* @since 0.0.1
* @author Igor Ivanovic
* @method Favicon#onRequest
*
* @description
* On request handle favicon
* @return {object}
*/
onRequest: function Favicon_onRequest(api) {
var url = api.parsedUrl.pathname,
maxAge = 60 * 60 * 24 * 30 * 12, // one year
filePath,
mimeType;
if (this.config.skip) {
url = url.replace(this.regex, '');
}
filePath = di.normalizePath(this.config.path + url);
mimeType = this.mimeType(filePath);
if (!mimeType) {
logger.info('Assets.onRequest.mimeType: missing', {
mimeType: mimeType,
filePath: filePath
});
return this.handleError(function() {
new error.HttpError(500, {path: filePath}, 'Invalid mime type');
});
}
if (api.getMethod() !== 'GET') {
return this.handleError(function() {
new error.HttpError(500, {path: filePath}, 'Assets are accessible only via GET request');
});
}
return new Promise(function (resolve, reject) {
this.readFile(filePath, function (err, file) {
if (err) {
try {
new error.HttpError(500, {path: filePath}, 'No file found', err);
} catch (e) {
return reject(e);
}
}
api.addHeader('Content-Type', mimeType);
api.addHeader('Cache-Control', 'public, max-age=' + ~~(maxAge));
api.addHeader('ETag', etag(file));
if (api.isHeaderCacheUnModified()) {
return resolve(api.sendNoChange());
}
logger.info('Assets.onRequest.mimeType:', {
mimeType: mimeType,
filePath: filePath
});
resolve(file);
});
}.bind(this));
},
/**
* @since 0.0.1
* @author Igor Ivanovic
* @method Favicon#handleError
*
* @description
* Handle error response
*/
handleError: function Assets_handleError(callback) {
return new Promise(function (resolve, reject) {
try {
callback();
} catch (e) {
reject(e);
}
});
},
/**
* @since 0.0.1
* @author Igor Ivanovic
* @method Favicon#mimeType
*
* @description
* Get mime type
*/
mimeType: function Assets_mimeType(filePath) {
return mime.lookup(filePath);
},
/**
* @since 0.0.1
* @author Igor Ivanovic
* @method Favicon#readFile
*
* @description
* Get default error route
*/
readFile: function Assets_readFile() {
return fs.readFile.apply(fs, arguments);
}
});
module.exports = Assets;