e657dcfd by astaxie

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")))
	}),
)
1 parent 2ed9b2bf
...@@ -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
......
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 }
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
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!