diff --git a/beego.go b/beego.go index 64e224da..a7f3fd5a 100644 --- a/beego.go +++ b/beego.go @@ -13,6 +13,13 @@ import ( // beego web framework version. const VERSION = "1.0.1" +type hookfunc func() error //hook function to run +var hooks []hookfunc //hook function slice to store the hookfunc + +func init() { + hooks = make([]hookfunc, 0) +} + // Router adds a patterned controller handler to BeeApp. // it's an alias method of App.Router. func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App { @@ -87,6 +94,12 @@ func InsertFilter(pattern string, pos int, filter FilterFunc) *App { return BeeApp } +// The hookfunc will run in beego.Run() +// such as sessionInit, middlerware start, buildtemplate, admin start +func AddAPPStartHook(hf hookfunc) { + hooks = append(hooks, hf) +} + // Run beego application. // it's alias of App.Run. func Run() { @@ -102,6 +115,14 @@ func Run() { //init mime initMime() + // do hooks function + for _, hk := range hooks { + err := hk() + if err != nil { + panic(err) + } + } + if SessionOn { GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, diff --git a/filter.go b/filter.go index 7e0245a6..98868865 100644 --- a/filter.go +++ b/filter.go @@ -28,6 +28,12 @@ func (mr *FilterRouter) ValidRouter(router string) (bool, map[string]string) { if router == mr.pattern { return true, nil } + //pattern /admin router /admin/ match + //pattern /admin/ router /admin don't match, because url will 301 in router + if n := len(router); n > 1 && router[n-1] == '/' && router[:n-2] == mr.pattern { + return true, nil + } + if mr.hasregex { if !mr.regex.MatchString(router) { return false, nil @@ -46,7 +52,7 @@ func (mr *FilterRouter) ValidRouter(router string) (bool, map[string]string) { return false, nil } -func buildFilter(pattern string, filter FilterFunc) *FilterRouter { +func buildFilter(pattern string, filter FilterFunc) (*FilterRouter, error) { mr := new(FilterRouter) mr.params = make(map[int]string) mr.filterFunc = filter @@ -54,7 +60,7 @@ func buildFilter(pattern string, filter FilterFunc) *FilterRouter { j := 0 for i, part := range parts { if strings.HasPrefix(part, ":") { - expr := "(.+)" + expr := "(.*)" //a user may choose to override the default expression // similar to expressjs: ‘/user/:id([0-9]+)’ if index := strings.Index(part, "("); index != -1 { @@ -77,7 +83,7 @@ func buildFilter(pattern string, filter FilterFunc) *FilterRouter { j++ } if strings.HasPrefix(part, "*") { - expr := "(.+)" + expr := "(.*)" if part == "*.*" { mr.params[j] = ":path" parts[i] = "([^.]+).([^.]+)" @@ -137,12 +143,11 @@ func buildFilter(pattern string, filter FilterFunc) *FilterRouter { pattern = strings.Join(parts, "/") regex, regexErr := regexp.Compile(pattern) if regexErr != nil { - //TODO add error handling here to avoid panic - panic(regexErr) + return nil, regexErr } mr.regex = regex mr.hasregex = true } mr.pattern = pattern - return mr + return mr, nil } diff --git a/fiter_test.go b/fiter_test.go index 4e9dae6a..7fe9a641 100644 --- a/fiter_test.go +++ b/fiter_test.go @@ -23,3 +23,32 @@ func TestFilter(t *testing.T) { t.Errorf("user define func can't run") } } + +var FilterAdminUser = func(ctx *context.Context) { + ctx.Output.Body([]byte("i am admin")) +} + +// Filter pattern /admin/:all +// all url like /admin/ /admin/xie will all get filter + +func TestPatternTwo(t *testing.T) { + r, _ := http.NewRequest("GET", "/admin/", nil) + w := httptest.NewRecorder() + handler := NewControllerRegistor() + handler.AddFilter("/admin/:all", "AfterStatic", FilterAdminUser) + handler.ServeHTTP(w, r) + if w.Body.String() != "i am admin" { + t.Errorf("filter /admin/ can't run") + } +} + +func TestPatternThree(t *testing.T) { + r, _ := http.NewRequest("GET", "/admin/astaxie", nil) + w := httptest.NewRecorder() + handler := NewControllerRegistor() + handler.AddFilter("/admin/:all", "AfterStatic", FilterAdminUser) + handler.ServeHTTP(w, r) + if w.Body.String() != "i am admin" { + t.Errorf("filter /admin/astaxie can't run") + } +} diff --git a/router.go b/router.go index d54576ec..21479a13 100644 --- a/router.go +++ b/router.go @@ -77,7 +77,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM params := make(map[int]string) for i, part := range parts { if strings.HasPrefix(part, ":") { - expr := "(.+)" + expr := "(.*)" //a user may choose to override the defult expression // similar to expressjs: ‘/user/:id([0-9]+)’ if index := strings.Index(part, "("); index != -1 { @@ -100,7 +100,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM j++ } if strings.HasPrefix(part, "*") { - expr := "(.+)" + expr := "(.*)" if part == "*.*" { params[j] = ":path" parts[i] = "([^.]+).([^.]+)" @@ -238,8 +238,11 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { // [Deprecated] use InsertFilter. // Add FilterFunc with pattern for action. -func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { - mr := buildFilter(pattern, filter) +func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) error { + mr, err := buildFilter(pattern, filter) + if err != nil { + return err + } switch action { case "BeforeRouter": p.filters[BeforeRouter] = append(p.filters[BeforeRouter], mr) @@ -253,13 +256,18 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc p.filters[FinishRouter] = append(p.filters[FinishRouter], mr) } p.enableFilter = true + return nil } // Add a FilterFunc with pattern rule and action constant. -func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) { - mr := buildFilter(pattern, filter) +func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) error { + mr, err := buildFilter(pattern, filter) + if err != nil { + return err + } p.filters[pos] = append(p.filters[pos], mr) p.enableFilter = true + return nil } // UrlFor does another controller handler in this request function.