A Case for Middleware
What is middleware?
Anything that happens between your app receiving a request and that request hitting it's controller/handler.
controller
request
response
request ID
auth
throttle
router := mux.NewRouter() //link routes to handlers
router.HandleFunc("/alarms", listAlarms).Methods("GET")
router.HandleFunc("/persons/{id}", updatePerson).Methods("PUT")
http.Handle("/", router) //listen for http requests
func listAlarms(res http.ResponseWriter, req *http.Request){
requestIDHelper(req)
if !isAuthorized(req) {
res.WriteHeader(403)
return
}
if needsThrottle(req){
res.WriteHeader(429)
return
}
// - Business Logic -
// - Write Response -
}
func updatePerson(res http.ResponseWriter, req *http.Request){
requestIDHelper(req)
if !isAuthorized(req) {
res.WriteHeader(403)
return
}
if needsThrottle(req){
res.WriteHeader(429)
return
}
// - Business Logic -
// - Write Response -
}
router := mux.NewRouter() //link routes to handlers
router.HandleFunc("/alarms", listAlarms).Methods("GET")
router.HandleFunc("/persons/{id}", updatePerson).Methods("PUT")
middlewareStack := negroni.New() //middleware stack
middlewareStack.use(requestID) //request ID middleware
middlewareStack.use(authorize) //authorization middleware
middlewareStack.use(throttle) //throttle middleware
middlewareStack.UseHandler(router) //router is the last piece of middleware
http.Handle("/", stack) //listen for http requests
func listAlarms(res http.ResponseWriter, req *http.Request){
// - Business Logic -
// - Write Response -
}
func updatePerson(res http.ResponseWriter, req *http.Request){
// - Business Logic -
// - Write Response -
}
//request ID middleware
AddMiddleware(middleware.RequestID())
//logging middleware
AddMiddleware(middleware.LoggingMiddleware(rootLogger))
//rate limiting middleware
var rootLimiter = lrLimiter.NewLimiterMap(10, 200, 2)
AddMiddleware(middleware.RateLimitingMiddleware(rootLimiter))
//get user info in the context for use in middleware/controllers
AddMiddleware(middleware.TokenInfo)
//Authorization checks
AddMiddleware(middleware.Auth(authService, domain.Read), `/cases/{id}`)
AddMiddleware(middleware.Auth(authService, domain.Update), `/cases/{id}`, "PUT")
//stop changes on a closed case
AddMiddleware(middleware.ClosedCheck(), `/cases/{id}`, "PUT", "POST", "DELETE")
Real Example
Pros
- one touch point
- isolate concerns
- potential to stop things from slipping through the cracks
Cons
- magic / hidden
- tightly coupled to URIs
deck
By Chris Langager
deck
- 415