Chi: Proper way of creating a subrouter

Created on 1 Mar 2020  路  12Comments  路  Source: go-chi/chi

I've used gorilla/mux and echo before and they support creating a subrouter from router:

router:= mux.NewRouter()
subRouter := router.Subrouter()
productSubrouter := router.PathPrefix("/products").Subrouter()

The subrouter inherits all the middleware from its parent router. Any middleware defined on subrouter doesn't affect the parent router, which is the primary functionality I'm aiming for.

I tried using Group:

router := chi.NewMux()
subRouter := routerGroup(nil)
authMiddleware := auth.Middleware()
subRouter2 := router.With(authMiddleware)

The problem is, subRouter and subRouter2 don't inherit the middleware from router. What's the best way to achieve this functionality (creating a subrouter while inheriting middleware from parent router) with Chi?

All 12 comments

Hi @ribice

I believe what you are looking for is Mount

You can see an example here

Given the middleware in the parent router is run through for each request I'm assuming that is what you mean?

I don't see the middleware being copied anywhere. In fact, the Route method even has a comment:

// Route creates a new Mux with a fresh middleware stack and mounts it
// along the `pattern` as a subrouter. Effectively, this is a short-hand
// call to Mount.

I'm confused why you'd want to 'copy' the middleware to the subrouter since it runs through the parents middleware before going the subrouter.

Is there a reason you want the middleware to run multiple times?

I don't see it running through parent's middleware before reaching the subrouter. I have CORS defined on primary router, but there is no CORS on subrouters created with Group or With.

I'm mounting my subrouters as sub-resources like in the todos resource example and it seems to work for me.

Not sure why in your working for you. Are you creating your subrouters inside of the parent router?

On GitHub mobile and don't see how to edit comments, here's the URL for the todos-resource example I referenced above:

https://github.com/go-chi/chi/tree/master/_examples/todos-resource

r has CORS properly set.

subRouter := chi.NewMux()
subRouter.Use(aMiddleware)
subRouter.Get("/someRoute", someRoute)
r.Mount("/", authR)

Invoking /someRoute returns CORS error. All other routes registered directly on r work properly.

I definitely don't get that problem. I can't post an example of what I've done right now as I'm on mobile but will do so later if you'd find that useful?

Please do.

it looks something like this..

    r := chi.NewRouter()

    // Basic CORS
    // for more ideas, see: https://developer.github.com/v3/#cross-origin-resource-sharing
    cors := cors.New(cors.Options{
        AllowOriginFunc:  AllowOriginFunc,
        AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
        AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
        ExposedHeaders:   []string{"Link"},
        AllowCredentials: true,
        MaxAge:           300, // Maximum value not ignored by any of major browsers
    })
    r.Use(cors.Handler)

    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("welcome"))
    })

    r.Route("/subrouter", func(r chi.Router) {
        r.Get("/", subHandlerIndex)
    })
    // note: look through other examples, you can also use r.Mount("/subrouter", subrouter)
    // where subrouter := chi.NewRouter()

    http.ListenAndServe(":3000", r)

@pkieltyka thanks and yup, my code looks pretty much like that except I'm using dependency injection with my mounted subrouters.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rocanion picture rocanion  路  4Comments

gpopovic picture gpopovic  路  5Comments

MrXu picture MrXu  路  3Comments

chenjie4255 picture chenjie4255  路  11Comments

makhov picture makhov  路  4Comments