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