httprouter icon indicating copy to clipboard operation
httprouter copied to clipboard

is it possible to get the registered path?

Open yumxu opened this issue 3 years ago • 10 comments

I'm about to use httprouter in a http api gateway, and use httprouter to match path. i do not need a handle function, so i register paths with an empty handler:

router := httprouter.New()
router.Handle("GET","/user/:user_id/basic", func(writer http.ResponseWriter,
			request *http.Request, params httprouter.Params) {})
router.Handle("GET","/user/:user_id/feature", func(writer http.ResponseWriter,
			request *http.Request, params httprouter.Params) {})

then use LookUp method to match path

router.LookUp("GET","/user/1234/basic")

the LookUp method only returns handler, params and tsr currently. what i need is the matched path /user/:user_id/basic to get the upstream server which is related to the path.

yumxu avatar Mar 09 '22 13:03 yumxu

I am also looking for this feature 😃 I'm using prometheus to instrument my code and I'd like to use each endpoint path as label for each of my metrics, but right now, for paths using url params I get a different path for every id that I use, which is wrong because I end up with n different metrics instead of one.

jairogloz avatar May 24 '22 16:05 jairogloz

I came up with a quick hack. Inside your handler, you can iterate over ps httprouter.Params (which is internally a []{key, value}) and then in your request.URL.Path, replace each value by it's key, preceded by a :. Like this:

registeredPath := request.URL.Path
for _, param := range ps {
	registeredPath = strings.Replace(registeredPath, param.Value, fmt.Sprintf(":%s", param.Key), 1)
}
fmt.Println(registeredPath)

And you can do the same with router.LookUp as it returns httprouter.Params as well.

Not the most elegant solution but it gets the job done. Hope it helps.

jairogloz avatar May 30 '22 19:05 jairogloz

This functionality was made available in master (but not yet released)

https://pkg.go.dev/github.com/julienschmidt/httprouter@master#Router.SaveMatchedRoutePath https://pkg.go.dev/github.com/julienschmidt/httprouter@master#Params.MatchedRoutePath

router.SaveMatchedRoutePath=true
// in request
registeredPath := ps.MatchedRoutePath()

jehiah avatar Mar 02 '23 00:03 jehiah

@julienschmidt any chance to have a new tagged release for all commits since 2019?

MattKetmo avatar Mar 06 '23 11:03 MattKetmo

@julienschmidt Sorry for the ping, but it would be amazing if you could include this in a versioned release 🙏

viccon avatar Jan 08 '24 08:01 viccon

This functionality was made available in master (but not yet released)

https://pkg.go.dev/github.com/julienschmidt/httprouter@master#Router.SaveMatchedRoutePath https://pkg.go.dev/github.com/julienschmidt/httprouter@master#Params.MatchedRoutePath

router.SaveMatchedRoutePath=true
// in request
registeredPath := ps.MatchedRoutePath()

I came up with a quick hack. Inside your handler, you can iterate over ps httprouter.Params (which is internally a []{key, value}) and then in your request.URL.Path, replace each value by it's key, preceded by a :. Like this:

registeredPath := request.URL.Path
for _, param := range ps {
	registeredPath = strings.Replace(registeredPath, param.Value, fmt.Sprintf(":%s", param.Key), 1)
}
fmt.Println(registeredPath)

And you can do the same with router.LookUp as it returns httprouter.Params as well.

Not the most elegant solution but it gets the job done. Hope it helps.

Wouldn't this fail, if a value matches a fixed path element (e.g. pattern: /foo/:id and request /foo/foo)?

sebogh avatar Mar 09 '24 10:03 sebogh

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

letmestudy avatar Mar 09 '24 10:03 letmestudy