add util func to get the url fix #282

UrlFor(endpoint string, values ...string) string
This commit is contained in:
astaxie 2013-11-10 23:05:07 +08:00
parent 167ad203cb
commit 9446563e5b
6 changed files with 157 additions and 2 deletions

3
app.go
View File

@ -87,6 +87,9 @@ func (app *App) AutoRouter(c ControllerInterface) *App {
return app
}
func (app *App) UrlFor(endpoint string, values ...string) string {
return app.Handlers.UrlFor(endpoint, values...)
}
func (app *App) Filter(pattern, action string, filter FilterFunc) *App {
app.Handlers.AddFilter(pattern, action, filter)
return app

View File

@ -16,6 +16,7 @@ import (
"net/http"
"net/url"
"os"
"reflect"
"strconv"
"strings"
"time"
@ -175,6 +176,17 @@ func (c *Controller) Abort(code string) {
panic(code)
}
func (c *Controller) UrlFor(endpoint string, values ...string) string {
if len(endpoint) <= 0 {
return ""
}
if endpoint[0] == '.' {
return UrlFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...)
} else {
return UrlFor(endpoint, values...)
}
}
func (c *Controller) ServeJson(encoding ...bool) {
var hasIndent bool
var hasencoding bool

115
router.go
View File

@ -259,6 +259,121 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc
p.filters[action] = append(p.filters[action], mr)
}
func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
paths := strings.Split(endpoint, ".")
if len(paths) <= 1 {
Warn("urlfor endpoint must like path.controller.method")
return ""
}
if len(values)%2 != 0 {
Warn("urlfor params must key-value pair")
return ""
}
urlv := url.Values{}
if len(values) > 0 {
key := ""
for k, v := range values {
if k%2 == 0 {
key = v
} else {
urlv.Set(key, v)
}
}
}
controllName := strings.Join(paths[:len(paths)-1], ".")
methodName := paths[len(paths)-1]
for _, route := range p.fixrouters {
if route.controllerType.Name() == controllName {
var finded bool
if inSlice(strings.ToLower(methodName), HTTPMETHOD) {
if route.hasMethod {
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
finded = false
} else if m, ok = route.methods["*"]; ok && m != methodName {
finded = false
} else {
finded = true
}
} else {
finded = true
}
} else if route.hasMethod {
for _, md := range route.methods {
if md == methodName {
finded = true
}
}
}
if !finded {
continue
}
if len(values) > 0 {
return route.pattern + "?" + urlv.Encode()
}
return route.pattern
}
}
for _, route := range p.routers {
if route.controllerType.Name() == controllName {
var finded bool
if inSlice(strings.ToLower(methodName), HTTPMETHOD) {
if route.hasMethod {
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
finded = false
} else if m, ok = route.methods["*"]; ok && m != methodName {
finded = false
} else {
finded = true
}
} else {
finded = true
}
} else if route.hasMethod {
for _, md := range route.methods {
if md == methodName {
finded = true
}
}
}
if !finded {
continue
}
var returnurl string
var i int
var startreg bool
for _, v := range route.regex.String() {
if v == '(' {
startreg = true
continue
} else if v == ')' {
startreg = false
returnurl = returnurl + urlv.Get(route.params[i])
i++
} else if !startreg {
returnurl = string(append([]rune(returnurl), v))
}
}
if route.regex.MatchString(returnurl) {
return returnurl
}
}
}
if p.enableAuto {
for cName, methodList := range p.autoRouter {
if strings.ToLower(strings.TrimSuffix(paths[len(paths)-2], "Controller")) == cName {
if _, ok := methodList[methodName]; ok {
if len(values) > 0 {
return "/" + strings.TrimSuffix(paths[len(paths)-2], "Controller") + "/" + methodName + "?" + urlv.Encode()
} else {
return "/" + strings.TrimSuffix(paths[len(paths)-2], "Controller") + "/" + methodName
}
}
}
}
}
return ""
}
// AutoRoute
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
defer func() {

View File

@ -25,6 +25,29 @@ func (this *TestController) Myext() {
this.Ctx.Output.Body([]byte(this.Ctx.Input.Params(":ext")))
}
func (this *TestController) GetUrl() {
this.Ctx.Output.Body([]byte(this.UrlFor(".Myext")))
}
func TestUrlFor(t *testing.T) {
handler := NewControllerRegistor()
handler.Add("/api/list", &TestController{}, "*:List")
handler.Add("/person/:last/:first", &TestController{})
handler.AddAuto(&TestController{})
if handler.UrlFor("TestController.List") != "/api/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/Myext" {
t.Errorf("TestController.Myext must equal to /Test/Myext")
}
if handler.UrlFor("TestController.GetUrl") != "/Test/GetUrl" {
t.Errorf("TestController.GetUrl must equal to /Test/GetUrl")
}
}
func TestUserFunc(t *testing.T) {
r, _ := http.NewRequest("GET", "/api/list", nil)
w := httptest.NewRecorder()

View File

@ -43,6 +43,8 @@ func init() {
beegoTplFuncMap["le"] = le // <=
beegoTplFuncMap["lt"] = lt // <
beegoTplFuncMap["ne"] = ne // !=
beegoTplFuncMap["urlfor"] = UrlFor // !=
}
// AddFuncMap let user to register a func in the template

View File

@ -385,6 +385,6 @@ func GetRandomString(n int) string {
// /login
// /login?next=/
// /user/John%20Doe
func UrlFor(endpoint string, values ...string) {
func UrlFor(endpoint string, values ...string) string {
return BeeApp.UrlFor(endpoint, values...)
}