Browse Source

SubRouter middleware

This middleware makes it much easier to write sub-routes, allowing you
to make the sub-router ignorant of its parent router's matched prefix.

The example app has also been modified to use this functionality for its
admin pages.

Fixes #65.
Carl Jackson 11 years ago
parent
commit
69ab4d722e
2 changed files with 51 additions and 8 deletions
  1. +15
    -8
      example/main.go
  2. +36
    -0
      web/middleware/subrouter.go

+ 15
- 8
example/main.go View File

@ -18,6 +18,7 @@ import (
"github.com/goji/param"
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
"github.com/zenazn/goji/web/middleware"
)
// Note: the code below cuts a lot of corners to make the example app simple.
@ -40,22 +41,28 @@ func main() {
goji.Use(PlainText)
// If the patterns ends with "/*", the path is treated as a prefix, and
// can be used to implement sub-routes. Sub-routes can be used to set
// custom middleware on sub-applications. Goji's interfaces are
// completely composable.
// can be used to implement sub-routes.
admin := web.New()
goji.Handle("/admin/*", admin)
// The standard SubRouter middleware helps make writing sub-routers
// easy. Ordinarily, Goji does not manipulate the request's URL.Path,
// meaning you'd have to repeat "/admin/" in each of the following
// routes. This middleware allows you to cut down on the repetition by
// eliminating the shared, already-matched prefix.
admin.Use(middleware.SubRouter)
// You can also easily attach extra middleware to sub-routers that are
// not present on the parent router. This one, for instance, presents a
// password prompt to users of the admin endpoints.
admin.Use(SuperSecure)
admin.Get("/", AdminRoot)
admin.Get("/finances", AdminFinances)
// Goji's routing, like Sinatra's, is exact: no effort is made to
// normalize trailing slashes.
goji.Get("/admin", http.RedirectHandler("/admin/", 301))
// Set up admin routes. Note that sub-routes do *not* mutate the path in
// any way, so we need to supply full ("/admin/" prefixed) paths.
admin.Get("/admin/", AdminRoot)
admin.Get("/admin/finances", AdminFinances)
// Use a custom 404 handler
goji.NotFound(NotFound)


+ 36
- 0
web/middleware/subrouter.go View File

@ -0,0 +1,36 @@
package middleware
import (
"net/http"
"github.com/zenazn/goji/web"
)
type subrouter struct {
c *web.C
h http.Handler
}
func (s subrouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if s.c.URLParams != nil {
if path, ok := s.c.URLParams["*"]; ok {
oldpath := r.URL.Path
r.URL.Path = path
defer func() {
r.URL.Path = oldpath
}()
}
}
s.h.ServeHTTP(w, r)
}
// SubRouter is a helper middleware that makes writing sub-routers easier.
//
// If you register a sub-router under a key like "/admin/*", Goji's router will
// automatically set c.URLParams["*"] to the unmatched path suffix. This
// middleware will help you set the request URL's Path to this unmatched suffix,
// allowing you to write sub-routers with no knowledge of what routes the parent
// router matches.
func SubRouter(c *web.C, h http.Handler) http.Handler {
return subrouter{c, h}
}

Loading…
Cancel
Save