github.com/ManabuSeki/goa-v1@v1.4.3/middleware.go (about)

     1  package goa
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"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  }