mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-14 20:22:20 +08:00
feat: add Engine.PathFor function
This commit is contained in:
parent
eac2daac64
commit
ce6939ce40
24
docs/doc.md
24
docs/doc.md
@ -9,6 +9,7 @@
|
|||||||
- [Using GET, POST, PUT, PATCH, DELETE and OPTIONS](#using-get-post-put-patch-delete-and-options)
|
- [Using GET, POST, PUT, PATCH, DELETE and OPTIONS](#using-get-post-put-patch-delete-and-options)
|
||||||
- [Parameters in path](#parameters-in-path)
|
- [Parameters in path](#parameters-in-path)
|
||||||
- [Querystring parameters](#querystring-parameters)
|
- [Querystring parameters](#querystring-parameters)
|
||||||
|
- [Retrieving the path of a registered handler](#retrieving-the-path-of-a-registered-handler)
|
||||||
- [Multipart/Urlencoded Form](#multiparturlencoded-form)
|
- [Multipart/Urlencoded Form](#multiparturlencoded-form)
|
||||||
- [Another example: query + post form](#another-example-query--post-form)
|
- [Another example: query + post form](#another-example-query--post-form)
|
||||||
- [Map as querystring or postform parameters](#map-as-querystring-or-postform-parameters)
|
- [Map as querystring or postform parameters](#map-as-querystring-or-postform-parameters)
|
||||||
@ -180,6 +181,29 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Retrieving the path of a registered handler
|
||||||
|
|
||||||
|
Once a handler is registered with the router, you can retrieve its path with the `PathFor` method:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
// Creates a gin router with default middleware:
|
||||||
|
// logger and recovery (crash-free) middleware
|
||||||
|
router := gin.Default()
|
||||||
|
|
||||||
|
getUser := func(c *Context) {
|
||||||
|
// Handle the GET request.
|
||||||
|
}
|
||||||
|
router.GET("/users/:name", getUser)
|
||||||
|
path := router.PathFor(getUser, ":name", "gopher")
|
||||||
|
|
||||||
|
print(path) // Prints /users/gopher
|
||||||
|
|
||||||
|
router.Run()
|
||||||
|
}
|
||||||
|
router := gin.Default()
|
||||||
|
```
|
||||||
|
|
||||||
### Multipart/Urlencoded Form
|
### Multipart/Urlencoded Form
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
66
gin.go
66
gin.go
@ -353,6 +353,24 @@ func (engine *Engine) Routes() (routes RoutesInfo) {
|
|||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Routes returns a slice of registered routes, including some useful information, such as:
|
||||||
|
// the http method, path and the handler name.
|
||||||
|
func (engine *Engine) Route(handler HandlerFunc) (route RouteInfo, ok bool) {
|
||||||
|
handlerName := nameOfFunction(handler)
|
||||||
|
routes := RoutesInfo{}
|
||||||
|
for _, tree := range engine.trees {
|
||||||
|
routes = iterate("", tree.method, routes, tree.root)
|
||||||
|
|
||||||
|
for _, route := range routes {
|
||||||
|
if route.Handler == handlerName {
|
||||||
|
return route, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RouteInfo{}, false
|
||||||
|
}
|
||||||
|
|
||||||
func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo {
|
func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo {
|
||||||
path += root.path
|
path += root.path
|
||||||
if len(root.handlers) > 0 {
|
if len(root.handlers) > 0 {
|
||||||
@ -589,6 +607,43 @@ func (engine *Engine) HandleContext(c *Context) {
|
|||||||
c.index = oldIndexValue
|
c.index = oldIndexValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PathFor returns the path registered for the specified handler function.
|
||||||
|
// Route values are passed pair-wise as key value.
|
||||||
|
func (engine *Engine) PathFor(handler HandlerFunc, values ...interface{}) string {
|
||||||
|
route, ok := engine.Route(handler)
|
||||||
|
|
||||||
|
if !ok || len(route.Path) == 0 || len(values)%2 != 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
url := route.Path
|
||||||
|
params := make(map[string]string)
|
||||||
|
if len(values) > 0 {
|
||||||
|
key := ""
|
||||||
|
for k, v := range values {
|
||||||
|
if k%2 == 0 {
|
||||||
|
key = fmt.Sprint(v)
|
||||||
|
} else {
|
||||||
|
params[key] = fmt.Sprint(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
urls := strings.Split(url, "/")
|
||||||
|
for _, v := range urls {
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v[0:1] == ":" {
|
||||||
|
if u, ok := params[v]; ok {
|
||||||
|
delete(params, v)
|
||||||
|
url = strings.Replace(url, v, u, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return url + toQuerystring(params)
|
||||||
|
}
|
||||||
|
|
||||||
func (engine *Engine) handleHTTPRequest(c *Context) {
|
func (engine *Engine) handleHTTPRequest(c *Context) {
|
||||||
httpMethod := c.Request.Method
|
httpMethod := c.Request.Method
|
||||||
rPath := c.Request.URL.Path
|
rPath := c.Request.URL.Path
|
||||||
@ -709,3 +764,14 @@ func redirectRequest(c *Context) {
|
|||||||
http.Redirect(c.Writer, req, rURL, code)
|
http.Redirect(c.Writer, req, rURL, code)
|
||||||
c.writermem.WriteHeaderNow()
|
c.writermem.WriteHeaderNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toQuerystring(params map[string]string) string {
|
||||||
|
if len(params) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
u := "?"
|
||||||
|
for k, v := range params {
|
||||||
|
u += k + "=" + v + "&"
|
||||||
|
}
|
||||||
|
return strings.TrimRight(u, "&")
|
||||||
|
}
|
||||||
|
19
gin_test.go
19
gin_test.go
@ -676,6 +676,25 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPathFor(t *testing.T) {
|
||||||
|
r := New()
|
||||||
|
|
||||||
|
getIndex := func(c *Context) {}
|
||||||
|
r.GET("/", getIndex)
|
||||||
|
|
||||||
|
users := r.Group("/users")
|
||||||
|
|
||||||
|
postUser := func(c *Context) {}
|
||||||
|
users.POST("", postUser)
|
||||||
|
|
||||||
|
getUser := func(c *Context) {}
|
||||||
|
users.GET("/:name", getUser)
|
||||||
|
|
||||||
|
assert.Equal(t, "/", r.PathFor(getIndex))
|
||||||
|
assert.Equal(t, "/users", r.PathFor(postUser))
|
||||||
|
assert.Equal(t, "/users/gopher", r.PathFor(getUser, ":name", "gopher"))
|
||||||
|
}
|
||||||
|
|
||||||
func parseCIDR(cidr string) *net.IPNet {
|
func parseCIDR(cidr string) *net.IPNet {
|
||||||
_, parsedCIDR, err := net.ParseCIDR(cidr)
|
_, parsedCIDR, err := net.ParseCIDR(cidr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user