gorilla/mux

[question] How to get the Url without Path Params

vijay8059 opened this issue · 8 comments

Describe the problem you're having

How do i get the url with out path params.
eg: http://localhost:8099/v1/random/{id}
How do i retrieve the url http://localhost:8099/v1/random/

Versions

Go version: go version go1.17.3 darwin/arm64

package version: run git rev-parse HEAD inside the repo

"Show me the code!"

A minimal code snippet can be useful, otherwise we're left guessing!

Hint: wrap it with backticks to format it

ya5u commented

@vijay8059 I don't know what is your purpose or what means "get the url". However, in server side, you can get the request URL with http.Request.URL.

@ya5u i am pushing this metrics to prometheus it's become difficult to identify the url . in the prometheus it's showing as different endpoints

@ya5u i am pushing this metrics to prometheus it's become difficult to identify the url . in the prometheus it's showing as different endpoints

In the handlers you can retrieve the URL field from the *http.Request object of the handlers function parameters (usually named r).

Example:

func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Println(r.URL)
}
hyahm commented

@vijay8059 This library can get the URL without matching the path:
https://github.com/hyahm/xmux

func enter( w http.ResponseWriter, r *http.Request) bool {
	
	fmt.Println(r.URL.Path)
}
router := xmux.NewRouter()
router.Enter = enter

@vijay8059 can you explain use case? In general I would highly recommend you to go through the link

My 2 cents would be to create nested routes:

func ProductsHandler( w http.ResponseWriter, r *http.Request) bool {
	fmt.Println(r.URL.Path)
}

func ProductsHandler( w http.ResponseWriter, r *http.Request) bool {
        ....
}

func ProductDetailsHandler( w http.ResponseWriter, r *http.Request) bool {
        ....
}

r := mux.NewRouter()
s := r.PathPrefix("/v1/random").Subrouter()
// "/v1/random"
s.HandleFunc("/", ProductsHandler)
// "/v1/random/{id}"
s.HandleFunc("/{id}/", ProductHandler)
// "/v1/random/{id}/details"
s.HandleFunc("/{id}/details", ProductDetailsHandler)

I'm looking for something similar. I have a tracing middleware and want to set the operation name to the route that was matched for a request. Using your example (simplified):

func ProductsHandler( w http.ResponseWriter, r *http.Request) bool {
        ....
}

func ProductDetailsHandler( w http.ResponseWriter, r *http.Request) bool {
        ....
}

r := mux.NewRouter()
// "/v1/random/{id}"
r.HandleFunc("/{id}/", ProductHandler)
// "/v1/random/{id}/details"
r.HandleFunc("/{id}/details", ProductDetailsHandler)

server := &Server{
mux: r
}

I want a middleware that looks like this:

func (s *Server) getMiddleware() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			route := s.mux.GetMatchedRoute(r)
			// route has no identifiers in it, ie "/v1/random/{id}" instead of "/v1/random/12345"
			fmt.Println("request received: ", route)
			next.ServeHTTP(w, r)
		}
		return http.HandlerFunc(fn)
	}
}

Using the default mux from the go library, you can do this:

func (s *Server) getMiddleware() func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			_, route := s.mux.Handler(r)
			// route has no identifiers in it, ie "/v1/random/{id}" instead of "/v1/random/12345"
			fmt.Println("request received: ", route)
			next.ServeHTTP(w, r)
		}
		return http.HandlerFunc(fn)
	}
}

IMO, that Handler function should be added to the gorilla mux

Essentially, given an *http.Request, you should be able to get the handler's pattern, rather than the requests path (/api/v1/products/{id} rather than api/v1/products/319093)

Inside the HandlerFunc you can write something like this:

fmt.Println(mux.CurrentRoute(req).GetPathTemplate())

Here is a screenshot example:
image

Duplicate of #266

cc @elithrar close this 👍🏻