about summary refs log tree commit diff
path: root/route.go
blob: 1950307ea8a0b576b6c8080ae4387e52f32bcf26 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package mooh

import (
	"regexp"
	"strings"
)

type fn map[string]func(*Request) (Response, error)

type Route struct {
	Path                    string
	Executors               fn
	Components              []string
	RequiredNamedComponents map[string]bool
	OptionalNamedComponents map[string]bool
	Length                  int
}

type Match struct {
	Path    string
	Route   *Route
	Mapping map[string]string
	Method  string
}

var componentIsVariable = regexp.MustCompile("^:")
var namedComponentsRegex = regexp.MustCompile("^:(.*)$")

func (self *Route) Match(request Request) *Match {

	methodMatch := false
	for m, _ := range self.Executors {
		if m == request.Method {
			methodMatch = true
		}
	}
	if methodMatch == false {
		return nil
	}

	components := strings.Split(request.Request.URL.Path, "/")

	if len(components) < self.Length {
		return nil
	}

	mapping := map[string]string{}

	for i, c := range self.Components {
		p := components[i]

		if componentIsVariable.MatchString(c) == true {
			mapping[c] = p
		} else {
			if p != c {
				return nil
			}
		}
	}

	match := &Match{
		Path:    request.Request.URL.Path,
		Route:   self,
		Mapping: mapping,
		Method:  request.Method,
	}

	return match
}

func (self *Route) Execute(request *Request) (Response, error) {
	code := self.Executors[request.Method]
	return code(request)
}

func MakeRoute(path string, method string, code func(*Request) (Response, error)) Route {

	components := []string{}

	for _, c := range strings.Split(path, "/") {
		if c != "" {
			components = append(components, c)
		}
	}

	namedComponents := getNamedComponents(components)
	exec := fn{method: code}

	route := Route{
		Path:                    path,
		Executors:               exec,
		Components:              components,
		RequiredNamedComponents: namedComponents,
		Length:                  len(components),
	}

	return route
}

func getNamedComponents(components []string) map[string]bool {
	namedComponents := map[string]bool{}
	for _, c := range components {
		if namedComponentsRegex.MatchString(c) == true {
			namedComponents[c] = true
		}
	}
	return namedComponents
}