MediaTypes.kt

  1. package com.hexagonkt.core.media

  2. import com.hexagonkt.core.media.MediaTypeGroup.*
  3. import java.io.File
  4. import java.net.URI
  5. import java.net.URL
  6. import java.nio.file.Path
  7. import kotlin.io.path.extension

  8. val MEDIA_TYPE_FORMAT: Regex by lazy { """\*|([\w+.-]+)""".toRegex() }

  9. val ANY_MEDIA: MediaType by lazy { MediaType(ANY, "*") }

  10. val APPLICATION_AVRO: MediaType by lazy { MediaType(APPLICATION, "avro") }
  11. val APPLICATION_CBOR: MediaType by lazy { MediaType(APPLICATION, "cbor") }
  12. val APPLICATION_JSON: MediaType by lazy { MediaType(APPLICATION, "json") }
  13. val APPLICATION_YAML: MediaType by lazy { MediaType(APPLICATION, "yaml") }
  14. val APPLICATION_XML: MediaType by lazy { MediaType(APPLICATION, "xml") }
  15. val APPLICATION_GZIP: MediaType by lazy { MediaType(APPLICATION, "gzip") }
  16. val APPLICATION_COMPRESS: MediaType by lazy { MediaType(APPLICATION, "compress") }
  17. val APPLICATION_OCTET_STREAM: MediaType by lazy { MediaType(APPLICATION, "octet-stream") }
  18. val APPLICATION_PDF: MediaType by lazy { MediaType(APPLICATION, "pdf") }
  19. val APPLICATION_POSTSCRIPT: MediaType by lazy { MediaType(APPLICATION, "postscript") }
  20. val APPLICATION_RTF: MediaType by lazy { MediaType(APPLICATION, "rtf") }
  21. val APPLICATION_X_CSH: MediaType by lazy { MediaType(APPLICATION, "x-csh") }
  22. val APPLICATION_X_GTAR: MediaType by lazy { MediaType(APPLICATION, "x-gtar") }
  23. val APPLICATION_X_LATEX: MediaType by lazy { MediaType(APPLICATION, "x-latex") }
  24. val APPLICATION_X_SH: MediaType by lazy { MediaType(APPLICATION, "x-sh") }
  25. val APPLICATION_X_TAR: MediaType by lazy { MediaType(APPLICATION, "x-tar") }
  26. val APPLICATION_X_TCL: MediaType by lazy { MediaType(APPLICATION, "x-tcl") }
  27. val APPLICATION_X_TEX: MediaType by lazy { MediaType(APPLICATION, "x-tex") }
  28. val APPLICATION_X_TEXINFO: MediaType by lazy { MediaType(APPLICATION, "x-texinfo") }
  29. val APPLICATION_ZIP: MediaType by lazy { MediaType(APPLICATION, "zip") }
  30. val APPLICATION_EPUB_ZIP: MediaType by lazy { MediaType(APPLICATION, "epub+zip") }
  31. val APPLICATION_JAVA_ARCHIVE: MediaType by lazy { MediaType(APPLICATION, "java-archive") }
  32. val APPLICATION_OGG: MediaType by lazy { MediaType(APPLICATION, "ogg") }
  33. val APPLICATION_RAR: MediaType by lazy { MediaType(APPLICATION, "vnd.rar") }
  34. val APPLICATION_XHTML: MediaType by lazy { MediaType(APPLICATION, "xhtml+xml") }
  35. val APPLICATION_WEB_MANIFEST: MediaType by lazy { MediaType(APPLICATION, "manifest+json") }
  36. val APPLICATION_TOML: MediaType by lazy { MediaType(APPLICATION, "toml") }
  37. val APPLICATION_7Z: MediaType by lazy { MediaType(APPLICATION, "x-7z-compressed") }
  38. val APPLICATION_BZIP: MediaType by lazy { MediaType(APPLICATION, "x-bzip") }
  39. val APPLICATION_BZIP2: MediaType by lazy { MediaType(APPLICATION, "x-bzip2") }
  40. val APPLICATION_CDF: MediaType by lazy { MediaType(APPLICATION, "x-cdf") }
  41. val APPLICATION_PHP: MediaType by lazy { MediaType(APPLICATION, "x-httpd-php") }

  42. val AUDIO_BASIC: MediaType by lazy { MediaType(AUDIO, "basic") }
  43. val AUDIO_MPEG: MediaType by lazy { MediaType(AUDIO, "mpeg") }
  44. val AUDIO_WAV: MediaType by lazy { MediaType(AUDIO, "wav") }
  45. val AUDIO_AAC: MediaType by lazy { MediaType(AUDIO, "aac") }
  46. val AUDIO_MIDI: MediaType by lazy { MediaType(AUDIO, "midi") }
  47. val AUDIO_OGG: MediaType by lazy { MediaType(AUDIO, "ogg") }
  48. val AUDIO_OPUS: MediaType by lazy { MediaType(AUDIO, "opus") }
  49. val AUDIO_WEBM: MediaType by lazy { MediaType(AUDIO, "webm") }

  50. val FONT_OTF: MediaType by lazy { MediaType(FONT, "otf") }
  51. val FONT_TTF: MediaType by lazy { MediaType(FONT, "ttf") }
  52. val FONT_WOFF: MediaType by lazy { MediaType(FONT, "woff") }
  53. val FONT_WOFF2: MediaType by lazy { MediaType(FONT, "woff2") }

  54. val IMAGE_GIF: MediaType by lazy { MediaType(IMAGE, "gif") }
  55. val IMAGE_JPEG: MediaType by lazy { MediaType(IMAGE, "jpeg") }
  56. val IMAGE_PNG: MediaType by lazy { MediaType(IMAGE, "png") }
  57. val IMAGE_TIFF: MediaType by lazy { MediaType(IMAGE, "tiff") }
  58. val IMAGE_SVG: MediaType by lazy { MediaType(IMAGE, "svg+xml") }
  59. val IMAGE_ICO: MediaType by lazy { MediaType(IMAGE, "vnd.microsoft.icon") }
  60. val IMAGE_WEBP: MediaType by lazy { MediaType(IMAGE, "webp") }
  61. val IMAGE_AVIF: MediaType by lazy { MediaType(IMAGE, "avif") }

  62. val MULTIPART_ALTERNATIVE: MediaType by lazy { MediaType(MULTIPART, "alternative") }
  63. val MULTIPART_APPLEDOUBLE: MediaType by lazy { MediaType(MULTIPART, "appledouble") }
  64. val MULTIPART_DIGEST: MediaType by lazy { MediaType(MULTIPART, "digest") }
  65. val MULTIPART_MIXED: MediaType by lazy { MediaType(MULTIPART, "mixed") }
  66. val MULTIPART_PARALLEL: MediaType by lazy { MediaType(MULTIPART, "parallel") }

  67. val TEXT_CSV: MediaType by lazy { MediaType(TEXT, "csv") }
  68. val TEXT_X_JAVA_PROPERTIES: MediaType by lazy { MediaType(TEXT, "x-java-properties") }
  69. val TEXT_JAVASCRIPT: MediaType by lazy { MediaType(TEXT, "javascript") }
  70. val TEXT_CSS: MediaType by lazy { MediaType(TEXT, "css") }
  71. val TEXT_HTML: MediaType by lazy { MediaType(TEXT, "html") }
  72. val TEXT_MARKDOWN: MediaType by lazy { MediaType(TEXT, "markdown") }
  73. val TEXT_PLAIN: MediaType by lazy { MediaType(TEXT, "plain") }
  74. val TEXT_RICHTEXT: MediaType by lazy { MediaType(TEXT, "richtext") }
  75. val TEXT_TAB_SEPARATED_VALUES: MediaType by lazy { MediaType(TEXT, "tab-separated-values") }
  76. val TEXT_CALENDAR: MediaType by lazy { MediaType(TEXT, "calendar") }
  77. val TEXT_EVENT_STREAM: MediaType by lazy { MediaType(TEXT, "event-stream") }

  78. val VIDEO_MPEG: MediaType by lazy { MediaType(VIDEO, "mpeg") }
  79. val VIDEO_QUICKTIME: MediaType by lazy { MediaType(VIDEO, "quicktime") }
  80. val VIDEO_X_MSVIDEO: MediaType by lazy { MediaType(VIDEO, "x-msvideo") }
  81. val VIDEO_MP4: MediaType by lazy { MediaType(VIDEO, "mp4") }
  82. val VIDEO_OGG: MediaType by lazy { MediaType(VIDEO, "ogg") }
  83. val VIDEO_WEBM: MediaType by lazy { MediaType(VIDEO, "webm") }

  84. val DEFAULT_MEDIA_TYPE: MediaType by lazy { APPLICATION_OCTET_STREAM }

  85. internal val MEDIA_TYPES_EXTENSIONS: Map<String, MediaType> by lazy {
  86.     mapOf(
  87.         "avro" to APPLICATION_AVRO,
  88.         "cbor" to APPLICATION_CBOR,
  89.         "json" to APPLICATION_JSON,
  90.         "yaml" to APPLICATION_YAML,
  91.         "yml" to APPLICATION_YAML,
  92.         "xml" to APPLICATION_XML,
  93.         "bin" to APPLICATION_OCTET_STREAM,
  94.         "lha" to APPLICATION_OCTET_STREAM,
  95.         "lzh" to APPLICATION_OCTET_STREAM,
  96.         "exe" to APPLICATION_OCTET_STREAM,
  97.         "so" to APPLICATION_OCTET_STREAM,
  98.         "class" to APPLICATION_OCTET_STREAM,
  99.         "pdf" to APPLICATION_PDF,
  100.         "ai" to APPLICATION_POSTSCRIPT,
  101.         "eps" to APPLICATION_POSTSCRIPT,
  102.         "ps" to APPLICATION_POSTSCRIPT,
  103.         "rtf" to APPLICATION_RTF,
  104.         "z" to APPLICATION_COMPRESS,
  105.         "csh" to APPLICATION_X_CSH,
  106.         "gtar" to APPLICATION_X_GTAR,
  107.         "gz" to APPLICATION_GZIP,
  108.         "gzip" to APPLICATION_GZIP,
  109.         "latex" to APPLICATION_X_LATEX,
  110.         "sh" to APPLICATION_X_SH,
  111.         "tar" to APPLICATION_X_TAR,
  112.         "tcl" to APPLICATION_X_TCL,
  113.         "tex" to APPLICATION_X_TEX,
  114.         "texinfo" to APPLICATION_X_TEXINFO,
  115.         "texi" to APPLICATION_X_TEXINFO,
  116.         "zip" to APPLICATION_ZIP,
  117.         "epub" to APPLICATION_EPUB_ZIP,
  118.         "jar" to APPLICATION_JAVA_ARCHIVE,
  119.         "ogx" to APPLICATION_OGG,
  120.         "rar" to APPLICATION_RAR,
  121.         "7z" to APPLICATION_7Z,
  122.         "bz" to APPLICATION_BZIP,
  123.         "bz2" to APPLICATION_BZIP2,
  124.         "cda" to APPLICATION_CDF,
  125.         "php" to APPLICATION_PHP,
  126.         "xhtml" to APPLICATION_XHTML,
  127.         "webmanifest" to APPLICATION_WEB_MANIFEST,
  128.         "toml" to APPLICATION_TOML,
  129.         "au" to AUDIO_BASIC,
  130.         "snd" to AUDIO_BASIC,
  131.         "mpga" to AUDIO_MPEG,
  132.         "mp2" to AUDIO_MPEG,
  133.         "mp2a" to AUDIO_MPEG,
  134.         "mp3" to AUDIO_MPEG,
  135.         "m2a" to AUDIO_MPEG,
  136.         "m3a" to AUDIO_MPEG,
  137.         "wav" to AUDIO_WAV,
  138.         "aac" to AUDIO_AAC,
  139.         "mid" to AUDIO_MIDI,
  140.         "midi" to AUDIO_MIDI,
  141.         "oga" to AUDIO_OGG,
  142.         "opus" to AUDIO_OPUS,
  143.         "weba" to AUDIO_WEBM,
  144.         "otf" to FONT_OTF,
  145.         "ttf" to FONT_TTF,
  146.         "woff" to FONT_WOFF,
  147.         "woff2" to FONT_WOFF2,
  148.         "gif" to IMAGE_GIF,
  149.         "jpeg" to IMAGE_JPEG,
  150.         "jpg" to IMAGE_JPEG,
  151.         "png" to IMAGE_PNG,
  152.         "tiff" to IMAGE_TIFF,
  153.         "tif" to IMAGE_TIFF,
  154.         "svg" to IMAGE_SVG,
  155.         "ico" to IMAGE_ICO,
  156.         "webp" to IMAGE_WEBP,
  157.         "avif" to IMAGE_AVIF,
  158.         "csv" to TEXT_CSV,
  159.         "properties" to TEXT_X_JAVA_PROPERTIES,
  160.         "js" to TEXT_JAVASCRIPT,
  161.         "css" to TEXT_CSS,
  162.         "html" to TEXT_HTML,
  163.         "htm" to TEXT_HTML,
  164.         "md" to TEXT_MARKDOWN,
  165.         "txt" to TEXT_PLAIN,
  166.         "log" to TEXT_PLAIN,
  167.         "rtx" to TEXT_RICHTEXT,
  168.         "tsv" to TEXT_TAB_SEPARATED_VALUES,
  169.         "ics" to TEXT_CALENDAR,
  170.         "mpeg" to VIDEO_MPEG,
  171.         "mpg" to VIDEO_MPEG,
  172.         "mpe" to VIDEO_MPEG,
  173.         "m1v" to VIDEO_MPEG,
  174.         "m2v" to VIDEO_MPEG,
  175.         "qt" to VIDEO_QUICKTIME,
  176.         "mov" to VIDEO_QUICKTIME,
  177.         "avi" to VIDEO_X_MSVIDEO,
  178.         "mp4" to VIDEO_MP4,
  179.         "ogv" to VIDEO_OGG,
  180.         "webm" to VIDEO_WEBM,
  181.     )
  182. }

  183. internal val EXTENSIONS_BY_MEDIA: Map<MediaType, List<String>> by lazy {
  184.     MEDIA_TYPES_EXTENSIONS.entries
  185.         .groupBy { it.value }
  186.         .mapValues {
  187.             it.value.map { entry -> entry.key }
  188.         }
  189. }

  190. fun parseMediaType(fullType: String): MediaType {
  191.     val groupType = fullType.split("/")
  192.     require(groupType.size == 2) { "Media type format must be <type>/<subtype>: $fullType" }

  193.     val groupText = groupType.first().uppercase()
  194.     val group = if (groupText == "*") ANY else MediaTypeGroup.valueOf(groupText)
  195.     val type = groupType.last()
  196.     return MediaType(group, type)
  197. }

  198. fun mediaTypeOfOrNull(uri: URI): MediaType? =
  199.     mediaTypeOfOrNull(pathExtension(uri.path))

  200. fun mediaTypeOfOrNull(url: URL): MediaType? =
  201.     mediaTypeOfOrNull(pathExtension(url.file))

  202. fun mediaTypeOfOrNull(file: File): MediaType? =
  203.     mediaTypeOfOrNull(file.extension)

  204. fun mediaTypeOfOrNull(path: Path): MediaType? =
  205.     mediaTypeOfOrNull(path.extension)

  206. fun mediaTypeOfOrNull(extension: String): MediaType? =
  207.     MEDIA_TYPES_EXTENSIONS[extension]

  208. fun mediaTypeOf(uri: URI): MediaType =
  209.     mediaTypeOfOrNull(uri) ?: error("Media type not found for: '$uri' URI")

  210. fun mediaTypeOf(url: URL): MediaType =
  211.     mediaTypeOfOrNull(url) ?: error("Media type not found for: '$url' URL")

  212. fun mediaTypeOf(file: File): MediaType =
  213.     mediaTypeOfOrNull(file) ?: error("Media type not found for: '$file' file")

  214. fun mediaTypeOf(path: Path): MediaType =
  215.     mediaTypeOfOrNull(path) ?: error("Media type not found for: '$path' path")

  216. fun mediaTypeOf(extension: String): MediaType =
  217.     mediaTypeOfOrNull(extension) ?: error("Media type not found for: '$extension' extension")

  218. fun extensionsOf(mediaType: MediaType): List<String> =
  219.     EXTENSIONS_BY_MEDIA[mediaType] ?: emptyList()

  220. fun pathExtension(path: String): String =
  221.     path.substringAfterLast('.')