Replies: 2 comments
-
Given the modular nature of chi there are a few ways to do this. Some ideas.. Create an articles package and have it return a
A package main
import (
"fmt"
"log"
"net/http"
"github.com/go-chi/chi/v5"
)
func main() {
r := chi.NewRouter()
r.Mount("/articles", newArticleRouter())
log.Fatal(http.ListenAndServe("localhost:9090", r))
}
func newArticleRouter() chi.Router {
r := chi.NewRouter()
r.Use(articleAuthCheck)
r.Get("/{id}", articleHandler)
return r
}
func articleAuthCheck(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
chiCtx := chi.RouteContext(r.Context())
fmt.Println(chiCtx.RouteMethod) // GET
fmt.Println(chiCtx.RoutePath) // /987
fmt.Println(chiCtx.RoutePatterns) // [/articles/*]
fmt.Println(chiCtx.URLParams.Values) // []
// All information available in this middleware to do auth checks.
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func articleHandler(w http.ResponseWriter, r *http.Request) {
articleID := chi.URLParam(r, "id")
w.Write([]byte("article_" + articleID))
} Another option (even in combination with the above), would be to group routes together inline with with specific middleware for that group, here's a full working example: package main
import (
"fmt"
"log"
"net/http"
"github.com/go-chi/chi/v5"
)
func main() {
r := chi.NewRouter()
r.Group(func(r chi.Router) {
r.Use(articleAuthCheck)
r.Get("/articles/{id}", articleHandler)
})
log.Fatal(http.ListenAndServe("localhost:9090", r))
}
func articleAuthCheck(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
chiCtx := chi.RouteContext(r.Context())
fmt.Println(chiCtx.RouteMethod) // GET
fmt.Println(chiCtx.RoutePath) //
fmt.Println(chiCtx.RoutePatterns) // [/articles/{id}]
fmt.Println(chiCtx.URLParams.Values) // [123]
// All information available in this middleware to do auth checks.
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
func articleHandler(w http.ResponseWriter, r *http.Request) {
articleID := chi.URLParam(r, "id")
w.Write([]byte("article_" + articleID))
} There's probably other ways, but figured this might be a good start? |
Beta Was this translation helpful? Give feedback.
-
Thanks for the detailed response! I was hoping to do everything in a single middleware that wrapped everything - at the expense of walking the url tree twice, once in my middleware and again in the main router. Imagine that I'm unable to adjust the main router code at all, other than a r.Use(MyMiddleware) at the start, so the main router code might look something like:
I think I'm trying to utilize the path matching/capture parts of Chi only, but I need to associate some kind of function, probably with a middleware signature (i.e., a way to pass control It may not possible; indeed I'm even having a difficult time describing it. |
Beta Was this translation helpful? Give feedback.
-
Imagine that I have an application router that handles URLs like this:
Now imagine that I want to add a middleware that will do some work before those URLs, but that the work it does is dependent on the url itself. For example, imagine that the middleware needs the article ID to check for authorization. Further, assume that the above code cannot be adjusted - other than to inject a middleware.
I'm imagining a middleware that duplicates the URLs of interest (yes, the duplication is actually desirable in this case), does the work, then on success, passes control to the next middleware (which is the application router above).
So you might have middleware code that looks something like:
I guess I'm trying to figure out how to add a url-specific middleware (like Chi's
With()
), but set it up away from the main application router, e.g., set it up in some other middleware that operates before the main application router.Thanks for any ideas!
Beta Was this translation helpful? Give feedback.
All reactions