package middleware import ( "bufio" "crypto/rand" "io" "strings" "sync" ) const ( _ = int64(1 << (10 * iota)) // ignore first value by assigning to blank identifier // KB is 1 KiloByte = 1024 bytes KB // MB is 1 Megabyte = 1_048_576 bytes MB // GB is 1 Gigabyte = 1_073_741_824 bytes GB // TB is 1 Terabyte = 1_099_511_627_776 bytes TB // PB is 1 Petabyte = 1_125_899_906_842_624 bytes PB // EB is 1 Exabyte = 1_152_921_504_606_847_000 bytes EB ) func matchScheme(domain, pattern string) bool { didx := strings.Index(domain, ":") pidx := strings.Index(pattern, ":") return didx != -1 && pidx != -1 && domain[:didx] == pattern[:pidx] } // matchSubdomain compares authority with wildcard func matchSubdomain(domain, pattern string) bool { if !matchScheme(domain, pattern) { return false } didx := strings.Index(domain, "://") pidx := strings.Index(pattern, "://") if didx == -1 || pidx == -1 { return false } domAuth := domain[didx+3:] // to avoid long loop by invalid long domain if len(domAuth) > 253 { return false } patAuth := pattern[pidx+3:] domComp := strings.Split(domAuth, ".") patComp := strings.Split(patAuth, ".") for i := len(domComp)/2 - 1; i >= 0; i-- { opp := len(domComp) - 1 - i domComp[i], domComp[opp] = domComp[opp], domComp[i] } for i := len(patComp)/2 - 1; i >= 0; i-- { opp := len(patComp) - 1 - i patComp[i], patComp[opp] = patComp[opp], patComp[i] } for i, v := range domComp { if len(patComp) <= i { return false } p := patComp[i] if p == "*" { return true } if p != v { return false } } return false } func createRandomStringGenerator(length uint8) func() string { return func() string { return randomString(length) } } // https://tip.golang.org/doc/go1.19#:~:text=Read%20no%20longer%20buffers%20random%20data%20obtained%20from%20the%20operating%20system%20between%20calls var randomReaderPool = sync.Pool{New: func() interface{} { return bufio.NewReader(rand.Reader) }} const randomStringCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" const randomStringCharsetLen = 52 // len(randomStringCharset) const randomStringMaxByte = 255 - (256 % randomStringCharsetLen) func randomString(length uint8) string { reader := randomReaderPool.Get().(*bufio.Reader) defer randomReaderPool.Put(reader) b := make([]byte, length) r := make([]byte, length+(length/4)) // perf: avoid read from rand.Reader many times var i uint8 = 0 for { _, err := io.ReadFull(reader, r) if err != nil { panic("unexpected error happened when reading from bufio.NewReader(crypto/rand.Reader)") } for _, rb := range r { if rb > randomStringMaxByte { // Skip this number to avoid bias. continue } b[i] = randomStringCharset[rb%randomStringCharsetLen] i++ if i == length { return string(b) } } } }