Reputation: 1940
When I write a simple web application like this:
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/about", handler)
http.ListenAndServe(":8080", nil)
}
How can I find the list of routes and params which I defined in my web app? e.g find "/about" in this example.
EDIT 1: How can get this one params and route?
gorilla.HandleFunc(`/check/{id:[0-9]+}`, func(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Regexp works :)"))
})
Upvotes: 3
Views: 10907
Reputation: 8098
http.ServeMux has a lowercase field called pattern []pattern where the str might be what you're looking for. Unfortunately, because the field is lowercase, accessing it isn't as straightforward. However, you can still obtain it using reflect
.
package main
import (
"fmt"
"net/http"
"reflect"
)
func EmptyHandler(w http.ResponseWriter, r *http.Request) {}
func main() {
http.HandleFunc("/about", EmptyHandler)
http.HandleFunc("GET /bar/is/{type}/{animal}", EmptyHandler)
var mux *http.ServeMux
mux = http.DefaultServeMux
patterns := reflect.ValueOf(mux).Elem().FieldByName("patterns")
for i := 0; i < patterns.Len(); i++ {
// pattern *http.pattern
pattern := patterns.Index(i).Elem()
strField := pattern.FieldByName("str").String()
fmt.Println(strField)
}
}
output
/about
GET /bar/is/{type}/{animal}
Upvotes: 0
Reputation: 1570
With Go 1.22, or when using GO 1.21 with GODEBUG=httpmuxgo121=1
:
You could use http.DefaultServeMux
(type ServeMux) and examine it. With reflect
package you can ValueOf
the default multiplexer and extract m
attribute which is a map of your routes.
v := reflect.ValueOf(http.DefaultServeMux).Elem()
fmt.Printf("routes: %v\n", v.FieldByName("mux121").FieldByName("m"))
With Go 1.21 or below:
You could use http.DefaultServeMux
(type ServeMux) and examine it. With reflect
package you can ValueOf
the default multiplexer and extract m
attribute which is a map of your routes.
v := reflect.ValueOf(http.DefaultServeMux).Elem()
fmt.Printf("routes: %v\n", v.FieldByName("m"))
upd:
if you use net/http
than you should implement extracting params before any request is actually done by yourself; otherwise you have access to params with r.URL.Query()
if you use gorilla/mux
than as elithrar mentioned you should use Walk
:
func main:
r := mux.NewRouter()
r.HandleFunc("/path/{param1}", handler)
err := r.Walk(gorillaWalkFn)
if err != nil {
log.Fatal(err)
}
func gorillaWalkFn:
func gorillaWalkFn(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
path, err := route.GetPathTemplate()
return nil
}
the path
variable contains your template:
"/path/{param1}"
but you should extract params manually.
Upvotes: 8
Reputation:
An answer to improve i guess.
it provides the missing piece of code to extract parameters from the route path template string.
var pathTemplateRegex = regexp.MustCompile(`\{(\\?[^}])+\}`)
func getRouteParams(router *mux.Router, route string) []string {
r := router.Get(route)
if r == nil {
return nil
}
t, _ := r.GetPathTemplate()
params := pathTemplateRegex.FindAllString(t, -1)
for i, p := range params {
p = strings.TrimPrefix(p, "{")
p = strings.TrimSuffix(p, "}")
if strings.ContainsAny(p, ":") {
p = strings.Split(p, ":")[0]
}
params[i] = p
}
return params
}
Upvotes: 1
Reputation: 31
You can see list of routes in HTTP package.
http.HandleFunc("/favicon.ico", func(res http.ResponseWriter, req *http.Request) {
http.ServeFile(res, req, "favicon.ico")
})
http.HandleFunc(`/check`, func(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Regexp works :)"))
})
httpMux := reflect.ValueOf(http.DefaultServeMux).Elem()
finList := httpMux.FieldByIndex([]int{1})
fmt.Println(finList)
Upvotes: 3