github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/server/service/mock.go (about) 1 package serverService 2 3 import ( 4 "encoding/json" 5 "encoding/xml" 6 "errors" 7 "fmt" 8 "mime/multipart" 9 "os" 10 "path/filepath" 11 "regexp" 12 "strings" 13 "time" 14 15 consts "github.com/easysoft/zendata/internal/pkg/const" 16 "github.com/easysoft/zendata/internal/pkg/domain" 17 "github.com/easysoft/zendata/internal/pkg/helper" 18 "github.com/easysoft/zendata/internal/pkg/model" 19 "github.com/easysoft/zendata/internal/pkg/service" 20 serverRepo "github.com/easysoft/zendata/internal/server/repo" 21 dateUtils "github.com/easysoft/zendata/pkg/utils/date" 22 fileUtils "github.com/easysoft/zendata/pkg/utils/file" 23 logUtils "github.com/easysoft/zendata/pkg/utils/log" 24 stringUtils "github.com/easysoft/zendata/pkg/utils/string" 25 "github.com/easysoft/zendata/pkg/utils/vari" 26 "github.com/kataras/iris/v12" 27 "github.com/snowlyg/helper/dir" 28 "gopkg.in/yaml.v2" 29 ) 30 31 var ( 32 MockServiceDataMap = map[string]domain.MockPathMap{} 33 MockServiceDataDefMap = map[string]string{} 34 MockServiceDataRegxPathToOrigPath = map[string]map[string]string{} 35 ) 36 37 type MockService struct { 38 MainService *service.MainService `inject:""` 39 OutputService *service.OutputService `inject:""` 40 MockService *service.MockService `inject:""` 41 DefService *DefService `inject:""` 42 MockRepo *serverRepo.MockRepo `inject:""` 43 } 44 45 func (s *MockService) List(keywords string, page int) (pos []*model.ZdMock, total int, err error) { 46 pos, total, err = s.MockRepo.List(strings.TrimSpace(keywords), page) 47 return 48 } 49 50 func (s *MockService) Get(id int) (po model.ZdMock, err error) { 51 po, err = s.MockRepo.Get(uint(id)) 52 53 return 54 } 55 56 func (s *MockService) Save(po *model.ZdMock) (err error) { 57 zdDef, err := helper.GetDefFromYamlString(po.MockContent) 58 if err != nil { 59 return 60 } 61 po.Name = zdDef.Title 62 63 if po.DefId == 0 { 64 fi := domain.ResFile{FileName: po.Name, Path: po.DataPath} 65 _, po.DefId = s.DefService.SyncToDB(fi, true) 66 } 67 err = s.MockRepo.Save(po) 68 69 return 70 } 71 72 func (s *MockService) Remove(id int) (err error) { 73 err = s.MockRepo.Remove(uint(id)) 74 75 return 76 } 77 78 func (s *MockService) LoadDef(pth string, files *[]string, level int) (err error) { 79 if !fileUtils.IsDir(pth) { 80 *files = append(*files, pth) 81 return 82 } 83 84 dir, err := os.ReadDir(pth) 85 if err != nil { 86 return err 87 } 88 89 for _, fi := range dir { 90 childPath := filepath.Join(pth, fi.Name()) 91 92 if fi.IsDir() && level < 3 { 93 s.LoadDef(childPath, files, level+1) 94 95 } else { 96 *files = append(*files, childPath) 97 98 } 99 } 100 101 return nil 102 } 103 104 func (s *MockService) GetResp(reqPath, reqMethod, respCode, mediaType string) (ret interface{}, err error) { 105 servicePath, apiPath := s.getServiceAndApiPath(reqPath) 106 reqMethod = strings.ToLower(reqMethod) 107 108 if MockServiceDataMap[servicePath] == nil { 109 err = errors.New("no matched service OR service not start") 110 return 111 } 112 113 for pth, mp := range MockServiceDataMap[servicePath] { 114 if !regexp.MustCompile(pth).MatchString(apiPath) { // no match 115 continue 116 } 117 118 if mp[reqMethod] == nil { // no such a method 119 continue 120 } 121 122 mockPo, err := s.MockRepo.GetByPath(servicePath) 123 if err != nil { 124 continue 125 } 126 127 endpoint := mp[reqMethod][respCode][mediaType] 128 129 key := fmt.Sprintf("%s-%s-%s-%s", 130 MockServiceDataRegxPathToOrigPath[servicePath][pth], reqMethod, respCode, mediaType) 131 src, _ := s.MockRepo.GetSampleSrc(mockPo.ID, key) 132 if src.Value != "" && src.Value != "schema" { 133 str := endpoint.Samples[src.Value] 134 if src.Value == "json" { 135 json.Unmarshal([]byte(str), &ret) 136 } else if src.Value == "xml" { 137 xml.Unmarshal([]byte(str), &ret) 138 } else { 139 ret = str 140 } 141 } else { 142 ret, err = s.GenDataForServerRequest(mp[reqMethod][respCode][mediaType], MockServiceDataDefMap[servicePath]) 143 if err != nil { 144 continue 145 } 146 } 147 } 148 149 if ret == nil { 150 err = errors.New("no matched api") 151 return 152 } 153 154 return 155 } 156 157 func (s *MockService) GenDataForServerRequest(endpoint *domain.EndPoint, dataConfigContent string) (ret interface{}, err error) { 158 if endpoint == nil || dataConfigContent == "" { 159 return 160 } 161 162 vari.GlobalVars.RunMode = consts.RunModeServerRequest 163 vari.GlobalVars.Total = endpoint.Lines 164 vari.GlobalVars.OutputFormat = "json" 165 vari.GlobalVars.ExportFields = strings.Split(endpoint.Fields, ",") 166 167 dataType := endpoint.Type 168 if dataType != consts.SchemaTypeArray { 169 vari.GlobalVars.Total = 1 170 } 171 172 contents := [][]byte{[]byte(dataConfigContent)} 173 174 s.MainService.GenerateDataByContents(contents) 175 176 records := s.OutputService.GenRecords() 177 if dataType == "item" { 178 ret = records[0] 179 } else { 180 ret = records 181 } 182 183 return 184 } 185 186 func (s *MockService) GenDataForMockPreview(endpoint *domain.EndPoint, dataConfig string) (ret interface{}, err error) { 187 vari.GlobalVars.RunMode = consts.RunModeMockPreview 188 vari.GlobalVars.Total = endpoint.Lines 189 vari.GlobalVars.OutputFormat = "json" 190 vari.GlobalVars.ExportFields = strings.Split(endpoint.Fields, ",") 191 192 dataType := endpoint.Type 193 if dataType != consts.SchemaTypeArray { 194 vari.GlobalVars.Total = 1 195 } 196 197 contents := [][]byte{[]byte(dataConfig)} 198 s.MainService.GenerateDataByContents(contents) 199 200 records := s.OutputService.GenRecords() 201 if dataType == consts.SchemaTypeObject { 202 ret = records[0] 203 } else { 204 ret = records 205 } 206 207 return 208 } 209 210 func (s *MockService) addPrefixIfNeeded(pth string) (ret string) { 211 ret = "/" + strings.TrimPrefix(pth, "/") 212 return 213 } 214 215 func (s *MockService) getPathPatten(pth string) (ret string) { 216 regx := regexp.MustCompile(`({[^}]+?})`) 217 ret = regx.ReplaceAllString(pth, "(.+)") 218 219 ret = "^" + ret + "$" 220 221 return 222 } 223 224 func (s *MockService) Upload(ctx iris.Context, fh *multipart.FileHeader) ( 225 name, content, mockConf, dataConf, pth string, err error, dataPath string) { 226 227 filename, err := fileUtils.GetUploadFileName(fh.Filename) 228 if err != nil { 229 logUtils.PrintTo(fmt.Sprintf("获取文件名失败,错误%s", err.Error())) 230 return 231 } 232 233 targetDir := filepath.Join("upload", dateUtils.DateStr(time.Now())) 234 absDir := filepath.Join(dir.GetCurrentAbPath(), targetDir) 235 236 err = dir.InsureDir(targetDir) 237 if err != nil { 238 logUtils.PrintTo(fmt.Sprintf("文件上传失败,错误%s", err.Error())) 239 return 240 } 241 242 pth = filepath.Join(absDir, filename) 243 _, err = ctx.SaveFormFile(fh, pth) 244 if err != nil { 245 logUtils.PrintTo(fmt.Sprintf("文件上传失败,错误%s", err.Error())) 246 return 247 } 248 249 content = fileUtils.ReadFile(pth) 250 251 vari.GlobalVars.Output = fileUtils.GetFileOrFolderDir(pth) 252 name, mockPath, dataPath, err := s.MockService.GenMockDef(pth) 253 254 if err == nil { 255 mockConf = fileUtils.ReadFile(mockPath) 256 dataConf = fileUtils.ReadFile(dataPath) 257 } 258 259 return 260 } 261 262 func (s *MockService) GetPreviewData(id int) (data domain.MockData, err error) { 263 po, err := s.MockRepo.Get(uint(id)) 264 265 yaml.Unmarshal([]byte(po.MockContent), &data) 266 data.Id = id 267 268 return 269 } 270 271 func (s *MockService) GetPreviewResp(req domain.MockPreviewReq) (ret interface{}, err error) { 272 po, err := s.MockRepo.Get(uint(req.Id)) 273 274 data := domain.MockData{} 275 err = yaml.Unmarshal([]byte(po.MockContent), &data) 276 if err != nil { 277 return 278 } 279 280 for pth, mp := range data.Paths { 281 if req.Url == pth { 282 endpoint := mp[req.Method][req.Code][req.Media] 283 284 key := fmt.Sprintf("%s-%s-%s-%s", pth, req.Method, req.Code, req.Media) 285 src, _ := s.MockRepo.GetSampleSrc(uint(req.Id), key) 286 if src.Value != "" && src.Value != "schema" { 287 str := endpoint.Samples[src.Value] 288 if src.Value == "json" { 289 ret = stringUtils.FormatJsonStr(str) 290 } else { 291 ret = str 292 } 293 } else { 294 ret, _ = s.GenDataForMockPreview(endpoint, po.DataContent) 295 } 296 297 return 298 } 299 } 300 301 return 302 } 303 304 func (s *MockService) StartMockService(id int) (err error) { 305 po, err := s.MockRepo.Get(uint(id)) 306 307 mockDef := domain.MockData{} 308 err = yaml.Unmarshal([]byte(po.MockContent), &mockDef) 309 if err != nil { 310 return 311 } 312 313 dataDef := domain.DefData{} 314 err = yaml.Unmarshal([]byte(po.DataContent), &dataDef) 315 if err != nil { 316 return 317 } 318 319 apiPath := po.Path 320 MockServiceDataDefMap[apiPath] = po.DataContent 321 322 if MockServiceDataMap[apiPath] == nil { 323 MockServiceDataMap[apiPath] = domain.MockPathMap{} 324 } 325 326 for pth, mp := range mockDef.Paths { 327 pattern := s.getPathPatten(pth) 328 MockServiceDataMap[apiPath][pattern] = mp 329 330 if MockServiceDataRegxPathToOrigPath[apiPath] == nil { 331 MockServiceDataRegxPathToOrigPath[apiPath] = map[string]string{} 332 } 333 MockServiceDataRegxPathToOrigPath[apiPath][pattern] = pth 334 } 335 336 return 337 } 338 339 func (s *MockService) StopMockService(id int) (err error) { 340 po, err := s.MockRepo.Get(uint(id)) 341 342 mockDef := domain.MockData{} 343 err = yaml.Unmarshal([]byte(po.MockContent), &mockDef) 344 if err != nil { 345 return 346 } 347 348 dataDef := domain.DefData{} 349 err = yaml.Unmarshal([]byte(po.DataContent), &dataDef) 350 if err != nil { 351 return 352 } 353 354 apiPath := po.Path 355 356 MockServiceDataMap[apiPath] = domain.MockPathMap{} 357 358 return 359 } 360 361 func (s *MockService) getServiceAndApiPath(uri string) (servicePath, apiPath string) { 362 arr := strings.Split(uri, "/") 363 if len(arr) < 2 { 364 return 365 } 366 367 servicePath = arr[0] 368 apiPath = strings.Join(arr[1:], "/") 369 370 apiPath = s.addPrefixIfNeeded(apiPath) 371 372 return 373 } 374 375 func (s *MockService) ListSampleSrc(mockId int) (ret map[string]string, err error) { 376 pos, err := s.MockRepo.ListSampleSrc(mockId) 377 if err != nil { 378 return 379 } 380 381 ret = map[string]string{} 382 for _, po := range pos { 383 ret[po.Key] = po.Value 384 } 385 386 return 387 } 388 389 func (s *MockService) ChangeSampleSrc(mockId int, req model.ZdMockSampleSrc) (err error) { 390 return s.MockRepo.ChangeSampleSrc(mockId, req) 391 }