From 0ad196a0130164e6a18da7ee20156de0d508f8a3 Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Mon, 22 Apr 2013 20:30:25 -0700 Subject: Change the interface to create routes. Previously, to create a route, a user would call the AddRoute function, and pass three arguments (the path, the HTTP method and the function). This interface is way too limited if we need/want to expand what a route is in the future. Instead, we keep calling the AddRoute function to create a route, but this time the user pass a Route structure. The AddRoute will then apply a few transformations and connect the route to the router. --- dispatcher.go | 27 ++++++++++++------------- mooh.go | 1 + request_test.go | 3 ++- route.go | 63 +++++++++++++++++++++++---------------------------------- router_test.go | 22 ++++++++++---------- 5 files changed, 52 insertions(+), 64 deletions(-) diff --git a/dispatcher.go b/dispatcher.go index 3b98b5f..7e17e54 100644 --- a/dispatcher.go +++ b/dispatcher.go @@ -8,7 +8,7 @@ import ( ) type Dispatcher struct { - Routes []Route + Routes []*Route RouteAccess map[string]*Route } @@ -18,26 +18,26 @@ func BuildDispatcher() Dispatcher { return router } -func (self *Dispatcher) GetRoute(path string) *Route { - r := self.RouteAccess[path] +func (self *Dispatcher) GetRoute(route *Route) *Route { + // r := self.RouteAccess[route.Path] - if r != nil { - return r - } + // if r != nil { + // return r + // } return nil } -func (self *Dispatcher) AddRoute(path string, method string, code func(*Request) (Response, error)) { - r := self.GetRoute(path) +func (self *Dispatcher) AddRoute(route *Route) { + r := self.GetRoute(route) if r == nil { - route := MakeRoute(path, method, code) + route.init() self.Routes = append(self.Routes, route) - self.RouteAccess[path] = &route + // self.RouteAccess[route.Path] = route } else { - r.Executors[method] = code - r.Methods[method] = true + // // r.Executors[method] = code + // // r.Methods[method] = true } } @@ -62,7 +62,6 @@ func (self *Dispatcher) Match(request *http.Request) (*Match, error) { } else { return self.disambiguateMatches(request.URL.Path, matches) } - return nil, nil } func (self *Dispatcher) disambiguateMatches(path string, matches []*Match) (*Match, error) { @@ -70,7 +69,7 @@ func (self *Dispatcher) disambiguateMatches(path string, matches []*Match) (*Mat found := []*Match{} for _, m := range matches { - req := m.Route.RequiredNamedComponents + req := m.Route.requiredNamedComponents vars := len(req) if min == -1 || vars < min { found = append(found, m) diff --git a/mooh.go b/mooh.go index a8858a6..2bcca75 100644 --- a/mooh.go +++ b/mooh.go @@ -10,6 +10,7 @@ func (self *Dispatcher) ServeHTTP(resp http.ResponseWriter, req *http.Request) { match, err := self.Match(req) if err != nil { + fmt.Println(err) fmt.Printf("oups") return } diff --git a/request_test.go b/request_test.go index e622b7e..5eb58a0 100644 --- a/request_test.go +++ b/request_test.go @@ -13,12 +13,13 @@ func testRequestRoute(req *Request) (Response, error) { func buildDispatcher() Dispatcher { router := BuildDispatcher() - router.AddRoute("/foo/:bar", "GET", testRequestRoute) + router.AddRoute(&Route{Method: "GET", Path: "/foo/:bar", Code: testRequestRoute}) return router } func TestBasicRequest(t *testing.T) { router := buildDispatcher() + t.Log(router.Routes[0].components) r := &http.Request{Method: "GET", URL: &url.URL{Path: "/foo/bar"}} m, _ := router.Match(r) request := NewRequest(r, m) diff --git a/route.go b/route.go index 9fc86ee..b724a04 100644 --- a/route.go +++ b/route.go @@ -9,14 +9,14 @@ type fn func(*Request) (Response, error) type fns map[string]fn type Route struct { + Method string Path string - Executors fns - Components []string - RequiredNamedComponents map[string]bool - OptionalNamedComponents map[string]bool - Length int - LengthWithoutOptional int - Methods map[string]bool + Code fn + components []string + requiredNamedComponents map[string]bool + optionalNamedComponents map[string]bool + length int + lengthWithoutOptional int } type Match struct { @@ -38,17 +38,17 @@ func (self *Route) convertComponentName(name string) string { func (self *Route) Match(method string, components []string) *Match { - if self.Methods[method] != true { + if self.Method != method { return nil } - if len(components) < self.LengthWithoutOptional || len(components) > self.Length { + if len(components) < self.lengthWithoutOptional || len(components) > self.length { return nil } mapping := map[string]string{} - for i, c := range self.Components { + for i, c := range self.components { if componentsIsOptional.MatchString(c) { break } @@ -72,44 +72,31 @@ func (self *Route) Match(method string, components []string) *Match { } func (self *Route) Execute(request *Request) (Response, error) { - code := self.Executors[request.Method] - return code(request) + return self.Code(request) } -func MakeRoute(path string, method string, code fn) Route { +func (self *Route) init() { - components := []string{} + self.components = []string{} - for _, c := range strings.Split(path, "/") { - components = append(components, c) + for _, c := range strings.Split(self.Path, "/") { + self.components = append(self.components, c) } + self.length = len(self.components) - reqComponents, optComponents := getNamedComponents(components) - exec := fns{method: code} - - route := Route{ - Path: path, - Executors: exec, - Components: components, - RequiredNamedComponents: reqComponents, - OptionalNamedComponents: optComponents, - Length: len(components), - LengthWithoutOptional: len(components) - len(optComponents), - Methods: map[string]bool{method: true}, - } - - return route + self.getNamedComponents() } -func getNamedComponents(components []string) (map[string]bool, map[string]bool) { - reqComponents := map[string]bool{} - optComponents := map[string]bool{} - for _, c := range components { +func (self *Route) getNamedComponents() { + self.requiredNamedComponents = map[string]bool{} + self.optionalNamedComponents = map[string]bool{} + + for _, c := range self.components { if namedComponentsRegex.MatchString(c) == true { - reqComponents[c] = true + self.requiredNamedComponents[c] = true } else if componentsIsOptional.MatchString(c) == true { - optComponents[c] = true + self.optionalNamedComponents[c] = true } } - return reqComponents, optComponents + self.lengthWithoutOptional = self.length - len(self.optionalNamedComponents) } diff --git a/router_test.go b/router_test.go index 497f547..bc6bc0c 100644 --- a/router_test.go +++ b/router_test.go @@ -14,9 +14,9 @@ func testRoute(req *Request) (Response, error) { func TestBasic(t *testing.T) { router := BuildDispatcher() - router.AddRoute("/", "GET", testRoute) - router.AddRoute("/blog/:year/:month/:day", "GET", testRoute) - router.AddRoute("/blog", "GET", testRoute) + router.AddRoute(&Route{Method: "GET", Path: "/", Code: testRoute}) + router.AddRoute(&Route{Method: "GET", Path: "/blog/:year/:month/:day", Code: testRoute}) + router.AddRoute(&Route{Method: "GET", Path: "/blog", Code: testRoute}) if router.Routes[0].Path != "/" { t.Fatal() @@ -31,8 +31,8 @@ func TestBasic(t *testing.T) { func TestMatch(t *testing.T) { router := BuildDispatcher() - router.AddRoute("/blog/:year/:month/:day", "GET", testRoute) - router.AddRoute("/blog", "GET", testRoute) + router.AddRoute(&Route{Method: "GET", Path: "/blog/:year/:month/:day", Code: testRoute}) + router.AddRoute(&Route{Method: "GET", Path: "/blog", Code: testRoute}) pathToTests := []url.URL{ url.URL{Path: "/blog"}, @@ -53,8 +53,8 @@ func TestMatch(t *testing.T) { func TestMatchOptional(t *testing.T) { router := BuildDispatcher() - router.AddRoute("/blog/?:year", "GET", testRoute) - router.AddRoute("/blog/:year/?:month", "GET", testRoute) + router.AddRoute(&Route{Path: "/blog/?:year", Method: "GET", Code: testRoute}) + router.AddRoute(&Route{Path: "/blog/:year/?:month", Method: "GET", Code: testRoute}) pathToTests := []url.URL{ url.URL{Path: "/blog"}, @@ -75,8 +75,8 @@ func TestMatchOptional(t *testing.T) { func TestAmbigiousSimple(t *testing.T) { router := BuildDispatcher() - router.AddRoute("/foo/bar", "GET", testRoute) - router.AddRoute("/foo/:bar", "GET", testRoute) + router.AddRoute(&Route{Path: "/foo/bar", Method: "GET", Code: testRoute}) + router.AddRoute(&Route{Path: "/foo/:bar", Method: "GET", Code: testRoute}) r := &http.Request{Method: "GET", URL: &url.URL{Path: "/foo/bar"}} m, _ := router.Match(r) @@ -89,8 +89,8 @@ func TestAmbigiousSimple(t *testing.T) { func TestAmbigiousFail(t *testing.T) { router := BuildDispatcher() - router.AddRoute("/foo/:bar", "GET", testRoute) - router.AddRoute("/:foo/bar", "GET", testRoute) + router.AddRoute(&Route{Path: "/foo/:bar", Method: "GET", Code: testRoute}) + router.AddRoute(&Route{Path: "/:foo/bar", Method: "GET", Code: testRoute}) r := &http.Request{Method: "GET", URL: &url.URL{Path: "/foo/bar"}} m, err := router.Match(r) -- cgit 1.4.1