github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/ginx/adapt/adapt.go (about)

     1  package adapt
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"reflect"
     7  
     8  	"github.com/gin-gonic/gin"
     9  )
    10  
    11  type Adapter interface {
    12  	Adapt(relativePath string, arg interface{}) Handler
    13  	Default(relativePath string) Handler
    14  }
    15  
    16  type Parent interface {
    17  	Parent() Adapter
    18  }
    19  
    20  type Adaptee struct {
    21  	Router       Gin
    22  	adapterFuncs map[reflect.Type]*adapterFuncItem
    23  	adapters     []Adapter
    24  }
    25  
    26  type adapterFuncItem struct {
    27  	adapterFunc reflect.Value
    28  }
    29  
    30  type Gin interface {
    31  	gin.IRouter
    32  	http.Handler
    33  }
    34  
    35  // Handler defines the handler used by gin middleware as return value.
    36  type Handler interface {
    37  	Handle(*gin.Context)
    38  }
    39  
    40  type Handlers []Handler
    41  
    42  func (h Handlers) Handle(c *gin.Context) {
    43  	for _, e := range h {
    44  		if e != nil {
    45  			e.Handle(c)
    46  		}
    47  	}
    48  }
    49  
    50  type HandlerFunc gin.HandlerFunc
    51  
    52  func (h HandlerFunc) Handle(c *gin.Context) { h(c) }
    53  
    54  type Middleware interface {
    55  	Before(c *gin.Context) (after Handler)
    56  }
    57  
    58  type Middlewares []Middleware
    59  
    60  func (s Middlewares) Before(c *gin.Context) (after Handler) {
    61  	afters := make([]Handler, len(s))
    62  	for i, m := range s {
    63  		afters[i] = m.Before(c)
    64  	}
    65  
    66  	return Handlers(afters)
    67  }
    68  
    69  func (i *adapterFuncItem) invoke(adapteeFn interface{}) gin.HandlerFunc {
    70  	args := []reflect.Value{reflect.ValueOf(adapteeFn)}
    71  	result := i.adapterFunc.Call(args)
    72  	return result[0].Convert(GinHandlerFuncType).Interface().(gin.HandlerFunc)
    73  }
    74  
    75  func (a *Adaptee) createHandlerFuncs(relativePath string, args []interface{}) gin.HandlerFunc {
    76  	adapterUnused := make(map[Adapter]bool)
    77  	for _, ad := range a.adapters {
    78  		adapterUnused[ad] = true
    79  	}
    80  
    81  	hfs := make([]Handler, 0, len(args))
    82  	middlewares := make([]Middleware, 0, len(a.adapters))
    83  
    84  	for _, arg := range args {
    85  		hf, ms := a.adapt(relativePath, arg, adapterUnused)
    86  		if hf != nil {
    87  			hfs = append(hfs, hf)
    88  		}
    89  
    90  		if len(ms) > 0 {
    91  			middlewares = append(middlewares, ms...)
    92  		}
    93  	}
    94  
    95  	for k := range adapterUnused {
    96  		f := k.Default(relativePath)
    97  		if f == nil {
    98  			continue
    99  		}
   100  
   101  		if m, ok := f.(Middleware); ok {
   102  			middlewares = append(middlewares, m)
   103  		}
   104  
   105  		hfs = append(hfs, f)
   106  	}
   107  
   108  	return func(c *gin.Context) {
   109  		defer Middlewares(middlewares).Before(c).Handle(c)
   110  
   111  		Handlers(hfs).Handle(c)
   112  	}
   113  }
   114  
   115  func (a *Adaptee) adapt(relativePath string, arg interface{}, adapterUnused map[Adapter]bool) (Handler, Middlewares) {
   116  	if arg == nil {
   117  		return nil, nil
   118  	}
   119  
   120  	if v := reflect.ValueOf(arg); v.Type().ConvertibleTo(GinHandlerFuncType) {
   121  		return HandlerFunc(v.Convert(GinHandlerFuncType).Interface().(gin.HandlerFunc)), nil
   122  	}
   123  
   124  	if f := a.findAdapterFunc(arg); f != nil {
   125  		return f, nil
   126  	}
   127  
   128  	return a.findAdapter(relativePath, arg, adapterUnused)
   129  }
   130  
   131  func (a *Adaptee) findAdapterFunc(arg interface{}) HandlerFunc {
   132  	argType := reflect.TypeOf(arg)
   133  
   134  	for funcType, funcItem := range a.adapterFuncs {
   135  		if argType.ConvertibleTo(funcType) {
   136  			return HandlerFunc(funcItem.invoke(arg))
   137  		}
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func (a *Adaptee) findAdapter(relativePath string, arg interface{}, adapterUnused map[Adapter]bool) (HandlerFunc, Middlewares) {
   144  	chain := make([]Handler, 0, len(a.adapters))
   145  	middlewares := make([]Middleware, 0, len(a.adapters))
   146  
   147  	for _, v := range a.adapters {
   148  		if f := v.Adapt(relativePath, arg); f != nil {
   149  			delete(adapterUnused, v)
   150  
   151  			if m, ok := f.(Middleware); ok {
   152  				middlewares = append(middlewares, m)
   153  			}
   154  
   155  			chain = append(chain, f)
   156  		}
   157  	}
   158  
   159  	return Handlers(chain).Handle, middlewares
   160  }
   161  
   162  func Adapt(router *gin.Engine, adapters ...interface{}) *Adaptee {
   163  	a := &Adaptee{
   164  		Router:       router,
   165  		adapterFuncs: make(map[reflect.Type]*adapterFuncItem),
   166  	}
   167  
   168  	for _, adapt := range adapters {
   169  		a.RegisterAdapter(adapt)
   170  	}
   171  
   172  	return a
   173  }
   174  
   175  func (a *Adaptee) ServeHTTP(r http.ResponseWriter, w *http.Request) {
   176  	a.Router.ServeHTTP(r, w)
   177  }
   178  
   179  var GinHandlerFuncType = reflect.TypeOf(gin.HandlerFunc(nil))
   180  
   181  func (a *Adaptee) RegisterAdapter(adapter interface{}) {
   182  	if v, ok := adapter.(Adapter); ok {
   183  		a.adapters = append(a.adapters, v)
   184  		return
   185  	}
   186  
   187  	adapterValue := reflect.ValueOf(adapter)
   188  	t := adapterValue.Type()
   189  
   190  	if t.Kind() != reflect.Func {
   191  		panic(fmt.Errorf("register method should use a func"))
   192  	}
   193  
   194  	if t.NumIn() != 1 || t.In(0).Kind() != reflect.Func {
   195  		panic(fmt.Errorf("register method should use a func which inputs a func"))
   196  	}
   197  
   198  	if t.NumOut() != 1 || !t.Out(0).ConvertibleTo(GinHandlerFuncType) {
   199  		panic(fmt.Errorf("register method should use a func which returns gin.HandlerFunc"))
   200  	}
   201  
   202  	a.adapterFuncs[t.In(0)] = &adapterFuncItem{
   203  		adapterFunc: adapterValue,
   204  	}
   205  }
   206  
   207  func (a *Adaptee) Use(f func(c *gin.Context)) {
   208  	a.Router.Use(f)
   209  }
   210  
   211  func (a *Adaptee) Handle(httpMethod, relativePath string, args ...interface{}) {
   212  	a.Router.Handle(httpMethod, relativePath, a.createHandlerFuncs(relativePath, args))
   213  }
   214  
   215  func (a *Adaptee) Any(relativePath string, args ...interface{}) {
   216  	a.Router.Any(relativePath, a.createHandlerFuncs(relativePath, args))
   217  }
   218  
   219  func (a *Adaptee) POST(relativePath string, args ...interface{}) {
   220  	a.Router.POST(relativePath, a.createHandlerFuncs(relativePath, args))
   221  }
   222  
   223  func (a *Adaptee) GET(relativePath string, args ...interface{}) {
   224  	a.Router.GET(relativePath, a.createHandlerFuncs(relativePath, args))
   225  }
   226  
   227  func (a *Adaptee) DELETE(relativePath string, args ...interface{}) {
   228  	a.Router.DELETE(relativePath, a.createHandlerFuncs(relativePath, args))
   229  }
   230  
   231  func (a *Adaptee) PUT(relativePath string, args ...interface{}) {
   232  	a.Router.PUT(relativePath, a.createHandlerFuncs(relativePath, args))
   233  }
   234  
   235  func (a *Adaptee) PATCH(relativePath string, args ...interface{}) {
   236  	a.Router.PATCH(relativePath, a.createHandlerFuncs(relativePath, args))
   237  }
   238  
   239  func (a *Adaptee) OPTIONS(relativePath string, args ...interface{}) {
   240  	a.Router.OPTIONS(relativePath, a.createHandlerFuncs(relativePath, args))
   241  }
   242  
   243  func (a *Adaptee) HEAD(relativePath string, args ...interface{}) {
   244  	a.Router.HEAD(relativePath, a.createHandlerFuncs(relativePath, args))
   245  }
   246  
   247  func (a *Adaptee) Group(relativePath string, args ...interface{}) *AdapteeGroup {
   248  	g := a.Router.Group(relativePath, a.createHandlerFuncs(relativePath, args))
   249  	return &AdapteeGroup{
   250  		Adaptee:     a,
   251  		RouterGroup: g,
   252  	}
   253  }
   254  
   255  type AdapteeGroup struct {
   256  	*Adaptee
   257  	*gin.RouterGroup
   258  }
   259  
   260  func (a *AdapteeGroup) Use(f func(c *gin.Context)) {
   261  	a.RouterGroup.Use(f)
   262  }
   263  
   264  func (a *AdapteeGroup) Any(relativePath string, args ...interface{}) {
   265  	a.RouterGroup.Any(relativePath, a.createHandlerFuncs(relativePath, args))
   266  }
   267  
   268  func (a *AdapteeGroup) POST(relativePath string, args ...interface{}) {
   269  	a.RouterGroup.POST(relativePath, a.createHandlerFuncs(relativePath, args))
   270  }
   271  
   272  func (a *AdapteeGroup) GET(relativePath string, args ...interface{}) {
   273  	a.RouterGroup.GET(relativePath, a.createHandlerFuncs(relativePath, args))
   274  }
   275  
   276  func (a *AdapteeGroup) DELETE(relativePath string, args ...interface{}) {
   277  	a.Router.DELETE(relativePath, a.createHandlerFuncs(relativePath, args))
   278  }
   279  
   280  func (a *AdapteeGroup) PUT(relativePath string, args ...interface{}) {
   281  	a.RouterGroup.PUT(relativePath, a.createHandlerFuncs(relativePath, args))
   282  }
   283  
   284  func (a *AdapteeGroup) PATCH(relativePath string, args ...interface{}) {
   285  	a.RouterGroup.PATCH(relativePath, a.createHandlerFuncs(relativePath, args))
   286  }
   287  
   288  func (a *AdapteeGroup) OPTIONS(relativePath string, args ...interface{}) {
   289  	a.RouterGroup.OPTIONS(relativePath, a.createHandlerFuncs(relativePath, args))
   290  }
   291  
   292  func (a *AdapteeGroup) HEAD(relativePath string, args ...interface{}) {
   293  	a.RouterGroup.HEAD(relativePath, a.createHandlerFuncs(relativePath, args))
   294  }