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

Add options check to Lookup(method, path) #274

Open ntbosscher opened 5 years ago

ntbosscher commented 5 years ago

I've built some extras around httprouter which would work much nicer if Lookup(method, path) would include the .HandleOPTIONS functionality that ServeHTTP has.

Use Case

I have user permission based routing. When an options request comes in, it doesn't work the way I'd like it to. Here's an example.

appUsers := httprouter.New()
appUsers.GET("/api/user", someHandler)

adminUsers := httprouter.New()
adminUsers.GET("/api/user", someHandler)
adminUsers.DELETE("/api/user", someHandler) // admin only handler

muxer := Mux({
    appRouter: appUsers,
    adminRouter: adminUsers,
}) 

func (m *Mux) ServeHTTP() {
     if user.IsAppUser && user.IsAdminUser {
              handler, params, _ := m.appRouter.Lookup(r.Method, r.Path)
              if handler != nil {
                     handler.ServeHTTP(w, r, params)
                     return
             }

             m.adminRouter.ServeHTTP(w, r)
            return
     }

     if user.IsAppUser {
          m.appRouter.ServeHTTP(w, r)
          return
     }

     if user.IsAdminUser {
          m.appRouter.ServeHTTP(w, r)
          return
     }

     http.NotFound(w, r)
}
ntbosscher commented 5 years ago

My usage here isn't a very good use case. Please ignore it.

Nevertheless, it seems to me that .Lookup should function almost the same as .ServeHTTP() such that you could implement your own ServeHTTP() with the following code

MyServeHTTP(w, r) {
     handler, params, _ := router.Lookup(r.Method, r.Path)
     handler(w, r, params)
}