Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
e00eab7f
Commit
e00eab7f
authored
Jun 08, 2014
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
beego: change to tree
parent
bfabcfcb
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
246 additions
and
156 deletions
+246
-156
admin.go
admin.go
+1
-40
beego.go
beego.go
+33
-9
controller.go
controller.go
+31
-1
filter.go
filter.go
+9
-36
filter_test.go
filter_test.go
+3
-3
namespace.go
namespace.go
+41
-30
namespace_test.go
namespace_test.go
+34
-26
parser.go
parser.go
+6
-0
router.go
router.go
+0
-0
router_test.go
router_test.go
+6
-4
tree.go
tree.go
+76
-7
tree_test.go
tree_test.go
+6
-0
No files found.
admin.go
View file @
e00eab7f
...
...
@@ -121,40 +121,7 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
fmt
.
Fprintln
(
rw
,
"AdminHttpPort:"
,
AdminHttpPort
)
case
"router"
:
fmt
.
Fprintln
(
rw
,
"Print all router infomation:"
)
for
_
,
router
:=
range
BeeApp
.
Handlers
.
fixrouters
{
if
router
.
routerType
==
routerTypeBeego
{
if
router
.
hasMethod
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
methods
,
"----"
,
router
.
controllerType
.
Name
())
}
else
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
controllerType
.
Name
())
}
}
else
if
router
.
routerType
==
routerTypeRESTFul
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
methods
,
"----"
,
router
.
runfunction
)
}
else
if
router
.
routerType
==
routerTypeHandler
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
handler
)
}
}
for
_
,
router
:=
range
BeeApp
.
Handlers
.
routers
{
if
router
.
routerType
==
routerTypeBeego
{
if
router
.
hasMethod
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
methods
,
"----"
,
router
.
controllerType
.
Name
())
}
else
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
controllerType
.
Name
())
}
}
else
if
router
.
routerType
==
routerTypeRESTFul
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
methods
,
"----"
,
router
.
runfunction
)
}
else
if
router
.
routerType
==
routerTypeHandler
{
fmt
.
Fprintln
(
rw
,
router
.
pattern
,
"----"
,
router
.
handler
)
}
}
if
BeeApp
.
Handlers
.
enableAuto
{
for
controllerName
,
methodObj
:=
range
BeeApp
.
Handlers
.
autoRouter
{
fmt
.
Fprintln
(
rw
,
controllerName
,
"----"
)
for
methodName
,
obj
:=
range
methodObj
{
fmt
.
Fprintln
(
rw
,
" "
,
methodName
,
"-----"
,
obj
.
Name
())
}
}
}
// @todo print routers
case
"filter"
:
fmt
.
Fprintln
(
rw
,
"Print all filter infomation:"
)
if
BeeApp
.
Handlers
.
enableFilter
{
...
...
@@ -164,12 +131,6 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
}
}
fmt
.
Fprintln
(
rw
,
"AfterStatic:"
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
AfterStatic
];
ok
{
for
_
,
f
:=
range
bf
{
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
}
}
fmt
.
Fprintln
(
rw
,
"BeforeExec:"
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
BeforeExec
];
ok
{
for
_
,
f
:=
range
bf
{
...
...
beego.go
View file @
e00eab7f
...
...
@@ -100,7 +100,7 @@ func AddGroupRouter(prefix string, groups GroupRouters) *App {
//
// regex router
//
// beego.Router(
“/api/:id([0-9]+)“
, &controllers.RController{})
// beego.Router(
"/api/:id([0-9]+)"
, &controllers.RController{})
//
// custom rules
// beego.Router("/api/list",&RestController{},"*:ListFood")
...
...
@@ -112,6 +112,38 @@ func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *A
return
BeeApp
}
// Router add list from
// usage:
// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
// type BankAccount struct{
// beego.Controller
// }
//
// register the function
// func (b *BankAccount)Mapping(){
// b.Mapping("ShowAccount" , b.ShowAccount)
// b.Mapping("ModifyAccount", b.ModifyAccount)
//}
//
// //@router /account/:id [get]
// func (b *BankAccount) ShowAccount(){
// //logic
// }
//
//
// //@router /account/:id [post]
// func (b *BankAccount) ModifyAccount(){
// //logic
// }
//
// the comments @router url methodlist
// url support all the function Router's pattern
// methodlist [get post head put delete options *]
func
Include
(
cList
...
ControllerInterface
)
*
App
{
BeeApp
.
Handlers
.
Include
(
cList
...
)
return
BeeApp
}
// RESTRouter adds a restful controller handler to BeeApp.
// its' controller implements beego.ControllerInterface and
// defines a param "pattern/:objectId" to visit each resource.
...
...
@@ -261,14 +293,6 @@ func DelStaticPath(url string) *App {
return
BeeApp
}
// [Deprecated] use InsertFilter.
// Filter adds a FilterFunc under pattern condition and named action.
// The actions contains BeforeRouter,AfterStatic,BeforeExec,AfterExec and FinishRouter.
func
AddFilter
(
pattern
,
action
string
,
filter
FilterFunc
)
*
App
{
BeeApp
.
Handlers
.
AddFilter
(
pattern
,
action
,
filter
)
return
BeeApp
}
// InsertFilter adds a FilterFunc with pattern condition and action constant.
// The pos means action constant including
// beego.BeforeRouter, beego.AfterStatic, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
...
...
controller.go
View file @
e00eab7f
...
...
@@ -35,6 +35,7 @@ const (
var
(
// custom error when user stop request handler manually.
USERSTOPRUN
=
errors
.
New
(
"User stop run"
)
GlobalControllerRouter
map
[
string
]
map
[
string
]
*
Tree
//pkgpath+controller:method:routertree
)
// Controller defines some basic http request handler operations, such as
...
...
@@ -55,6 +56,7 @@ type Controller struct {
AppController
interface
{}
EnableRender
bool
EnableXSRF
bool
Routers
map
[
string
]
*
Tree
//method:routertree
}
// ControllerInterface is an interface to uniform all controller handler.
...
...
@@ -72,6 +74,8 @@ type ControllerInterface interface {
Render
()
error
XsrfToken
()
string
CheckXsrfCookie
()
bool
HandlerFunc
(
fn
interface
{})
URLMapping
()
}
// Init generates default values of controller operations.
...
...
@@ -86,6 +90,7 @@ func (c *Controller) Init(ctx *context.Context, controllerName, actionName strin
c
.
EnableRender
=
true
c
.
EnableXSRF
=
true
c
.
Data
=
ctx
.
Input
.
Data
c
.
Routers
=
make
(
map
[
string
]
*
Tree
)
}
// Prepare runs after Init before request function execution.
...
...
@@ -133,6 +138,32 @@ func (c *Controller) Options() {
http
.
Error
(
c
.
Ctx
.
ResponseWriter
,
"Method Not Allowed"
,
405
)
}
// call function fn
func
(
c
*
Controller
)
HandlerFunc
(
fn
interface
{})
{
if
v
,
ok
:=
fn
.
(
func
());
ok
{
v
()
}
}
// URLMapping register the internal Controller router.
func
(
c
*
Controller
)
URLMapping
()
{
}
func
(
c
*
Controller
)
Mapping
(
method
,
pattern
string
,
fn
func
())
{
method
=
strings
.
ToLower
(
method
)
if
!
utils
.
InSlice
(
method
,
HTTPMETHOD
)
&&
method
!=
"*"
{
Critical
(
"add mapping method:"
+
method
+
" is a valid method"
)
return
}
if
t
,
ok
:=
c
.
Routers
[
method
];
ok
{
t
.
AddRouter
(
pattern
,
fn
)
}
else
{
t
=
NewTree
()
t
.
AddRouter
(
pattern
,
fn
)
c
.
Routers
[
method
]
=
t
}
}
// Render sends the response with rendered template bytes as text/html type.
func
(
c
*
Controller
)
Render
()
error
{
if
!
c
.
EnableRender
{
...
...
@@ -295,7 +326,6 @@ func (c *Controller) ServeXml() {
}
// ServeFormatted serve Xml OR Json, depending on the value of the Accept header
func
(
c
*
Controller
)
ServeFormatted
()
{
accept
:=
c
.
Ctx
.
Input
.
Header
(
"Accept"
)
switch
accept
{
...
...
filter.go
View file @
e00eab7f
...
...
@@ -6,51 +6,24 @@
package
beego
import
"regexp"
// FilterRouter defines filter operation before controller handler execution.
// it can match patterned url and do filter function when action arrives.
type
FilterRouter
struct
{
pattern
string
regex
*
regexp
.
Regexp
filterFunc
FilterFunc
hasregex
bool
params
map
[
int
]
string
parseParams
map
[
string
]
string
tree
*
Tree
pattern
string
}
// ValidRouter check current request is valid for this filter.
// if matched, returns parsed params in this request by defined filter router pattern.
func
(
mr
*
FilterRouter
)
ValidRouter
(
router
string
)
(
bool
,
map
[
string
]
string
)
{
if
mr
.
pattern
==
""
{
return
true
,
nil
}
if
mr
.
pattern
==
"*"
{
return
true
,
nil
}
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
)
{
func
(
f
*
FilterRouter
)
ValidRouter
(
router
string
)
(
bool
,
map
[
string
]
string
)
{
isok
,
params
:=
f
.
tree
.
Match
(
router
)
if
isok
==
nil
{
return
false
,
nil
}
matches
:=
mr
.
regex
.
FindStringSubmatch
(
router
)
if
len
(
matches
)
>
0
{
if
len
(
matches
[
0
])
==
len
(
router
)
{
params
:=
make
(
map
[
string
]
string
)
for
i
,
match
:=
range
matches
[
1
:
]
{
params
[
mr
.
params
[
i
]]
=
match
}
return
true
,
params
}
}
}
if
isok
,
ok
:=
isok
.
(
bool
);
ok
{
return
isok
,
params
}
else
{
return
false
,
nil
}
}
filter_test.go
View file @
e00eab7f
...
...
@@ -22,7 +22,7 @@ func TestFilter(t *testing.T) {
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/person/asta/Xie"
,
nil
)
w
:=
httptest
.
NewRecorder
()
handler
:=
NewControllerRegistor
()
handler
.
AddFilter
(
"/person/:last/:first"
,
"AfterStatic"
,
FilterUser
)
handler
.
InsertFilter
(
"/person/:last/:first"
,
BeforeRouter
,
FilterUser
)
handler
.
Add
(
"/person/:last/:first"
,
&
TestController
{})
handler
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"i am astaXie"
{
...
...
@@ -41,7 +41,7 @@ func TestPatternTwo(t *testing.T) {
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/admin/"
,
nil
)
w
:=
httptest
.
NewRecorder
()
handler
:=
NewControllerRegistor
()
handler
.
AddFilter
(
"/admin/:all"
,
"AfterStatic"
,
FilterAdminUser
)
handler
.
InsertFilter
(
"/admin/?:all"
,
BeforeRouter
,
FilterAdminUser
)
handler
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"i am admin"
{
t
.
Errorf
(
"filter /admin/ can't run"
)
...
...
@@ -52,7 +52,7 @@ func TestPatternThree(t *testing.T) {
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/admin/astaxie"
,
nil
)
w
:=
httptest
.
NewRecorder
()
handler
:=
NewControllerRegistor
()
handler
.
AddFilter
(
"/admin/:all"
,
"AfterStatic"
,
FilterAdminUser
)
handler
.
InsertFilter
(
"/admin/:all"
,
BeforeRouter
,
FilterAdminUser
)
handler
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"i am admin"
{
t
.
Errorf
(
"filter /admin/astaxie can't run"
)
...
...
namespace.go
View file @
e00eab7f
...
...
@@ -7,9 +7,9 @@ package beego
import
(
"net/http"
"strings"
beecontext
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
)
type
namespaceCond
func
(
*
beecontext
.
Context
)
bool
...
...
@@ -17,7 +17,6 @@ type namespaceCond func(*beecontext.Context) bool
// Namespace is store all the info
type
Namespace
struct
{
prefix
string
condition
namespaceCond
handlers
*
ControllerRegistor
}
...
...
@@ -39,8 +38,23 @@ func NewNamespace(prefix string) *Namespace {
// }
// return false
// })
// Cond as the first filter
func
(
n
*
Namespace
)
Cond
(
cond
namespaceCond
)
*
Namespace
{
n
.
condition
=
cond
fn
:=
func
(
ctx
*
beecontext
.
Context
)
{
if
!
cond
(
ctx
)
{
middleware
.
Exception
(
"405"
,
ctx
.
ResponseWriter
,
ctx
.
Request
,
"Method not allowed"
)
}
}
if
v
,
ok
:=
n
.
handlers
.
filters
[
BeforeRouter
];
ok
{
mr
:=
new
(
FilterRouter
)
mr
.
tree
=
NewTree
()
mr
.
pattern
=
"*"
mr
.
filterFunc
=
fn
mr
.
tree
.
AddRouter
(
"*"
,
true
)
n
.
handlers
.
filters
[
BeforeRouter
]
=
append
([]
*
FilterRouter
{
mr
},
v
...
)
}
else
{
n
.
handlers
.
InsertFilter
(
"*"
,
BeforeRouter
,
fn
)
}
return
n
}
...
...
@@ -55,12 +69,13 @@ func (n *Namespace) Cond(cond namespaceCond) *Namespace {
// }
// })
func
(
n
*
Namespace
)
Filter
(
action
string
,
filter
FilterFunc
)
*
Namespace
{
var
a
int
if
action
==
"before"
{
a
ction
=
"BeforeRouter"
a
=
BeforeRouter
}
else
if
action
==
"after"
{
a
ction
=
"FinishRouter"
a
=
FinishRouter
}
n
.
handlers
.
AddFilter
(
"*"
,
action
,
filter
)
n
.
handlers
.
InsertFilter
(
"*"
,
a
,
filter
)
return
n
}
...
...
@@ -167,39 +182,35 @@ func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace {
//)
func
(
n
*
Namespace
)
Namespace
(
ns
...*
Namespace
)
*
Namespace
{
for
_
,
ni
:=
range
ns
{
n
.
handlers
.
Handler
(
ni
.
prefix
,
ni
,
true
)
n
.
handlers
.
routers
.
AddTree
(
ni
.
prefix
,
ni
.
handlers
.
routers
)
if
n
.
handlers
.
enableFilter
{
for
pos
,
filterList
:=
range
ni
.
handlers
.
filters
{
for
_
,
mr
:=
range
filterList
{
t
:=
NewTree
()
t
.
AddTree
(
ni
.
prefix
,
mr
.
tree
)
mr
.
tree
=
t
n
.
handlers
.
insertFilterRouter
(
pos
,
mr
)
}
return
n
}
// Namespace implement the http.Handler
func
(
n
*
Namespace
)
ServeHTTP
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
//trim the preifix from URL.Path
r
.
URL
.
Path
=
strings
.
TrimPrefix
(
r
.
URL
.
Path
,
n
.
prefix
)
// init context
context
:=
&
beecontext
.
Context
{
ResponseWriter
:
rw
,
Request
:
r
,
Input
:
beecontext
.
NewInput
(
r
),
Output
:
beecontext
.
NewOutput
(),
}
context
.
Output
.
Context
=
context
context
.
Output
.
EnableGzip
=
EnableGzip
if
context
.
Input
.
IsWebsocket
()
{
context
.
ResponseWriter
=
rw
}
if
n
.
condition
!=
nil
&&
!
n
.
condition
(
context
)
{
http
.
Error
(
rw
,
"Method Not Allowed"
,
405
)
return
}
n
.
handlers
.
ServeHTTP
(
rw
,
r
)
return
n
}
// register Namespace into beego.Handler
// support multi Namespace
func
AddNamespace
(
nl
...*
Namespace
)
{
for
_
,
n
:=
range
nl
{
Handler
(
n
.
prefix
,
n
,
true
)
BeeApp
.
Handlers
.
routers
.
AddTree
(
n
.
prefix
,
n
.
handlers
.
routers
)
if
n
.
handlers
.
enableFilter
{
for
pos
,
filterList
:=
range
n
.
handlers
.
filters
{
for
_
,
mr
:=
range
filterList
{
t
:=
NewTree
()
t
.
AddTree
(
n
.
prefix
,
mr
.
tree
)
mr
.
tree
=
t
BeeApp
.
Handlers
.
insertFilterRouter
(
pos
,
mr
)
}
}
}
}
}
namespace_test.go
View file @
e00eab7f
...
...
@@ -23,7 +23,8 @@ func TestNamespaceGet(t *testing.T) {
ns
.
Get
(
"/user"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
"v1_user"
))
})
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"v1_user"
{
t
.
Errorf
(
"TestNamespaceGet can't run, get the response is "
+
w
.
Body
.
String
())
}
...
...
@@ -37,7 +38,8 @@ func TestNamespacePost(t *testing.T) {
ns
.
Post
(
"/user/:id"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
ctx
.
Input
.
Param
(
":id"
)))
})
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"123"
{
t
.
Errorf
(
"TestNamespacePost can't run, get the response is "
+
w
.
Body
.
String
())
}
...
...
@@ -54,7 +56,8 @@ func TestNamespaceNest(t *testing.T) {
ctx
.
Output
.
Body
([]
byte
(
"order"
))
}),
)
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"order"
{
t
.
Errorf
(
"TestNamespaceNest can't run, get the response is "
+
w
.
Body
.
String
())
}
...
...
@@ -71,36 +74,21 @@ func TestNamespaceNestParam(t *testing.T) {
ctx
.
Output
.
Body
([]
byte
(
ctx
.
Input
.
Param
(
":id"
)))
}),
)
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"123"
{
t
.
Errorf
(
"TestNamespaceNestParam can't run, get the response is "
+
w
.
Body
.
String
())
}
}
func
TestNamespaceFilter
(
t
*
testing
.
T
)
{
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/v1/user/123"
,
nil
)
w
:=
httptest
.
NewRecorder
()
ns
:=
NewNamespace
(
"/v1"
)
ns
.
Filter
(
"before"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
"this is Filter"
))
})
.
Get
(
"/user/:id"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
ctx
.
Input
.
Param
(
":id"
)))
})
ns
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"this is Filter"
{
t
.
Errorf
(
"TestNamespaceFilter can't run, get the response is "
+
w
.
Body
.
String
())
}
}
func
TestNamespaceRouter
(
t
*
testing
.
T
)
{
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/v1/api/list"
,
nil
)
w
:=
httptest
.
NewRecorder
()
ns
:=
NewNamespace
(
"/v1"
)
ns
.
Router
(
"/api/list"
,
&
TestController
{},
"*:List"
)
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"i am list"
{
t
.
Errorf
(
"TestNamespaceRouter can't run, get the response is "
+
w
.
Body
.
String
())
}
...
...
@@ -112,17 +100,36 @@ func TestNamespaceAutoFunc(t *testing.T) {
ns
:=
NewNamespace
(
"/v1"
)
ns
.
AutoRouter
(
&
TestController
{})
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"i am list"
{
t
.
Errorf
(
"user define func can't run"
)
}
}
func
TestNamespace
Cond
(
t
*
testing
.
T
)
{
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/v1/
test/list
"
,
nil
)
func
TestNamespace
Filter
(
t
*
testing
.
T
)
{
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/v1/
user/123
"
,
nil
)
w
:=
httptest
.
NewRecorder
()
ns
:=
NewNamespace
(
"/v1"
)
ns
.
Filter
(
"before"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
"this is Filter"
))
})
.
Get
(
"/user/:id"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
Body
([]
byte
(
ctx
.
Input
.
Param
(
":id"
)))
})
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Body
.
String
()
!=
"this is Filter"
{
t
.
Errorf
(
"TestNamespaceFilter can't run, get the response is "
+
w
.
Body
.
String
())
}
}
func
TestNamespaceCond
(
t
*
testing
.
T
)
{
r
,
_
:=
http
.
NewRequest
(
"GET"
,
"/v2/test/list"
,
nil
)
w
:=
httptest
.
NewRecorder
()
ns
:=
NewNamespace
(
"/v2"
)
ns
.
Cond
(
func
(
ctx
*
context
.
Context
)
bool
{
if
ctx
.
Input
.
Domain
()
==
"beego.me"
{
return
true
...
...
@@ -130,7 +137,8 @@ func TestNamespaceCond(t *testing.T) {
return
false
})
.
AutoRouter
(
&
TestController
{})
ns
.
ServeHTTP
(
w
,
r
)
AddNamespace
(
ns
)
BeeApp
.
Handlers
.
ServeHTTP
(
w
,
r
)
if
w
.
Code
!=
405
{
t
.
Errorf
(
"TestNamespaceCond can't run get the result "
+
strconv
.
Itoa
(
w
.
Code
))
}
...
...
parser.go
0 → 100644
View file @
e00eab7f
// Beego (http://beego.me/)
// @description beego is an open-source, high-performance web framework for the Go programming language.
// @link http://github.com/astaxie/beego for the canonical source repository
// @license http://github.com/astaxie/beego/blob/master/LICENSE
// @authors astaxie
package
beego
router.go
View file @
e00eab7f
This diff is collapsed.
Click to expand it.
router_test.go
View file @
e00eab7f
...
...
@@ -10,6 +10,7 @@ import (
"net/http"
"net/http/httptest"
"testing"
"github.com/astaxie/beego/context"
)
...
...
@@ -76,16 +77,17 @@ func TestUrlFor(t *testing.T) {
handler
.
Add
(
"/person/:last/:first"
,
&
TestController
{})
handler
.
AddAuto
(
&
TestController
{})
if
handler
.
UrlFor
(
"TestController.List"
)
!=
"/api/list"
{
Info
(
handler
.
UrlFor
(
"TestController.List"
))
t
.
Errorf
(
"TestController.List must equal to /api/list"
)
}
if
handler
.
UrlFor
(
"TestController.Get"
,
":last"
,
"xie"
,
":first"
,
"asta"
)
!=
"/person/xie/asta"
{
t
.
Errorf
(
"TestController.Get must equal to /person/xie/asta"
)
}
if
handler
.
UrlFor
(
"TestController.Myext"
)
!=
"/
Test/M
yext"
{
t
.
Errorf
(
"TestController.Myext must equal to /
Test/M
yext"
)
if
handler
.
UrlFor
(
"TestController.Myext"
)
!=
"/
test/m
yext"
{
t
.
Errorf
(
"TestController.Myext must equal to /
test/m
yext"
)
}
if
handler
.
UrlFor
(
"TestController.GetUrl"
)
!=
"/
Test/GetU
rl"
{
t
.
Errorf
(
"TestController.GetUrl must equal to /
Test/GetU
rl"
)
if
handler
.
UrlFor
(
"TestController.GetUrl"
)
!=
"/
test/getu
rl"
{
t
.
Errorf
(
"TestController.GetUrl must equal to /
test/getu
rl"
)
}
}
...
...
tree.go
View file @
e00eab7f
...
...
@@ -25,6 +25,26 @@ func NewTree() *Tree {
}
}
// add Tree to the exist Tree
// prefix should has no params
func
(
t
*
Tree
)
AddTree
(
prefix
string
,
tree
*
Tree
)
{
t
.
addtree
(
splitPath
(
prefix
),
tree
)
}
func
(
t
*
Tree
)
addtree
(
segments
[]
string
,
tree
*
Tree
)
{
if
len
(
segments
)
==
0
{
panic
(
"prefix should has path"
)
}
if
len
(
segments
)
==
1
&&
segments
[
0
]
!=
""
{
t
.
fixrouters
[
segments
[
0
]]
=
tree
return
}
seg
:=
segments
[
0
]
subTree
:=
NewTree
()
t
.
fixrouters
[
seg
]
=
subTree
subTree
.
addtree
(
segments
[
1
:
],
tree
)
}
// call addseg function
func
(
t
*
Tree
)
AddRouter
(
pattern
string
,
runObject
interface
{})
{
t
.
addseg
(
splitPath
(
pattern
),
runObject
,
nil
,
""
)
...
...
@@ -83,22 +103,40 @@ func (t *Tree) match(segments []string, wildcardValues []string) (runObject inte
return
t
.
leaf
.
runObject
,
pa
}
}
if
t
.
wildcard
!=
nil
&&
t
.
wildcard
.
leaf
!=
nil
{
if
ok
,
pa
:=
t
.
wildcard
.
leaf
.
match
(
wildcardValues
);
ok
{
return
t
.
wildcard
.
leaf
.
runObject
,
pa
}
}
return
nil
,
nil
}
var
seg
string
seg
,
segments
=
segments
[
0
],
segments
[
1
:
]
seg
,
segs
:=
segments
[
0
],
segments
[
1
:
]
subTree
,
ok
:=
t
.
fixrouters
[
seg
]
if
ok
{
runObject
,
params
=
subTree
.
match
(
segments
,
wildcardValues
)
runObject
,
params
=
subTree
.
match
(
segs
,
wildcardValues
)
}
else
if
len
(
segs
)
==
0
{
//.json .xml
if
subindex
:=
strings
.
LastIndex
(
seg
,
"."
);
subindex
!=
-
1
{
subTree
,
ok
=
t
.
fixrouters
[
seg
[
:
subindex
]]
if
ok
{
runObject
,
params
=
subTree
.
match
(
segs
,
wildcardValues
)
if
runObject
!=
nil
{
if
params
==
nil
{
params
=
make
(
map
[
string
]
string
)
}
params
[
":ext"
]
=
seg
[
subindex
+
1
:
]
return
runObject
,
params
}
}
}
}
if
runObject
==
nil
&&
t
.
wildcard
!=
nil
{
runObject
,
params
=
t
.
wildcard
.
match
(
seg
ment
s
,
append
(
wildcardValues
,
seg
))
runObject
,
params
=
t
.
wildcard
.
match
(
segs
,
append
(
wildcardValues
,
seg
))
}
if
runObject
==
nil
{
if
t
.
leaf
!=
nil
{
if
ok
,
pa
:=
t
.
leaf
.
match
(
append
(
wildcardValues
,
seg
));
ok
{
if
ok
,
pa
:=
t
.
leaf
.
match
(
append
(
wildcardValues
,
seg
ments
...
));
ok
{
return
t
.
leaf
.
runObject
,
pa
}
}
...
...
@@ -122,7 +160,21 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string
// has error
if
len
(
wildcardValues
)
==
0
&&
len
(
leaf
.
wildcards
)
>
0
{
if
utils
.
InSlice
(
":"
,
leaf
.
wildcards
)
{
return
true
,
nil
params
=
make
(
map
[
string
]
string
)
j
:=
0
for
_
,
v
:=
range
leaf
.
wildcards
{
if
v
==
":"
{
continue
}
params
[
v
]
=
""
j
+=
1
}
return
true
,
params
}
if
len
(
leaf
.
wildcards
)
==
1
&&
leaf
.
wildcards
[
0
]
==
":splat"
{
params
=
make
(
map
[
string
]
string
)
params
[
":splat"
]
=
""
return
true
,
params
}
Error
(
"bug of router"
)
return
false
,
nil
...
...
@@ -155,10 +207,27 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string
if
v
==
":"
{
continue
}
if
v
==
"."
{
lastone
:=
wildcardValues
[
len
(
wildcardValues
)
-
1
]
strs
:=
strings
.
SplitN
(
lastone
,
"."
,
2
)
if
len
(
strs
)
==
2
{
params
[
":ext"
]
=
strs
[
1
]
}
else
{
params
[
":ext"
]
=
""
}
if
len
(
wildcardValues
[
j
:
])
==
1
{
params
[
":path"
]
=
strs
[
0
]
}
else
{
params
[
":path"
]
=
path
.
Join
(
wildcardValues
[
j
:
]
...
)
+
"/"
+
strs
[
0
]
}
return
true
,
params
}
params
[
v
]
=
wildcardValues
[
j
]
j
+=
1
}
if
len
(
params
)
!=
len
(
wildcardValues
)
{
Info
(
params
)
Info
(
wildcardValues
)
Error
(
"bug of router"
)
return
false
,
nil
}
...
...
@@ -193,7 +262,7 @@ func splitPath(key string) []string {
// "admin" -> false, nil, ""
// ":id" -> true, [:id], ""
// "?:id" -> true, [: id], "" : meaning can empty
// "?:id" -> true, [:
:
id], "" : meaning can empty
// ":id:int" -> true, [:id], ([0-9]+)
// ":name:string" -> true, [:name], ([\w]+)
// ":id([0-9]+)" -> true, [:id], ([0-9]+)
...
...
tree_test.go
View file @
e00eab7f
...
...
@@ -13,10 +13,16 @@ var routers []testinfo
func
init
()
{
routers
=
make
([]
testinfo
,
0
)
routers
=
append
(
routers
,
testinfo
{
"/:id"
,
"/123"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/hello/?:id"
,
"/hello"
,
map
[
string
]
string
{
":id"
:
""
}})
routers
=
append
(
routers
,
testinfo
{
"/"
,
"/"
,
nil
})
routers
=
append
(
routers
,
testinfo
{
"/customer/login"
,
"/customer/login"
,
nil
})
routers
=
append
(
routers
,
testinfo
{
"/customer/login"
,
"/customer/login.json"
,
map
[
string
]
string
{
":ext"
:
"json"
}})
routers
=
append
(
routers
,
testinfo
{
"/*"
,
"/customer/123"
,
map
[
string
]
string
{
":splat"
:
"customer/123"
}})
routers
=
append
(
routers
,
testinfo
{
"/customer/*"
,
"/customer"
,
map
[
string
]
string
{
":splat"
:
""
}})
routers
=
append
(
routers
,
testinfo
{
"/*"
,
"/customer/2009/12/11"
,
map
[
string
]
string
{
":splat"
:
"customer/2009/12/11"
}})
routers
=
append
(
routers
,
testinfo
{
"/*.*"
,
"/nice/api.json"
,
map
[
string
]
string
{
":path"
:
"nice/api"
,
":ext"
:
"json"
}})
routers
=
append
(
routers
,
testinfo
{
"/:name/*.*"
,
"/nice/api.json"
,
map
[
string
]
string
{
":name"
:
"nice"
,
":path"
:
"api"
,
":ext"
:
"json"
}})
routers
=
append
(
routers
,
testinfo
{
"/:name/test/*.*"
,
"/nice/test/api.json"
,
map
[
string
]
string
{
":name"
:
"nice"
,
":path"
:
"api"
,
":ext"
:
"json"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id:int"
,
"/v1/shop/123"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id/:name"
,
"/v1/shop/123/nike"
,
map
[
string
]
string
{
":id"
:
"123"
,
":name"
:
"nike"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id/account"
,
"/v1/shop/123/account"
,
map
[
string
]
string
{
":id"
:
"123"
}})
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment