github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/middleware.go (about) 1 package goa 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "golang.org/x/net/context" 8 ) 9 10 type ( 11 // Middleware represents the canonical goa middleware signature. 12 Middleware func(Handler) Handler 13 ) 14 15 // NewMiddleware creates a middleware from the given argument. The allowed types for the 16 // argument are: 17 // 18 // - a goa middleware: goa.Middleware or func(goa.Handler) goa.Handler 19 // 20 // - a goa handler: goa.Handler or func(context.Context, http.ResponseWriter, *http.Request) error 21 // 22 // - an http middleware: func(http.Handler) http.Handler 23 // 24 // - or an http handler: http.Handler or func(http.ResponseWriter, *http.Request) 25 // 26 // An error is returned if the given argument is not one of the types above. 27 func NewMiddleware(m interface{}) (mw Middleware, err error) { 28 switch m := m.(type) { 29 case Middleware: 30 mw = m 31 case func(Handler) Handler: 32 mw = m 33 case Handler: 34 mw = handlerToMiddleware(m) 35 case func(context.Context, http.ResponseWriter, *http.Request) error: 36 mw = handlerToMiddleware(m) 37 case func(http.Handler) http.Handler: 38 mw = func(h Handler) Handler { 39 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) (err error) { 40 m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 41 err = h(ctx, w, r) 42 })).ServeHTTP(rw, req) 43 return 44 } 45 } 46 case http.Handler: 47 mw = httpHandlerToMiddleware(m.ServeHTTP) 48 case func(http.ResponseWriter, *http.Request): 49 mw = httpHandlerToMiddleware(m) 50 default: 51 err = fmt.Errorf("invalid middleware %#v", m) 52 } 53 return 54 } 55 56 // handlerToMiddleware creates a middleware from a raw handler. 57 // The middleware calls the handler and either breaks the middleware chain if the handler returns 58 // an error by also returning the error or calls the next handler in the chain otherwise. 59 func handlerToMiddleware(m Handler) Middleware { 60 return func(h Handler) Handler { 61 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 62 if err := m(ctx, rw, req); err != nil { 63 return err 64 } 65 return h(ctx, rw, req) 66 } 67 } 68 } 69 70 // httpHandlerToMiddleware creates a middleware from a http.HandlerFunc. 71 // The middleware calls the ServerHTTP method exposed by the http handler and then calls the next 72 // middleware in the chain. 73 func httpHandlerToMiddleware(m http.HandlerFunc) Middleware { 74 return func(h Handler) Handler { 75 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 76 m.ServeHTTP(rw, req) 77 return h(ctx, rw, req) 78 } 79 } 80 }