| /*! |
| * mime-types |
| * Copyright(c) 2014 Jonathan Ong |
| * Copyright(c) 2015 Douglas Christopher Wilson |
| * MIT Licensed |
| */ |
| |
| 'use strict' |
| |
| /** |
| * Module dependencies. |
| * @private |
| */ |
| |
| var db = require('mime-db') |
| var extname = require('path').extname |
| |
| /** |
| * Module variables. |
| * @private |
| */ |
| |
| var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/ |
| var TEXT_TYPE_REGEXP = /^text\//i |
| |
| /** |
| * Module exports. |
| * @public |
| */ |
| |
| exports.charset = charset |
| exports.charsets = { lookup: charset } |
| exports.contentType = contentType |
| exports.extension = extension |
| exports.extensions = Object.create(null) |
| exports.lookup = lookup |
| exports.types = Object.create(null) |
| |
| // Populate the extensions/types maps |
| populateMaps(exports.extensions, exports.types) |
| |
| /** |
| * Get the default charset for a MIME type. |
| * |
| * @param {string} type |
| * @return {boolean|string} |
| */ |
| |
| function charset (type) { |
| if (!type || typeof type !== 'string') { |
| return false |
| } |
| |
| // TODO: use media-typer |
| var match = EXTRACT_TYPE_REGEXP.exec(type) |
| var mime = match && db[match[1].toLowerCase()] |
| |
| if (mime && mime.charset) { |
| return mime.charset |
| } |
| |
| // default text/* to utf-8 |
| if (match && TEXT_TYPE_REGEXP.test(match[1])) { |
| return 'UTF-8' |
| } |
| |
| return false |
| } |
| |
| /** |
| * Create a full Content-Type header given a MIME type or extension. |
| * |
| * @param {string} str |
| * @return {boolean|string} |
| */ |
| |
| function contentType (str) { |
| // TODO: should this even be in this module? |
| if (!str || typeof str !== 'string') { |
| return false |
| } |
| |
| var mime = str.indexOf('/') === -1 |
| ? exports.lookup(str) |
| : str |
| |
| if (!mime) { |
| return false |
| } |
| |
| // TODO: use content-type or other module |
| if (mime.indexOf('charset') === -1) { |
| var charset = exports.charset(mime) |
| if (charset) mime += '; charset=' + charset.toLowerCase() |
| } |
| |
| return mime |
| } |
| |
| /** |
| * Get the default extension for a MIME type. |
| * |
| * @param {string} type |
| * @return {boolean|string} |
| */ |
| |
| function extension (type) { |
| if (!type || typeof type !== 'string') { |
| return false |
| } |
| |
| // TODO: use media-typer |
| var match = EXTRACT_TYPE_REGEXP.exec(type) |
| |
| // get extensions |
| var exts = match && exports.extensions[match[1].toLowerCase()] |
| |
| if (!exts || !exts.length) { |
| return false |
| } |
| |
| return exts[0] |
| } |
| |
| /** |
| * Lookup the MIME type for a file path/extension. |
| * |
| * @param {string} path |
| * @return {boolean|string} |
| */ |
| |
| function lookup (path) { |
| if (!path || typeof path !== 'string') { |
| return false |
| } |
| |
| // get the extension ("ext" or ".ext" or full path) |
| var extension = extname('x.' + path) |
| .toLowerCase() |
| .substr(1) |
| |
| if (!extension) { |
| return false |
| } |
| |
| return exports.types[extension] || false |
| } |
| |
| /** |
| * Populate the extensions and types maps. |
| * @private |
| */ |
| |
| function populateMaps (extensions, types) { |
| // source preference (least -> most) |
| var preference = ['nginx', 'apache', undefined, 'iana'] |
| |
| Object.keys(db).forEach(function forEachMimeType (type) { |
| var mime = db[type] |
| var exts = mime.extensions |
| |
| if (!exts || !exts.length) { |
| return |
| } |
| |
| // mime -> extensions |
| extensions[type] = exts |
| |
| // extension -> mime |
| for (var i = 0; i < exts.length; i++) { |
| var extension = exts[i] |
| |
| if (types[extension]) { |
| var from = preference.indexOf(db[types[extension]].source) |
| var to = preference.indexOf(mime.source) |
| |
| if (types[extension] !== 'application/octet-stream' && |
| (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) { |
| // skip the remapping |
| continue |
| } |
| } |
| |
| // set the extension -> mime |
| types[extension] = type |
| } |
| }) |
| } |