Skip to content

yawboakye/midriff

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Midriff

GoDoc

Because we have to inspect requests before they reach our inner parts, and our response before they are sent out into the open, unforgiving world.

Many a times you write a simple web application, in Go, without a framework. Which usually means you have the honor and pleasure of composing your own parts to make a whole that uniquely fits you, looks like you even.

In those situations you'd probably need something like a middleware, and just like me, you've probably created one for yourself already. In that case you don't need me and what I have to offer. Unless you want to entertain some competition for your little servant, keep it on its toes.

For the rest of us who haven't yet abstracted our middleware functions into a neat package, this is how your routes/mux setup probably looks like:

package main

import "net/http"

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/route1", one(two(three(four(handler1)))))
  mux.HandleFunc("/route2", one(two(three(four(handler2)))))
}

A little Lisp in your Go. Or, you wrote a little combinator (aka chaining function) and that helped you bring them parentheses under control. Does your code look like this?

package main

import (
  "net/http"
)

func chain(handlers ...[]http.HandlerFunc) http.HandlerFunc {
  // Combine all the handlers and return a single
  // handler that knows how to do what the constituent
  // handlers did.
}

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/route1", chain(one, two, three, four, handler1))
  mux.HandleFunc("/route2", chain(one, two, three, four, handler2))
}

Still gnarly, and it doesn't even depend on how you look at it or who you ask. Flat out gnarly. I know because like you I've written loads of this and variants. Many years later how this appeared simple and clean beats me. It goes without saying that I don't write that anymore. I midriff my middleware like so:

package main

import (
  "net/http"

  "github.com/yawboakye/midriff"
)

func main() {
  // A basic group of middleware functions.
  basicGroup := midriff.NewGroup("json-api")
  basicGroup.Append(one, two, three, four)

  mux.HandleFunc("/route1", basicGroup.And(handler1))
  mux.HandleFunc("/route2", basicGroup.And(handler2))

  // A new group of middleware that extends
  // the basic middleware. It ensures that
  // the request has enough information to be
  // granted admin privileges.
  adminGroup := midriff.NewGroup("must-be-admin")
  adminGroup.Extend(basicGroup)
  adminGroup.Prepend(mustBeAdmin)

  mux.HandleFunc("/admin/route1", adminGroup.And(handler1))
  mux.HandleFunc("/admin/route2", adminGroup.And(handler2))
}

In the interest of keeping things simple we'll keep it at that. Something I've thought of is to move the HandleFunc function of mux onto the middleware group. But I resist.

About

Midriff, also known as the midsection of your HTTP server

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages