package router import ( "context" "net/http" "regexp" "strconv" "strings" ) type closure func(http.ResponseWriter, *http.Request) type Middleware func(http.ResponseWriter, *http.Request) (bool, *http.Request) //Route struct de uma rota type Route struct { Method string Pattern string Handler closure Middlewares []Middleware } //Routes array of route type Routes []Route var routes Routes //Match retorna a rota encontrada func (routes Routes) Match(w http.ResponseWriter, r *http.Request) bool { url := r.URL.Path for _, element := range routes { when := element.Pattern pattern := toRegex(when) items := regexSubmatch(pattern, url) ctx := context.WithValue(r.Context(), "urlParameters", items) r = r.WithContext(ctx) if items[0] == url { if element.Method != r.Method { //method not allowed w.WriteHeader(405) w.Write(nil) return false } if element.Middlewares != nil && len(element.Middlewares) > 0 { for _, mid := range element.Middlewares { var validator bool validator, r = mid(w, r) if !validator { w.WriteHeader(500) w.Write(nil) return false } } } element.Handler(w, r) return true } } w.WriteHeader(404) w.Write(nil) return false } //PatternURL coloca barra no final de url se não tiver func patternURL(url string) string { lastChar := url[len(url)-1:] if lastChar != "/" { url = url + "/" } return url } //ToRegex converte uma expressao imputada em expressão do go func toRegex(regex string) *regexp.Regexp { return regexp.MustCompile(`(?m)` + regex) } //RegexSubmatch cria os matches aplicando a padrão de regex inputado func regexSubmatch(pattern *regexp.Regexp, str string) []string { data := []string{""} items := pattern.FindAllStringSubmatch(str, -1) if len(items) > 0 { data = items[0] } return data } //ReplaceStringsURL alterar a url imputada colocando as variaveis da url inserida func replaceStringsURL(items []string, urlPattern string) string { for index, element := range items { urlPattern = strings.Replace(urlPattern, "$"+strconv.Itoa(index), element, -1) } return urlPattern }