Skip to content

Commit

Permalink
Importing module routes under the parent path
Browse files Browse the repository at this point in the history
  • Loading branch information
landaire committed Dec 22, 2013
1 parent 2b0599a commit 4fb6b7b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
2 changes: 1 addition & 1 deletion fakeapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func startFakeBookingApp() {

MainRouter = NewRouter("")
routesFile, _ := ioutil.ReadFile(filepath.Join(BasePath, "conf", "routes"))
MainRouter.Routes, _ = parseRoutes("", string(routesFile), false)
MainRouter.Routes, _ = parseRoutes("", "", string(routesFile), false)
MainRouter.updateTree()
MainTemplateLoader = NewTemplateLoader([]string{ViewsPath, path.Join(RevelPath, "templates")})
MainTemplateLoader.Refresh()
Expand Down
37 changes: 29 additions & 8 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (router *Router) Route(req *http.Request) *RouteMatch {
// Refresh re-reads the routes file and re-calculates the routing table.
// Returns an error if a specified action could not be found.
func (router *Router) Refresh() (err *Error) {
router.Routes, err = parseRoutesFile(router.path, true)
router.Routes, err = parseRoutesFile(router.path, "", true)
if err != nil {
return
}
Expand All @@ -158,19 +158,19 @@ func (router *Router) updateTree() *Error {
}

// parseRoutesFile reads the given routes file and returns the contained routes.
func parseRoutesFile(routesPath string, validate bool) ([]*Route, *Error) {
func parseRoutesFile(routesPath, joinedPath string, validate bool) ([]*Route, *Error) {
contentBytes, err := ioutil.ReadFile(routesPath)
if err != nil {
return nil, &Error{
Title: "Failed to load routes file",
Description: err.Error(),
}
}
return parseRoutes(routesPath, string(contentBytes), validate)
return parseRoutes(routesPath, joinedPath, string(contentBytes), validate)
}

// parseRoutes reads the content of a routes file into the routing table.
func parseRoutes(routesPath, content string, validate bool) ([]*Route, *Error) {
func parseRoutes(routesPath, joinedPath, content string, validate bool) ([]*Route, *Error) {
var routes []*Route

// For each line..
Expand All @@ -180,10 +180,12 @@ func parseRoutes(routesPath, content string, validate bool) ([]*Route, *Error) {
continue
}

const modulePrefix = "module:"

// Handle included routes from modules.
// e.g. "module:testrunner" imports all routes from that module.
if strings.HasPrefix(line, "module:") {
moduleRoutes, err := getModuleRoutes(line[len("module:"):], validate)
if strings.HasPrefix(line, modulePrefix) {
moduleRoutes, err := getModuleRoutes(line[len(modulePrefix):], joinedPath, validate)
if err != nil {
return nil, routeError(err, routesPath, content, n)
}
Expand All @@ -197,6 +199,25 @@ func parseRoutes(routesPath, content string, validate bool) ([]*Route, *Error) {
continue
}

joinChar := ""
if !strings.HasSuffix(joinedPath, "/") {
joinChar = ""
}
path = strings.Join([]string{joinedPath, path}, joinChar)

// This will import the module routes under the path described in the
// routes file (joinedPath param). e.g. "* /jobs/ module:jobs" -> all
// routes' paths will have the path /jobs/ prepended to them.
// See #282 for more info
if method == "*" && strings.HasPrefix(action, modulePrefix) {
moduleRoutes, err := getModuleRoutes(action[len(modulePrefix):], path, validate)
if err != nil {
return nil, routeError(err, routesPath, content, n)
}
routes = append(routes, moduleRoutes...)
continue
}

route := NewRoute(method, path, action, fixedArgs, routesPath, n)
routes = append(routes, route)

Expand Down Expand Up @@ -262,15 +283,15 @@ func routeError(err error, routesPath, content string, n int) *Error {

// getModuleRoutes loads the routes file for the given module and returns the
// list of routes.
func getModuleRoutes(moduleName string, validate bool) ([]*Route, *Error) {
func getModuleRoutes(moduleName, joinedPath string, validate bool) ([]*Route, *Error) {
// Look up the module. It may be not found due to the common case of e.g. the
// testrunner module being active only in dev mode.
module, found := ModuleByName(moduleName)
if !found {
INFO.Println("Skipping routes for inactive module", moduleName)
return nil, nil
}
return parseRoutesFile(path.Join(module.Path, "conf", "routes"), validate)
return parseRoutesFile(path.Join(module.Path, "conf", "routes"), joinedPath, validate)
}

// Groups:
Expand Down
6 changes: 3 additions & 3 deletions router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ var routeMatchTestCases = map[*http.Request]*RouteMatch{
func TestRouteMatches(t *testing.T) {
BasePath = "/BasePath"
router := NewRouter("")
router.Routes, _ = parseRoutes("", TEST_ROUTES, false)
router.Routes, _ = parseRoutes("", "", TEST_ROUTES, false)
router.updateTree()
for req, expected := range routeMatchTestCases {
t.Log("Routing:", req.Method, req.URL)
Expand Down Expand Up @@ -276,7 +276,7 @@ var reverseRoutingTestCases = map[*ReverseRouteArgs]*ActionDefinition{

func TestReverseRouting(t *testing.T) {
router := NewRouter("")
router.Routes, _ = parseRoutes("", TEST_ROUTES, false)
router.Routes, _ = parseRoutes("", "", TEST_ROUTES, false)
for routeArgs, expected := range reverseRoutingTestCases {
actual := router.Reverse(routeArgs.action, routeArgs.args)
if !eq(t, "Found route", actual != nil, expected != nil) {
Expand All @@ -291,7 +291,7 @@ func TestReverseRouting(t *testing.T) {

func BenchmarkRouter(b *testing.B) {
router := NewRouter("")
router.Routes, _ = parseRoutes("", TEST_ROUTES, false)
router.Routes, _ = parseRoutes("", "", TEST_ROUTES, false)
router.updateTree()
b.ResetTimer()
for i := 0; i < b.N/len(routeMatchTestCases); i++ {
Expand Down

0 comments on commit 4fb6b7b

Please sign in to comment.