Нет описания

router.go 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package router
  2. import (
  3. "context"
  4. "net/http"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. )
  9. type closure func(http.ResponseWriter, *http.Request)
  10. type Middleware func(http.ResponseWriter, *http.Request) (bool, *http.Request)
  11. //Route struct de uma rota
  12. type Route struct {
  13. Method string
  14. Pattern string
  15. Handler closure
  16. Middlewares []Middleware
  17. }
  18. //Routes array of route
  19. type Routes []Route
  20. var routes Routes
  21. //Match retorna a rota encontrada
  22. func (routes Routes) Match(w http.ResponseWriter, r *http.Request) bool {
  23. url := r.URL.Path
  24. for _, element := range routes {
  25. when := element.Pattern
  26. pattern := toRegex(when)
  27. items := regexSubmatch(pattern, url)
  28. ctx := context.WithValue(r.Context(), "urlParameters", items)
  29. r = r.WithContext(ctx)
  30. if items[0] == url {
  31. if element.Method != r.Method {
  32. //method not allowed
  33. w.WriteHeader(405)
  34. w.Write(nil)
  35. return false
  36. }
  37. if element.Middlewares != nil && len(element.Middlewares) > 0 {
  38. for _, mid := range element.Middlewares {
  39. var validator bool
  40. validator, r = mid(w, r)
  41. if !validator {
  42. w.WriteHeader(500)
  43. w.Write(nil)
  44. return false
  45. }
  46. }
  47. }
  48. element.Handler(w, r)
  49. return true
  50. }
  51. }
  52. w.WriteHeader(404)
  53. w.Write(nil)
  54. return false
  55. }
  56. //PatternURL coloca barra no final de url se não tiver
  57. func patternURL(url string) string {
  58. lastChar := url[len(url)-1:]
  59. if lastChar != "/" {
  60. url = url + "/"
  61. }
  62. return url
  63. }
  64. //ToRegex converte uma expressao imputada em expressão do go
  65. func toRegex(regex string) *regexp.Regexp {
  66. return regexp.MustCompile(`(?m)` + regex)
  67. }
  68. //RegexSubmatch cria os matches aplicando a padrão de regex inputado
  69. func regexSubmatch(pattern *regexp.Regexp, str string) []string {
  70. data := []string{""}
  71. items := pattern.FindAllStringSubmatch(str, -1)
  72. if len(items) > 0 {
  73. data = items[0]
  74. }
  75. return data
  76. }
  77. //ReplaceStringsURL alterar a url imputada colocando as variaveis da url inserida
  78. func replaceStringsURL(items []string, urlPattern string) string {
  79. for index, element := range items {
  80. urlPattern = strings.Replace(urlPattern, "$"+strconv.Itoa(index), element, -1)
  81. }
  82. return urlPattern
  83. }