beego: support namespace
ns := beego.NewNamespace("/v1/api/")
ns.Cond(func(ctx *context.Context)bool{
if ctx.Input.Domain() == "www.beego.me" {
return true
}
return false
})
.Filter("before", Authenticate)
.Router("/order", &admin.OrderController{})
.Get("/version",func (ctx *context.Context) {
ctx.Output.Body([]byte("1.0.0"))
})
.Post("/login",func (ctx *context.Context) {
if ctx.Query("username") == "admin" && ctx.Query("username") ==
"password" {
}
})
.Namespace(
NewNamespace("/shop").
Get("/order/:id", func(ctx *context.Context) {
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
}),
)
Showing
5 changed files
with
294 additions
and
5 deletions
| ... | @@ -185,8 +185,8 @@ func (app *App) Any(rootpath string, f FilterFunc) *App { | ... | @@ -185,8 +185,8 @@ func (app *App) Any(rootpath string, f FilterFunc) *App { |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | // add router for http.Handler | 187 | // add router for http.Handler |
| 188 | func (app *App) Handler(rootpath string, h http.Handler) *App { | 188 | func (app *App) Handler(rootpath string, h http.Handler, options ...interface{}) *App { |
| 189 | app.Handlers.Handler(rootpath, h) | 189 | app.Handlers.Handler(rootpath, h, options...) |
| 190 | return app | 190 | return app |
| 191 | } | 191 | } |
| 192 | 192 | ... | ... |
| ... | @@ -170,8 +170,8 @@ func Any(rootpath string, f FilterFunc) *App { | ... | @@ -170,8 +170,8 @@ func Any(rootpath string, f FilterFunc) *App { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | // register router for own Handler | 172 | // register router for own Handler |
| 173 | func Handler(rootpath string, h http.Handler) *App { | 173 | func Handler(rootpath string, h http.Handler, options ...interface{}) *App { |
| 174 | BeeApp.Handler(rootpath, h) | 174 | BeeApp.Handler(rootpath, h, options...) |
| 175 | return BeeApp | 175 | return BeeApp |
| 176 | } | 176 | } |
| 177 | 177 | ... | ... |
namespace.go
0 → 100644
| 1 | // Beego (http://beego.me/) | ||
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | ||
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | ||
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | ||
| 5 | // @authors astaxie | ||
| 6 | package beego | ||
| 7 | |||
| 8 | import ( | ||
| 9 | "net/http" | ||
| 10 | "strings" | ||
| 11 | |||
| 12 | beecontext "github.com/astaxie/beego/context" | ||
| 13 | ) | ||
| 14 | |||
| 15 | type namespaceCond func(*beecontext.Context) bool | ||
| 16 | |||
| 17 | type Namespace struct { | ||
| 18 | prefix string | ||
| 19 | condition namespaceCond | ||
| 20 | handlers *ControllerRegistor | ||
| 21 | } | ||
| 22 | |||
| 23 | func NewNamespace(prefix string) *Namespace { | ||
| 24 | cr := NewControllerRegistor() | ||
| 25 | return &Namespace{ | ||
| 26 | prefix: prefix, | ||
| 27 | handlers: cr, | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | func (n *Namespace) Cond(cond namespaceCond) *Namespace { | ||
| 32 | n.condition = cond | ||
| 33 | return n | ||
| 34 | } | ||
| 35 | |||
| 36 | func (n *Namespace) Filter(action string, filter FilterFunc) *Namespace { | ||
| 37 | if action == "before" { | ||
| 38 | action = "BeforeRouter" | ||
| 39 | } else if action == "after" { | ||
| 40 | action = "FinishRouter" | ||
| 41 | } | ||
| 42 | n.handlers.AddFilter("*", action, filter) | ||
| 43 | return n | ||
| 44 | } | ||
| 45 | |||
| 46 | func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace { | ||
| 47 | n.handlers.Add(rootpath, c, mappingMethods...) | ||
| 48 | return n | ||
| 49 | } | ||
| 50 | |||
| 51 | func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace { | ||
| 52 | n.handlers.AddAuto(c) | ||
| 53 | return n | ||
| 54 | } | ||
| 55 | |||
| 56 | func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace { | ||
| 57 | n.handlers.AddAutoPrefix(prefix, c) | ||
| 58 | return n | ||
| 59 | } | ||
| 60 | |||
| 61 | func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace { | ||
| 62 | n.handlers.Get(rootpath, f) | ||
| 63 | return n | ||
| 64 | } | ||
| 65 | |||
| 66 | func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace { | ||
| 67 | n.handlers.Post(rootpath, f) | ||
| 68 | return n | ||
| 69 | } | ||
| 70 | |||
| 71 | func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace { | ||
| 72 | n.handlers.Delete(rootpath, f) | ||
| 73 | return n | ||
| 74 | } | ||
| 75 | |||
| 76 | func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace { | ||
| 77 | n.handlers.Put(rootpath, f) | ||
| 78 | return n | ||
| 79 | } | ||
| 80 | |||
| 81 | func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace { | ||
| 82 | n.handlers.Head(rootpath, f) | ||
| 83 | return n | ||
| 84 | } | ||
| 85 | |||
| 86 | func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace { | ||
| 87 | n.handlers.Options(rootpath, f) | ||
| 88 | return n | ||
| 89 | } | ||
| 90 | |||
| 91 | func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace { | ||
| 92 | n.handlers.Patch(rootpath, f) | ||
| 93 | return n | ||
| 94 | } | ||
| 95 | |||
| 96 | func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace { | ||
| 97 | n.handlers.Any(rootpath, f) | ||
| 98 | return n | ||
| 99 | } | ||
| 100 | |||
| 101 | func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace { | ||
| 102 | n.handlers.Handler(rootpath, h) | ||
| 103 | return n | ||
| 104 | } | ||
| 105 | |||
| 106 | func (n *Namespace) Namespace(ns *Namespace) *Namespace { | ||
| 107 | n.handlers.Handler(ns.prefix, ns, true) | ||
| 108 | return n | ||
| 109 | } | ||
| 110 | |||
| 111 | func (n *Namespace) ServeHTTP(rw http.ResponseWriter, r *http.Request) { | ||
| 112 | //trim the preifix from URL.Path | ||
| 113 | r.URL.Path = strings.TrimPrefix(r.URL.Path, n.prefix) | ||
| 114 | // init context | ||
| 115 | context := &beecontext.Context{ | ||
| 116 | ResponseWriter: rw, | ||
| 117 | Request: r, | ||
| 118 | Input: beecontext.NewInput(r), | ||
| 119 | Output: beecontext.NewOutput(), | ||
| 120 | } | ||
| 121 | context.Output.Context = context | ||
| 122 | context.Output.EnableGzip = EnableGzip | ||
| 123 | |||
| 124 | if context.Input.IsWebsocket() { | ||
| 125 | context.ResponseWriter = rw | ||
| 126 | } | ||
| 127 | if n.condition != nil && !n.condition(context) { | ||
| 128 | http.Error(rw, "Method Not Allowed", 405) | ||
| 129 | } | ||
| 130 | n.handlers.ServeHTTP(rw, r) | ||
| 131 | } | ||
| 132 | |||
| 133 | func AddNamespace(nl ...*Namespace) { | ||
| 134 | for _, n := range nl { | ||
| 135 | Handler(n.prefix, n, true) | ||
| 136 | } | ||
| 137 | } |
namespace_test.go
0 → 100644
| 1 | // Beego (http://beego.me/) | ||
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | ||
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | ||
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | ||
| 5 | // @authors astaxie | ||
| 6 | |||
| 7 | package beego | ||
| 8 | |||
| 9 | import ( | ||
| 10 | "net/http" | ||
| 11 | "net/http/httptest" | ||
| 12 | "strconv" | ||
| 13 | "testing" | ||
| 14 | |||
| 15 | "github.com/astaxie/beego/context" | ||
| 16 | ) | ||
| 17 | |||
| 18 | func TestNamespaceGet(t *testing.T) { | ||
| 19 | r, _ := http.NewRequest("GET", "/v1/user", nil) | ||
| 20 | w := httptest.NewRecorder() | ||
| 21 | |||
| 22 | ns := NewNamespace("/v1") | ||
| 23 | ns.Get("/user", func(ctx *context.Context) { | ||
| 24 | ctx.Output.Body([]byte("v1_user")) | ||
| 25 | }) | ||
| 26 | ns.ServeHTTP(w, r) | ||
| 27 | if w.Body.String() != "v1_user" { | ||
| 28 | t.Errorf("TestNamespaceGet can't run, get the response is " + w.Body.String()) | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | func TestNamespacePost(t *testing.T) { | ||
| 33 | r, _ := http.NewRequest("POST", "/v1/user/123", nil) | ||
| 34 | w := httptest.NewRecorder() | ||
| 35 | |||
| 36 | ns := NewNamespace("/v1") | ||
| 37 | ns.Post("/user/:id", func(ctx *context.Context) { | ||
| 38 | ctx.Output.Body([]byte(ctx.Input.Param(":id"))) | ||
| 39 | }) | ||
| 40 | ns.ServeHTTP(w, r) | ||
| 41 | if w.Body.String() != "123" { | ||
| 42 | t.Errorf("TestNamespacePost can't run, get the response is " + w.Body.String()) | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | func TestNamespaceNest(t *testing.T) { | ||
| 47 | r, _ := http.NewRequest("GET", "/v1/admin/order", nil) | ||
| 48 | w := httptest.NewRecorder() | ||
| 49 | |||
| 50 | ns := NewNamespace("/v1") | ||
| 51 | ns.Namespace( | ||
| 52 | NewNamespace("/admin"). | ||
| 53 | Get("/order", func(ctx *context.Context) { | ||
| 54 | ctx.Output.Body([]byte("order")) | ||
| 55 | }), | ||
| 56 | ) | ||
| 57 | ns.ServeHTTP(w, r) | ||
| 58 | if w.Body.String() != "order" { | ||
| 59 | t.Errorf("TestNamespaceNest can't run, get the response is " + w.Body.String()) | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | func TestNamespaceNestParam(t *testing.T) { | ||
| 64 | r, _ := http.NewRequest("GET", "/v1/admin/order/123", nil) | ||
| 65 | w := httptest.NewRecorder() | ||
| 66 | |||
| 67 | ns := NewNamespace("/v1") | ||
| 68 | ns.Namespace( | ||
| 69 | NewNamespace("/admin"). | ||
| 70 | Get("/order/:id", func(ctx *context.Context) { | ||
| 71 | ctx.Output.Body([]byte(ctx.Input.Param(":id"))) | ||
| 72 | }), | ||
| 73 | ) | ||
| 74 | ns.ServeHTTP(w, r) | ||
| 75 | if w.Body.String() != "123" { | ||
| 76 | t.Errorf("TestNamespaceNestParam can't run, get the response is " + w.Body.String()) | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | func TestNamespaceFilter(t *testing.T) { | ||
| 81 | r, _ := http.NewRequest("GET", "/v1/user/123", nil) | ||
| 82 | w := httptest.NewRecorder() | ||
| 83 | |||
| 84 | ns := NewNamespace("/v1") | ||
| 85 | ns.Filter("before", func(ctx *context.Context) { | ||
| 86 | ctx.Output.Body([]byte("this is Filter")) | ||
| 87 | }). | ||
| 88 | Get("/user/:id", func(ctx *context.Context) { | ||
| 89 | ctx.Output.Body([]byte(ctx.Input.Param(":id"))) | ||
| 90 | }) | ||
| 91 | ns.ServeHTTP(w, r) | ||
| 92 | if w.Body.String() != "this is Filter" { | ||
| 93 | t.Errorf("TestNamespaceFilter can't run, get the response is " + w.Body.String()) | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | func TestNamespaceRouter(t *testing.T) { | ||
| 98 | r, _ := http.NewRequest("GET", "/v1/api/list", nil) | ||
| 99 | w := httptest.NewRecorder() | ||
| 100 | |||
| 101 | ns := NewNamespace("/v1") | ||
| 102 | ns.Router("/api/list", &TestController{}, "*:List") | ||
| 103 | ns.ServeHTTP(w, r) | ||
| 104 | if w.Body.String() != "i am list" { | ||
| 105 | t.Errorf("TestNamespaceRouter can't run, get the response is " + w.Body.String()) | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | func TestNamespaceAutoFunc(t *testing.T) { | ||
| 110 | r, _ := http.NewRequest("GET", "/v1/test/list", nil) | ||
| 111 | w := httptest.NewRecorder() | ||
| 112 | |||
| 113 | ns := NewNamespace("/v1") | ||
| 114 | ns.AutoRouter(&TestController{}) | ||
| 115 | ns.ServeHTTP(w, r) | ||
| 116 | if w.Body.String() != "i am list" { | ||
| 117 | t.Errorf("user define func can't run") | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | func TestNamespaceCond(t *testing.T) { | ||
| 122 | r, _ := http.NewRequest("GET", "/v1/test/list", nil) | ||
| 123 | w := httptest.NewRecorder() | ||
| 124 | |||
| 125 | ns := NewNamespace("/v1") | ||
| 126 | ns.Cond(func(ctx *context.Context) bool { | ||
| 127 | if ctx.Input.Domain() == "beego.me" { | ||
| 128 | return true | ||
| 129 | } | ||
| 130 | return false | ||
| 131 | }). | ||
| 132 | AutoRouter(&TestController{}) | ||
| 133 | ns.ServeHTTP(w, r) | ||
| 134 | if w.Code != 405 { | ||
| 135 | t.Errorf("TestNamespaceCond can't run get the result " + strconv.Itoa(w.Code)) | ||
| 136 | } | ||
| 137 | } |
| ... | @@ -69,6 +69,7 @@ type controllerInfo struct { | ... | @@ -69,6 +69,7 @@ type controllerInfo struct { |
| 69 | handler http.Handler | 69 | handler http.Handler |
| 70 | runfunction FilterFunc | 70 | runfunction FilterFunc |
| 71 | routerType int | 71 | routerType int |
| 72 | isPrefix bool | ||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | // ControllerRegistor containers registered router rules, controller handlers and filters. | 75 | // ControllerRegistor containers registered router rules, controller handlers and filters. |
| ... | @@ -277,11 +278,16 @@ func (p *ControllerRegistor) AddMethod(method, pattern string, f FilterFunc) { | ... | @@ -277,11 +278,16 @@ func (p *ControllerRegistor) AddMethod(method, pattern string, f FilterFunc) { |
| 277 | } | 278 | } |
| 278 | } | 279 | } |
| 279 | 280 | ||
| 280 | func (p *ControllerRegistor) Handler(pattern string, h http.Handler) { | 281 | func (p *ControllerRegistor) Handler(pattern string, h http.Handler, options ...interface{}) { |
| 281 | paramnums, params, parts := p.splitRoute(pattern) | 282 | paramnums, params, parts := p.splitRoute(pattern) |
| 282 | route := &controllerInfo{} | 283 | route := &controllerInfo{} |
| 283 | route.routerType = routerTypeHandler | 284 | route.routerType = routerTypeHandler |
| 284 | route.handler = h | 285 | route.handler = h |
| 286 | if len(options) > 0 { | ||
| 287 | if v, ok := options[0].(bool); ok { | ||
| 288 | route.isPrefix = v | ||
| 289 | } | ||
| 290 | } | ||
| 285 | if paramnums == 0 { | 291 | if paramnums == 0 { |
| 286 | route.pattern = pattern | 292 | route.pattern = pattern |
| 287 | p.fixrouters = append(p.fixrouters, route) | 293 | p.fixrouters = append(p.fixrouters, route) |
| ... | @@ -446,6 +452,7 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc | ... | @@ -446,6 +452,7 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc |
| 446 | if err != nil { | 452 | if err != nil { |
| 447 | return err | 453 | return err |
| 448 | } | 454 | } |
| 455 | |||
| 449 | switch action { | 456 | switch action { |
| 450 | case "BeforeRouter": | 457 | case "BeforeRouter": |
| 451 | p.filters[BeforeRouter] = append(p.filters[BeforeRouter], mr) | 458 | p.filters[BeforeRouter] = append(p.filters[BeforeRouter], mr) |
| ... | @@ -760,6 +767,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -760,6 +767,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 760 | break | 767 | break |
| 761 | } | 768 | } |
| 762 | } | 769 | } |
| 770 | if route.routerType == routerTypeHandler && route.isPrefix && | ||
| 771 | strings.HasPrefix(requestPath, route.pattern) { | ||
| 772 | |||
| 773 | routerInfo = route | ||
| 774 | runrouter = route.controllerType | ||
| 775 | findrouter = true | ||
| 776 | break | ||
| 777 | } | ||
| 763 | } | 778 | } |
| 764 | } | 779 | } |
| 765 | 780 | ... | ... |
-
Please register or sign in to post a comment