package binding import ( "git.sxidc.com/go-framework/baize/framework/core/api" "git.sxidc.com/go-framework/baize/framework/core/api/request" "git.sxidc.com/go-framework/baize/framework/core/domain" "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "github.com/pkg/errors" "net/http" "reflect" "strings" ) // Bind 通用绑定 // 类型参数: // - O: 响应数据类型,对应response.SendResponseFunc的data的类型 // 参数: // - binder: 用来执行绑定的binder // - item: 执行绑定的参数 // - middlewares: 该绑定的中间件 func Bind[O any](binder *Binder, item *BindItem[O], middlewares ...Middleware) { item.bind(binder, middlewares...) } // BindItem 通用BindItem type BindItem[O any] struct { Method string *SimpleBindItem[O] } func (item *BindItem[O]) bind(binder *Binder, middlewares ...Middleware) { if strutils.IsStringEmpty(item.Path) { panic("需要指定路径") } if strutils.IsStringEmpty(item.Method) { panic("需要指定方法") } if item.SendResponseFunc == nil { panic("需要指定响应函数") } if item.ServiceFunc == nil { panic("需要指定应用服务函数") } var outputZero O outputZeroValue := reflect.ValueOf(outputZero) if outputZeroValue.IsValid() && outputZeroValue.Kind() == reflect.Pointer { panic("bind的输出类型不能使用指针类型") } if outputZeroValue.IsValid() && strings.Contains(outputZeroValue.String(), "response.InfosData") { infosField := outputZeroValue.FieldByName("Infos") if infosField.IsValid() && infosField.Type().Elem().Kind() == reflect.Pointer { panic("bind的输出类型不能使用指针类型") } } apiMiddlewares := make([]api.Handler, len(middlewares)) for i, middleware := range middlewares { innerMiddleware := middleware apiMiddlewares[i] = func(c *api.Context) { innerMiddleware(c, binder.i) } } handlers := append(apiMiddlewares, func(c *api.Context) { var params request.Params // 有请求数据 if item.RequestParams != nil { requestParamsType := reflect.TypeOf(item.RequestParams) if !reflectutils.IsTypeStructOrStructPointer(requestParamsType) { item.SendResponseFunc(c, http.StatusOK, outputZero, errors.New("请求参数不是结构或结构指针")) return } if requestParamsType.Kind() == reflect.Pointer { params = reflect.New(requestParamsType.Elem()).Interface().(request.Params) } else { params = reflect.New(requestParamsType).Interface().(request.Params) } // 将请求数据解析到请求参数中 if item.BindRequestParamsFunc != nil { err := item.BindRequestParamsFunc(c, params) if err != nil { item.SendResponseFunc(c, http.StatusBadRequest, outputZero, err) return } } else { switch item.Method { case http.MethodPost: fallthrough case http.MethodPut: err := request.BindJsonBody(c, params) if err != nil { item.SendResponseFunc(c, http.StatusBadRequest, outputZero, err) return } case http.MethodDelete: fallthrough case http.MethodGet: err := request.BindQueryParams(c, params) if err != nil { item.SendResponseFunc(c, http.StatusBadRequest, outputZero, err) return } } } } // 进行领域对象转化 var domainObjects []domain.Object if item.FormDomainObjectsFunc != nil { innerDomainObjects, err := item.FormDomainObjectsFunc(c, params) if err != nil { item.SendResponseFunc(c, http.StatusOK, outputZero, err) return } domainObjects = innerDomainObjects } else { if item.Objects != nil && len(item.Objects) != 0 { for _, object := range item.Objects { if object == nil { continue } objectType := reflect.TypeOf(object) if !reflectutils.IsTypeStructOrStructPointer(objectType) { item.SendResponseFunc(c, http.StatusOK, outputZero, errors.New("领域对象不是结构或结构指针")) return } obj := reflect.New(reflectutils.PointerTypeElem(objectType)).Interface().(domain.Object) if params != nil { err := request.AssignRequestParamsToDomainObject(params, obj) if err != nil { item.SendResponseFunc(c, http.StatusOK, outputZero, err) return } } domainObjects = append(domainObjects, obj) } } } // 执行业务函数 outputModel, err := item.ServiceFunc(c, params, domainObjects, binder.i) item.SendResponseFunc(c, http.StatusOK, outputModel, err) return }) // 所有的函数加入到执行链中 binder.router.AddRoute(item.Method, item.Path, handlers...) }