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