Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to get full router path in middleware? #692

Closed
bestgopher opened this issue Dec 28, 2021 · 5 comments
Closed

how to get full router path in middleware? #692

bestgopher opened this issue Dec 28, 2021 · 5 comments

Comments

@bestgopher
Copy link

I want to get full router path in middleware before calling the handler.
image

@bestgopher
Copy link
Author

like gin's ctx.FullPath() method

@js-everts
Copy link

Maybe with RoutePattern()?

chi.RouteContext(r.Context()).RoutePattern()

@bestgopher
Copy link
Author

Maybe with RoutePattern()?

chi.RouteContext(r.Context()).RoutePattern()

I tried it, but failed. it only got /test1/* in my example.

@js-everts
Copy link

Apologies. I misunderstood you.

I am not that familiar with chi's internals. But I'm guessing what you want is not possible because of the way chi does routing. Since its based on a trie data structure, a middleware will have no knowledge of the full route pattern high up in the trie because chi has not yet resolved the full route pattern at this point in time. However if you were to attach the middleware as close to the final handlers as possible, then this could work. But that would mean attaching the middleware to every route handler using With().

For example something like the following. This will print /foo/bar/{slug} and /foo/baz/{slug} when calling the respective paths.

func PrintPattern(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		fmt.Println(chi.RouteContext(r.Context()).RoutePattern())
		next.ServeHTTP(w, r)
	}

	return http.HandlerFunc(fn)
}

func main() {
	r := chi.NewRouter()

	r.Route("/foo", func(r chi.Router) {
		r.With(PrintPattern).Get("/bar/{slug}", func(rw http.ResponseWriter, r *http.Request) {
			rw.Write([]byte("hello"))
		})

		r.With(PrintPattern).Get("/baz/{slug}", func(rw http.ResponseWriter, r *http.Request) {
			rw.Write([]byte("hello"))
		})
	})

	http.ListenAndServe(":3000", r)
}

@pkieltyka
Copy link
Member

pkieltyka commented Jan 3, 2022

hey all, the pattern is determined at runtime as the request is traversing the router. As a result, you need to fetch the pattern after the call to next.ServeHTTP, see https://github.com/go-chi/chi/blob/master/context.go#L117-L118

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants