// https://fiber.wiki package fiber import ( "bytes" "fmt" "net" "os" "path/filepath" "regexp" "strings" "time" "unsafe" websocket "github.com/fasthttp/websocket" schema "github.com/gorilla/schema" fasthttp "github.com/valyala/fasthttp" ) var schemaDecoder = schema.NewDecoder() var socketUpgrade = websocket.FastHTTPUpgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(fctx *fasthttp.RequestCtx) bool { return true }, } // MIME types const ( MIMEApplicationJSON = "application/json" MIMEApplicationJavaScript = "application/javascript" MIMEApplicationXML = "application/xml" MIMETextXML = "text/xml" MIMEApplicationForm = "application/x-www-form-urlencoded" MIMEApplicationProtobuf = "application/protobuf" MIMEApplicationMsgpack = "application/msgpack" MIMETextHTML = "text/html" MIMETextPlain = "text/plain" MIMEMultipartForm = "multipart/form-data" MIMEOctetStream = "application/octet-stream" ) func getParams(path string) (params []string) { if len(path) < 1 { return } segments := strings.Split(path, "/") replacer := strings.NewReplacer(":", "", "?", "") for _, s := range segments { if s == "" { continue } else if s[0] == ':' { params = append(params, replacer.Replace(s)) } if strings.Contains(s, "*") { params = append(params, "*") } } return } func getRegex(path string) (*regexp.Regexp, error) { pattern := "^" segments := strings.Split(path, "/") for _, s := range segments { if s == "" { continue } if s[0] == ':' { if strings.Contains(s, "?") { pattern += "(?:/([^/]+?))?" } else { pattern += "/(?:([^/]+?))" } } else if s[0] == '*' { pattern += "/(.*)" } else { pattern += "/" + s } } pattern += "/?$" regex, err := regexp.Compile(pattern) return regex, err } func getFiles(root string) (files []string, dir bool, err error) { root = filepath.Clean(root) if _, err := os.Lstat(root); err != nil { return files, dir, fmt.Errorf("%s", err) } err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if !info.IsDir() { files = append(files, path) } else { dir = true } return err }) return } func getType(ext string) (mime string) { if ext == "" { return mime } if ext[0] == '.' { mime = extensionMIME[ext[1:]] } else { mime = extensionMIME[ext] } if mime == "" { return MIMEOctetStream } return mime } func getStatus(status int) (msg string) { return statusMessage[status] } // #nosec G103 // getString converts byte slice to a string without memory allocation. // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ . func getString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // #nosec G103 // getBytes converts string to a byte slice without memory allocation. // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ . func getBytes(s string) (b []byte) { return *(*[]byte)(unsafe.Pointer(&s)) } // https://golang.org/src/net/net.go#L113 // Helper methods for application#test type testConn struct { net.Conn r bytes.Buffer w bytes.Buffer } func (c *testConn) RemoteAddr() net.Addr { return &net.TCPAddr{ IP: net.IPv4(0, 0, 0, 0), } } func (c *testConn) LocalAddr() net.Addr { return c.RemoteAddr() } func (c *testConn) Read(b []byte) (int, error) { return c.r.Read(b) } func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) } func (c *testConn) Close() error { return nil } func (c *testConn) SetDeadline(t time.Time) error { return nil } func (c *testConn) SetReadDeadline(t time.Time) error { return nil } func (c *testConn) SetWriteDeadline(t time.Time) error { return nil } // HTTP status codes var statusMessage = map[int]string{ 100: "Continue", 101: "Switching Protocols", 102: "Processing", 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 208: "Already Reported", 226: "IM Used", 300: "Multiple Choices", 301: "Moved Permanently", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 306: "Switch Proxy", 307: "Temporary Redirect", 308: "Permanent Redirect", 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Request Entity Too Large", 414: "Request URI Too Long", 415: "Unsupported Media Type", 416: "Requested Range Not Satisfiable", 417: "Expectation Failed", 418: "I'm a teapot", 422: "Unprocessable Entity", 423: "Locked", 424: "Failed Dependency", 426: "Upgrade Required", 428: "Precondition Required", 429: "Too Many Requests", 431: "Request Header Fields Too Large", 451: "Unavailable For Legal Reasons", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported", 506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected", 510: "Not Extended", 511: "Network Authentication Required", } // MIME types for file extensions var extensionMIME = map[string]string{ "html": "text/html", "htm": "text/html", "shtml": "text/html", "css": "text/css", "gif": "image/gif", "jpeg": "image/jpeg", "jpg": "image/jpeg", "xml": "application/xml", "js": "application/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", "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", "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", "wmlc": "application/vnd.wap.wmlc", "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", "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", }