package patternmatcher import ( "fmt" "regexp" "strings" "golang.org/x/xerrors" ) // RoutePatterns provides a method to generate a regex which will match a URL // path against a collection of patterns. If any of the patterns match the path, // the regex will return a successful match. // // Multiple patterns can be provided and they are matched in order. Example: // - /api/* matches /api/1 but not /api or /api/1/2 // - /api/*/2 matches /api/1/2 but not /api/2 /api/1 // - /api/** matches /api/1, /api/1/2, /api/1/2/3 but not /api // - /api/**/3 matches /api/1/2, /api/1/2/3 but not /api, /api/1 or /api/1/2 // // All patterns support an optional trailing slash. type RoutePatterns []string func (rp RoutePatterns) MustCompile() *regexp.Regexp { re, err := rp.Compile() if err != nil { panic(err) } return re } func (rp RoutePatterns) Compile() (*regexp.Regexp, error) { patterns := make([]string, len(rp)) for i, p := range rp { p = strings.ReplaceAll(p, "**", ".+") p = strings.ReplaceAll(p, "*", "[^/]+") if !strings.HasSuffix(p, "/") { p += "/?" } patterns[i] = p } pattern := fmt.Sprintf("^(%s)$", strings.Join(patterns, "|")) re, err := regexp.Compile(pattern) if err != nil { return nil, xerrors.Errorf("compile regex %q: %w", pattern, err) } return re, nil }