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 }