julienschmidt / httprouter

A high performance HTTP request router that scales well
https://pkg.go.dev/github.com/julienschmidt/httprouter
BSD 3-Clause "New" or "Revised" License
16.56k stars 1.47k forks source link

is it possible to get the registered path? #344

Open yumxu opened 2 years ago

yumxu commented 2 years ago

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.

jairogloz commented 2 years ago

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 commented 2 years ago

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.

jehiah commented 1 year ago

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()
MattKetmo commented 1 year ago

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

creativecreature commented 8 months ago

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

sebogh commented 6 months ago

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)?

letmestudy commented 6 months ago

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

ajb-neodynamics-io commented 3 months ago

@julienschmidt Any plans to incorporate this into a versioned release any time soon? This would be a very helpful feature.

letmestudy commented 3 months ago

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

ajb-neodynamics-io commented 3 months ago

@letmestudy I hope you're enjoying your (extended) vacation!