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.64k stars 1.47k forks source link

type Handle to interface #218

Open neumachen opened 7 years ago

neumachen commented 7 years ago

Can we switch to be an interface? Because I tend to use custom handlers that have a base so that I'll have a single place to catch things.

Example:

    router := httprouter.New()

    router.Handle(
        "POST",
        "/api/foo/moo",
        &handler.Base{
            H: handler.MooMoo,
            Opts: &handler.Opts{
                DB:       opt.DB,
                FS:       opt.FS,
                Lgr:      opt.Lgr,
            },
        },
    )
cristiangraz commented 7 years ago

Do you just need some data accessible to handlers? You could rework your example to something like this:

// Server ...
type Server {
    DB *sql.DB
    FS foo
    Lgr bar
}

// MooMoo handles requests for ...
func (s *Server) handleMooMoo(w http.ResponseWriter, r *http.Request) {
    // s.DB, s.FS, s.LGR
    w.Write([]byte("moo"))
}

s := NewServer(db, fs, logger)
router := httprouter.New()
router.Handle("POST", "/api/foo/moo", s.handleMooMoo)

If you need something custom per handler, you could create a function that takes options and returns a handler:

MooMooHandler(db *sql.Db, fs foo, logger bar) httprouter.Handler {
    return func(http.ResponseWriter, r *http.Requests, p httprouter.Params) {
        // db, fs, logger
        w.Write([]byte("hi"))
    }
}

router := httprouter.New()
router.Handle("POST", "/api/foo/moo", MooMooHandler(db, fs, logger))

Or a combination of both if you need things like a global db handler/logger, and handler-specific data.