api.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package rest
  2. import (
  3. "fmt"
  4. "git.nspix.com/golang/micro/gateway/http"
  5. "git.nspix.com/golang/rest/v3/cache"
  6. "gorm.io/gorm"
  7. "time"
  8. )
  9. type (
  10. Api struct {
  11. crud *CRUD
  12. svr *http.Server
  13. exists []string
  14. middleware []http.Middleware
  15. }
  16. feedRequest struct {
  17. ModuleName string `json:"module_name"`
  18. TableName string `json:"table_name"`
  19. ValueField string `json:"value_field"`
  20. LabelField string `json:"label_field"`
  21. Condition string `json:"condition,omitempty"`
  22. Limit int `json:"limit,omitempty"`
  23. }
  24. feedResponse struct {
  25. Label interface{} `json:"label" yaml:"label"`
  26. Value interface{} `json:"value" yaml:"value"`
  27. }
  28. )
  29. func (f *feedRequest) cacheID() string {
  30. return "feed:" + f.ModuleName + f.TableName + f.ValueField + f.LabelField
  31. }
  32. func (api *Api) handleListSchema(httpCtx *http.Context) (err error) {
  33. var (
  34. schemas []*Schema
  35. )
  36. ns := httpCtx.FormValue(NamespaceVariable)
  37. if ns == "" {
  38. ns = DefaultNamespace
  39. }
  40. if schemas, err = api.crud.GetSchemas(httpCtx.Request().Context(), ns, httpCtx.ParamValue("module"), httpCtx.ParamValue("table")); err == nil {
  41. return httpCtx.Success(schemas)
  42. } else {
  43. return httpCtx.Error(HttpDatabaseQueryFailed, err.Error())
  44. }
  45. }
  46. //handleSaveSchema 保存schema
  47. func (api *Api) handleSaveSchema(httpCtx *http.Context) (err error) {
  48. var (
  49. rest *Restful
  50. )
  51. ns := httpCtx.FormValue(NamespaceVariable)
  52. if ns == "" {
  53. ns = DefaultNamespace
  54. }
  55. moduleName := httpCtx.ParamValue("module")
  56. tableName := httpCtx.ParamValue("table")
  57. for _, row := range api.crud.modules {
  58. if row.model.ModuleName() == moduleName && row.model.TableName() == tableName {
  59. rest = row
  60. break
  61. }
  62. }
  63. if rest == nil {
  64. return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("module %s table %s schema not found", moduleName, tableName))
  65. }
  66. schemas := make([]*Schema, 0)
  67. if err = httpCtx.Bind(&schemas); err != nil {
  68. return httpCtx.Error(HttpInvalidPayload, err.Error())
  69. }
  70. if err = api.crud.db.Transaction(func(tx *gorm.DB) error {
  71. var (
  72. errTx error
  73. )
  74. for _, scm := range schemas {
  75. if errTx = tx.Save(scm).Error; errTx != nil {
  76. return errTx
  77. }
  78. }
  79. return nil
  80. }); err == nil {
  81. if api.crud.enableCache {
  82. cache.Delete(fmt.Sprintf("schema:%s:%s:%s", ns, moduleName, tableName))
  83. }
  84. return httpCtx.Success(map[string]interface{}{
  85. "count": len(schemas),
  86. "state": "success",
  87. })
  88. } else {
  89. return httpCtx.Error(HTTPUnknownFailed, err.Error())
  90. }
  91. }
  92. //handleListSchemas 查看表schema
  93. func (api *Api) handleListSchemas(httpCtx *http.Context) (err error) {
  94. var (
  95. moduleLabel string
  96. )
  97. ts := make([]*treeValue, 0)
  98. isHandled := false
  99. for _, e := range api.crud.modules {
  100. isHandled = false
  101. for _, tv := range ts {
  102. if tv.Value == e.model.ModuleName() {
  103. tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
  104. isHandled = true
  105. break
  106. }
  107. }
  108. if isHandled {
  109. continue
  110. }
  111. moduleLabel = e.model.ModuleName()
  112. tv := &treeValue{Label: moduleLabel, Value: e.model.ModuleName(), Type: TypeModule}
  113. tv.Append(&treeValue{Value: e.model.TableName(), Label: e.model.TableName(), Type: TypeTable})
  114. ts = append(ts, tv)
  115. }
  116. return httpCtx.Success(ts)
  117. }
  118. //handleDeleteSchema 删除指定的表结构
  119. func (api *Api) handleDeleteSchema(httpCtx *http.Context) (err error) {
  120. id := httpCtx.ParamValue("id")
  121. model := &Schema{}
  122. if err = api.crud.db.Where("id=?", id).First(model).Error; err == nil {
  123. if err = api.crud.db.Where("id=?", id).Delete(&Schema{}).Error; err == nil {
  124. if api.crud.enableCache {
  125. cache.Delete(fmt.Sprintf("schema:%s:%s:%s", model.Namespace, model.ModuleName, model.TableName))
  126. }
  127. return httpCtx.Success(map[string]string{
  128. "id": id,
  129. "state": "success",
  130. })
  131. } else {
  132. return httpCtx.Error(HttpDatabaseDeleteFailed, err.Error())
  133. }
  134. } else {
  135. return httpCtx.Error(HttpDatabaseFindFailed, err.Error())
  136. }
  137. }
  138. //handleFeed 订阅指定模块数据
  139. func (api *Api) handleFeed(httpCtx *http.Context) (err error) {
  140. req := &feedRequest{}
  141. if err = httpCtx.Bind(req); err != nil {
  142. return httpCtx.Error(HttpInvalidPayload, err.Error())
  143. }
  144. if !api.isExists(req.TableName + "@" + req.ModuleName) {
  145. return httpCtx.Error(HTTPUnknownFailed, fmt.Sprintf("model %s not register", req.TableName))
  146. }
  147. if api.crud.enableCache {
  148. if v, ok := cache.Get(req.cacheID()); ok {
  149. return httpCtx.Success(v)
  150. }
  151. }
  152. result := make([]map[string]interface{}, 0, 10)
  153. query := api.crud.db.Table(req.TableName).Select(req.LabelField, req.ValueField)
  154. if req.Condition != "" {
  155. query = query.Where(req.Condition)
  156. }
  157. if req.Limit > 0 {
  158. query = query.Limit(req.Limit)
  159. }
  160. if err = query.Scan(&result).Error; err == nil {
  161. feeds := make([]feedResponse, 0, len(result))
  162. for _, pairs := range result {
  163. feed := feedResponse{}
  164. for k, v := range pairs {
  165. if k == req.LabelField {
  166. feed.Label = v
  167. }
  168. if k == req.ValueField {
  169. feed.Value = v
  170. }
  171. }
  172. feeds = append(feeds, feed)
  173. }
  174. if api.crud.enableCache {
  175. cache.SetEx(req.cacheID(), feeds, time.Second*10)
  176. }
  177. return httpCtx.Success(feeds)
  178. } else {
  179. return httpCtx.Error(HttpDatabaseFindFailed, err.Error())
  180. }
  181. }
  182. func (api *Api) isExists(id string) bool {
  183. if api.exists == nil {
  184. return false
  185. }
  186. for _, s := range api.exists {
  187. if s == id {
  188. return true
  189. }
  190. }
  191. return false
  192. }
  193. func (api *Api) Attach(rest *Restful, ms ...http.Middleware) {
  194. if api.svr == nil {
  195. return
  196. }
  197. id := rest.model.TableName() + "@" + rest.model.ModuleName()
  198. if api.isExists(id) {
  199. return
  200. }
  201. if len(ms) == 0 {
  202. ms = api.middleware
  203. }
  204. if rest.hasScenario(ScenarioList) {
  205. api.svr.Handle("GET", rest.getScenarioUrl(ScenarioList), rest.getScenarioHandle(ScenarioList), ms...)
  206. }
  207. if rest.hasScenario(ScenarioCreate) {
  208. api.svr.Handle("POST", rest.getScenarioUrl(ScenarioCreate), rest.getScenarioHandle(ScenarioCreate), ms...)
  209. }
  210. if rest.hasScenario(ScenarioUpdate) {
  211. api.svr.Handle("PUT", rest.getScenarioUrl(ScenarioUpdate), rest.getScenarioHandle(ScenarioUpdate), ms...)
  212. }
  213. if rest.hasScenario(ScenarioDelete) {
  214. api.svr.Handle("DELETE", rest.getScenarioUrl(ScenarioDelete), rest.getScenarioHandle(ScenarioDelete), ms...)
  215. }
  216. if rest.hasScenario(ScenarioExport) {
  217. api.svr.Handle("GET", rest.getScenarioUrl(ScenarioExport), rest.getScenarioHandle(ScenarioExport), ms...)
  218. }
  219. if rest.hasScenario(ScenarioView) {
  220. api.svr.Handle("GET", rest.getScenarioUrl(ScenarioView), rest.getScenarioHandle(ScenarioView), ms...)
  221. }
  222. api.exists = append(api.exists, id)
  223. }
  224. func (api *Api) Router(svr *http.Server, ms ...http.Middleware) {
  225. api.svr = svr
  226. api.middleware = ms
  227. svr.Handle("GET", "/rest/schemas", api.handleListSchemas, ms...)
  228. svr.Handle("GET", "/rest/schema/:module/:table", api.handleListSchema, ms...)
  229. svr.Handle("PUT", "/rest/schema/:module/:table", api.handleSaveSchema, ms...)
  230. svr.Handle("DELETE", "/rest/schema/:id", api.handleDeleteSchema, ms...)
  231. svr.Handle("POST", "/rest/feed", api.handleFeed, ms...)
  232. api.exists = make([]string, 0, 10)
  233. for _, rest := range api.crud.modules {
  234. api.Attach(rest, ms...)
  235. }
  236. }