3 * Copyright(c) 2014 Jonathan Ong
4 * Copyright(c) 2015 Douglas Christopher Wilson
11 * Module dependencies.
15 var db = require('mime-db')
16 var extname = require('path').extname
23 var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/
24 var TEXT_TYPE_REGEXP = /^text\//i
31 exports.charset = charset
32 exports.charsets = { lookup: charset }
33 exports.contentType = contentType
34 exports.extension = extension
35 exports.extensions = Object.create(null)
36 exports.lookup = lookup
37 exports.types = Object.create(null)
39 // Populate the extensions/types maps
40 populateMaps(exports.extensions, exports.types)
43 * Get the default charset for a MIME type.
45 * @param {string} type
46 * @return {boolean|string}
49 function charset (type) {
50 if (!type || typeof type !== 'string') {
54 // TODO: use media-typer
55 var match = EXTRACT_TYPE_REGEXP.exec(type)
56 var mime = match && db[match[1].toLowerCase()]
58 if (mime && mime.charset) {
62 // default text/* to utf-8
63 if (match && TEXT_TYPE_REGEXP.test(match[1])) {
71 * Create a full Content-Type header given a MIME type or extension.
74 * @return {boolean|string}
77 function contentType (str) {
78 // TODO: should this even be in this module?
79 if (!str || typeof str !== 'string') {
83 var mime = str.indexOf('/') === -1
91 // TODO: use content-type or other module
92 if (mime.indexOf('charset') === -1) {
93 var charset = exports.charset(mime)
94 if (charset) mime += '; charset=' + charset.toLowerCase()
101 * Get the default extension for a MIME type.
103 * @param {string} type
104 * @return {boolean|string}
107 function extension (type) {
108 if (!type || typeof type !== 'string') {
112 // TODO: use media-typer
113 var match = EXTRACT_TYPE_REGEXP.exec(type)
116 var exts = match && exports.extensions[match[1].toLowerCase()]
118 if (!exts || !exts.length) {
126 * Lookup the MIME type for a file path/extension.
128 * @param {string} path
129 * @return {boolean|string}
132 function lookup (path) {
133 if (!path || typeof path !== 'string') {
137 // get the extension ("ext" or ".ext" or full path)
138 var extension = extname('x.' + path)
146 return exports.types[extension] || false
150 * Populate the extensions and types maps.
154 function populateMaps (extensions, types) {
155 // source preference (least -> most)
156 var preference = ['nginx', 'apache', undefined, 'iana']
158 Object.keys(db).forEach(function forEachMimeType (type) {
160 var exts = mime.extensions
162 if (!exts || !exts.length) {
166 // mime -> extensions
167 extensions[type] = exts
170 for (var i = 0; i < exts.length; i++) {
171 var extension = exts[i]
173 if (types[extension]) {
174 var from = preference.indexOf(db[types[extension]].source)
175 var to = preference.indexOf(mime.source)
177 if (types[extension] !== 'application/octet-stream' &&
178 (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
179 // skip the remapping
184 // set the extension -> mime
185 types[extension] = type