index.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*!
  2. * mime-types
  3. * Copyright(c) 2014 Jonathan Ong
  4. * Copyright(c) 2015 Douglas Christopher Wilson
  5. * MIT Licensed
  6. */
  7. 'use strict'
  8. /**
  9. * Module dependencies.
  10. * @private
  11. */
  12. var db = require('mime-db')
  13. var extname = require('path').extname
  14. /**
  15. * Module variables.
  16. * @private
  17. */
  18. var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/
  19. var TEXT_TYPE_REGEXP = /^text\//i
  20. /**
  21. * Module exports.
  22. * @public
  23. */
  24. exports.charset = charset
  25. exports.charsets = { lookup: charset }
  26. exports.contentType = contentType
  27. exports.extension = extension
  28. exports.extensions = Object.create(null)
  29. exports.lookup = lookup
  30. exports.types = Object.create(null)
  31. // Populate the extensions/types maps
  32. populateMaps(exports.extensions, exports.types)
  33. /**
  34. * Get the default charset for a MIME type.
  35. *
  36. * @param {string} type
  37. * @return {boolean|string}
  38. */
  39. function charset (type) {
  40. if (!type || typeof type !== 'string') {
  41. return false
  42. }
  43. // TODO: use media-typer
  44. var match = EXTRACT_TYPE_REGEXP.exec(type)
  45. var mime = match && db[match[1].toLowerCase()]
  46. if (mime && mime.charset) {
  47. return mime.charset
  48. }
  49. // default text/* to utf-8
  50. if (match && TEXT_TYPE_REGEXP.test(match[1])) {
  51. return 'UTF-8'
  52. }
  53. return false
  54. }
  55. /**
  56. * Create a full Content-Type header given a MIME type or extension.
  57. *
  58. * @param {string} str
  59. * @return {boolean|string}
  60. */
  61. function contentType (str) {
  62. // TODO: should this even be in this module?
  63. if (!str || typeof str !== 'string') {
  64. return false
  65. }
  66. var mime = str.indexOf('/') === -1
  67. ? exports.lookup(str)
  68. : str
  69. if (!mime) {
  70. return false
  71. }
  72. // TODO: use content-type or other module
  73. if (mime.indexOf('charset') === -1) {
  74. var charset = exports.charset(mime)
  75. if (charset) mime += '; charset=' + charset.toLowerCase()
  76. }
  77. return mime
  78. }
  79. /**
  80. * Get the default extension for a MIME type.
  81. *
  82. * @param {string} type
  83. * @return {boolean|string}
  84. */
  85. function extension (type) {
  86. if (!type || typeof type !== 'string') {
  87. return false
  88. }
  89. // TODO: use media-typer
  90. var match = EXTRACT_TYPE_REGEXP.exec(type)
  91. // get extensions
  92. var exts = match && exports.extensions[match[1].toLowerCase()]
  93. if (!exts || !exts.length) {
  94. return false
  95. }
  96. return exts[0]
  97. }
  98. /**
  99. * Lookup the MIME type for a file path/extension.
  100. *
  101. * @param {string} path
  102. * @return {boolean|string}
  103. */
  104. function lookup (path) {
  105. if (!path || typeof path !== 'string') {
  106. return false
  107. }
  108. // get the extension ("ext" or ".ext" or full path)
  109. var extension = extname('x.' + path)
  110. .toLowerCase()
  111. .substr(1)
  112. if (!extension) {
  113. return false
  114. }
  115. return exports.types[extension] || false
  116. }
  117. /**
  118. * Populate the extensions and types maps.
  119. * @private
  120. */
  121. function populateMaps (extensions, types) {
  122. // source preference (least -> most)
  123. var preference = ['nginx', 'apache', undefined, 'iana']
  124. Object.keys(db).forEach(function forEachMimeType (type) {
  125. var mime = db[type]
  126. var exts = mime.extensions
  127. if (!exts || !exts.length) {
  128. return
  129. }
  130. // mime -> extensions
  131. extensions[type] = exts
  132. // extension -> mime
  133. for (var i = 0; i < exts.length; i++) {
  134. var extension = exts[i]
  135. if (types[extension]) {
  136. var from = preference.indexOf(db[types[extension]].source)
  137. var to = preference.indexOf(mime.source)
  138. if (types[extension] !== 'application/octet-stream' &&
  139. (from > to || (from === to && types[extension].substr(0, 12) === 'application/'))) {
  140. // skip the remapping
  141. continue
  142. }
  143. }
  144. // set the extension -> mime
  145. types[extension] = type
  146. }
  147. })
  148. }