http.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
  2. // 🤖 Github Repository: https://github.com/gofiber/fiber
  3. // 📌 API Documentation: https://docs.gofiber.io
  4. package utils
  5. import (
  6. "mime"
  7. "strings"
  8. )
  9. const MIMEOctetStream = "application/octet-stream"
  10. const (
  11. contentTypeApplicationJSON = "application/json"
  12. contentTypeApplicationXML = "application/xml"
  13. contentTypeApplicationFormURLEncoded = "application/x-www-form-urlencoded"
  14. contentTypePrefixApplicationWithSlashLen = len("application/")
  15. )
  16. // GetMIME returns the content-type of a file extension
  17. func GetMIME(extension string) string {
  18. if len(extension) == 0 {
  19. return ""
  20. }
  21. // Normalize extension once at the start to avoid repeated checks
  22. var extWithoutDot string
  23. var extWithDot string
  24. if extension[0] == '.' {
  25. extWithoutDot = extension[1:]
  26. extWithDot = extension
  27. } else {
  28. extWithoutDot = extension
  29. extWithDot = "." + extension
  30. }
  31. // Single map lookup with normalized key
  32. if foundMime := mimeExtensions[extWithoutDot]; len(foundMime) > 0 {
  33. return foundMime
  34. }
  35. // Fallback to mime package with pre-computed extension
  36. if foundMime := mime.TypeByExtension(extWithDot); foundMime != "" {
  37. return foundMime
  38. }
  39. return MIMEOctetStream
  40. }
  41. // ParseVendorSpecificContentType check if content type is vendor specific and
  42. // if it is parsable to any known types. If its not vendor specific then returns
  43. // the original content type.
  44. func ParseVendorSpecificContentType(cType string, caseInsensitive ...bool) string {
  45. useLower := len(caseInsensitive) > 0 && caseInsensitive[0]
  46. working := cType
  47. if useLower {
  48. // Content types are case-insensitive. Normalize if requested using the
  49. // utils.ToLower function to avoid allocations when possible.
  50. working = ToLower(cType)
  51. }
  52. plusIndex := strings.IndexByte(working, '+')
  53. if plusIndex == -1 {
  54. return cType
  55. }
  56. var parsableType string
  57. if semiColonIndex := strings.IndexByte(working, ';'); semiColonIndex == -1 {
  58. parsableType = working[plusIndex+1:]
  59. } else if plusIndex < semiColonIndex {
  60. parsableType = working[plusIndex+1 : semiColonIndex]
  61. } else {
  62. return cType[:semiColonIndex]
  63. }
  64. slashIndex := strings.IndexByte(working, '/')
  65. if slashIndex == -1 {
  66. return cType
  67. }
  68. if slashIndex+1 == contentTypePrefixApplicationWithSlashLen {
  69. switch parsableType {
  70. case "json":
  71. return contentTypeApplicationJSON
  72. case "xml":
  73. return contentTypeApplicationXML
  74. case "x-www-form-urlencoded":
  75. return contentTypeApplicationFormURLEncoded
  76. }
  77. }
  78. return working[:slashIndex+1] + parsableType
  79. }
  80. // limits for HTTP statuscodes
  81. const (
  82. statusMessageMin = 100
  83. statusMessageMax = 511
  84. )
  85. // StatusMessage returns the correct message for the provided HTTP statuscode
  86. func StatusMessage(status int) string {
  87. if status < statusMessageMin || status > statusMessageMax {
  88. return ""
  89. }
  90. return statusMessage[status]
  91. }
  92. // NOTE: Keep this in sync with fiber's status code list
  93. var statusMessage = []string{
  94. 100: "Continue", // StatusContinue
  95. 101: "Switching Protocols", // StatusSwitchingProtocols
  96. 102: "Processing", // StatusProcessing
  97. 103: "Early Hints", // StatusEarlyHints
  98. 200: "OK", // StatusOK
  99. 201: "Created", // StatusCreated
  100. 202: "Accepted", // StatusAccepted
  101. 203: "Non-Authoritative Information", // StatusNonAuthoritativeInformation
  102. 204: "No Content", // StatusNoContent
  103. 205: "Reset Content", // StatusResetContent
  104. 206: "Partial Content", // StatusPartialContent
  105. 207: "Multi-Status", // StatusMultiStatus
  106. 208: "Already Reported", // StatusAlreadyReported
  107. 226: "IM Used", // StatusIMUsed
  108. 300: "Multiple Choices", // StatusMultipleChoices
  109. 301: "Moved Permanently", // StatusMovedPermanently
  110. 302: "Found", // StatusFound
  111. 303: "See Other", // StatusSeeOther
  112. 304: "Not Modified", // StatusNotModified
  113. 305: "Use Proxy", // StatusUseProxy
  114. 306: "Switch Proxy", // StatusSwitchProxy
  115. 307: "Temporary Redirect", // StatusTemporaryRedirect
  116. 308: "Permanent Redirect", // StatusPermanentRedirect
  117. 400: "Bad Request", // StatusBadRequest
  118. 401: "Unauthorized", // StatusUnauthorized
  119. 402: "Payment Required", // StatusPaymentRequired
  120. 403: "Forbidden", // StatusForbidden
  121. 404: "Not Found", // StatusNotFound
  122. 405: "Method Not Allowed", // StatusMethodNotAllowed
  123. 406: "Not Acceptable", // StatusNotAcceptable
  124. 407: "Proxy Authentication Required", // StatusProxyAuthRequired
  125. 408: "Request Timeout", // StatusRequestTimeout
  126. 409: "Conflict", // StatusConflict
  127. 410: "Gone", // StatusGone
  128. 411: "Length Required", // StatusLengthRequired
  129. 412: "Precondition Failed", // StatusPreconditionFailed
  130. 413: "Request Entity Too Large", // StatusRequestEntityTooLarge
  131. 414: "Request URI Too Long", // StatusRequestURITooLong
  132. 415: "Unsupported Media Type", // StatusUnsupportedMediaType
  133. 416: "Requested Range Not Satisfiable", // StatusRequestedRangeNotSatisfiable
  134. 417: "Expectation Failed", // StatusExpectationFailed
  135. 418: "I'm a teapot", // StatusTeapot
  136. 421: "Misdirected Request", // StatusMisdirectedRequest
  137. 422: "Unprocessable Entity", // StatusUnprocessableEntity
  138. 423: "Locked", // StatusLocked
  139. 424: "Failed Dependency", // StatusFailedDependency
  140. 425: "Too Early", // StatusTooEarly
  141. 426: "Upgrade Required", // StatusUpgradeRequired
  142. 428: "Precondition Required", // StatusPreconditionRequired
  143. 429: "Too Many Requests", // StatusTooManyRequests
  144. 431: "Request Header Fields Too Large", // StatusRequestHeaderFieldsTooLarge
  145. 451: "Unavailable For Legal Reasons", // StatusUnavailableForLegalReasons
  146. 500: "Internal Server Error", // StatusInternalServerError
  147. 501: "Not Implemented", // StatusNotImplemented
  148. 502: "Bad Gateway", // StatusBadGateway
  149. 503: "Service Unavailable", // StatusServiceUnavailable
  150. 504: "Gateway Timeout", // StatusGatewayTimeout
  151. 505: "HTTP Version Not Supported", // StatusHTTPVersionNotSupported
  152. 506: "Variant Also Negotiates", // StatusVariantAlsoNegotiates
  153. 507: "Insufficient Storage", // StatusInsufficientStorage
  154. 508: "Loop Detected", // StatusLoopDetected
  155. 510: "Not Extended", // StatusNotExtended
  156. 511: "Network Authentication Required", // StatusNetworkAuthenticationRequired
  157. }
  158. // MIME types were copied from https://github.com/nginx/nginx/blob/67d2a9541826ecd5db97d604f23460210fd3e517/conf/mime.types with the following updates:
  159. // - Use "application/xml" instead of "text/xml" as recommended per https://datatracker.ietf.org/doc/html/rfc7303#section-4.1
  160. // - Use "text/javascript" instead of "application/javascript" as recommended per https://www.rfc-editor.org/rfc/rfc9239#name-text-javascript
  161. // - Use "application/vnd.msgpack" from https://www.iana.org/assignments/media-types/application/vnd.msgpack
  162. var mimeExtensions = map[string]string{
  163. "html": "text/html",
  164. "htm": "text/html",
  165. "shtml": "text/html",
  166. "css": "text/css",
  167. "xml": "application/xml",
  168. "cbor": "application/cbor",
  169. "gif": "image/gif",
  170. "jpeg": "image/jpeg",
  171. "jpg": "image/jpeg",
  172. "js": "text/javascript",
  173. "atom": "application/atom+xml",
  174. "rss": "application/rss+xml",
  175. "mml": "text/mathml",
  176. "txt": "text/plain",
  177. "jad": "text/vnd.sun.j2me.app-descriptor",
  178. "wml": "text/vnd.wap.wml",
  179. "htc": "text/x-component",
  180. "avif": "image/avif",
  181. "png": "image/png",
  182. "svg": "image/svg+xml",
  183. "svgz": "image/svg+xml",
  184. "tif": "image/tiff",
  185. "tiff": "image/tiff",
  186. "wbmp": "image/vnd.wap.wbmp",
  187. "webp": "image/webp",
  188. "ico": "image/x-icon",
  189. "jng": "image/x-jng",
  190. "bmp": "image/x-ms-bmp",
  191. "woff": "font/woff",
  192. "woff2": "font/woff2",
  193. "jar": "application/java-archive",
  194. "war": "application/java-archive",
  195. "ear": "application/java-archive",
  196. "json": "application/json",
  197. "msgpack": "application/vnd.msgpack",
  198. "hqx": "application/mac-binhex40",
  199. "doc": "application/msword",
  200. "pdf": "application/pdf",
  201. "ps": "application/postscript",
  202. "eps": "application/postscript",
  203. "ai": "application/postscript",
  204. "rtf": "application/rtf",
  205. "m3u8": "application/vnd.apple.mpegurl",
  206. "kml": "application/vnd.google-earth.kml+xml",
  207. "kmz": "application/vnd.google-earth.kmz",
  208. "xls": "application/vnd.ms-excel",
  209. "eot": "application/vnd.ms-fontobject",
  210. "ppt": "application/vnd.ms-powerpoint",
  211. "odg": "application/vnd.oasis.opendocument.graphics",
  212. "odp": "application/vnd.oasis.opendocument.presentation",
  213. "ods": "application/vnd.oasis.opendocument.spreadsheet",
  214. "odt": "application/vnd.oasis.opendocument.text",
  215. "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  216. "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  217. "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  218. "wmlc": "application/vnd.wap.wmlc",
  219. "wasm": "application/wasm",
  220. "7z": "application/x-7z-compressed",
  221. "cco": "application/x-cocoa",
  222. "jardiff": "application/x-java-archive-diff",
  223. "jnlp": "application/x-java-jnlp-file",
  224. "run": "application/x-makeself",
  225. "pl": "application/x-perl",
  226. "pm": "application/x-perl",
  227. "prc": "application/x-pilot",
  228. "pdb": "application/x-pilot",
  229. "rar": "application/x-rar-compressed",
  230. "rpm": "application/x-redhat-package-manager",
  231. "sea": "application/x-sea",
  232. "swf": "application/x-shockwave-flash",
  233. "sit": "application/x-stuffit",
  234. "tcl": "application/x-tcl",
  235. "tk": "application/x-tcl",
  236. "der": "application/x-x509-ca-cert",
  237. "pem": "application/x-x509-ca-cert",
  238. "crt": "application/x-x509-ca-cert",
  239. "xpi": "application/x-xpinstall",
  240. "xhtml": "application/xhtml+xml",
  241. "xspf": "application/xspf+xml",
  242. "zip": "application/zip",
  243. "zst": "application/zstd",
  244. "bin": "application/octet-stream",
  245. "exe": "application/octet-stream",
  246. "dll": "application/octet-stream",
  247. "deb": "application/octet-stream",
  248. "dmg": "application/octet-stream",
  249. "iso": "application/octet-stream",
  250. "img": "application/octet-stream",
  251. "msi": "application/octet-stream",
  252. "msp": "application/octet-stream",
  253. "msm": "application/octet-stream",
  254. "mid": "audio/midi",
  255. "midi": "audio/midi",
  256. "kar": "audio/midi",
  257. "mp3": "audio/mpeg",
  258. "ogg": "audio/ogg",
  259. "m4a": "audio/x-m4a",
  260. "ra": "audio/x-realaudio",
  261. "3gpp": "video/3gpp",
  262. "3gp": "video/3gpp",
  263. "ts": "video/mp2t",
  264. "mp4": "video/mp4",
  265. "mpeg": "video/mpeg",
  266. "mpg": "video/mpeg",
  267. "mov": "video/quicktime",
  268. "webm": "video/webm",
  269. "flv": "video/x-flv",
  270. "m4v": "video/x-m4v",
  271. "mng": "video/x-mng",
  272. "asx": "video/x-ms-asf",
  273. "asf": "video/x-ms-asf",
  274. "wmv": "video/x-ms-wmv",
  275. "avi": "video/x-msvideo",
  276. }