From 582072e174fd50236cebb0d37bbd987269fab8a0 Mon Sep 17 00:00:00 2001 From: Liujian <824010343@qq.com> Date: Fri, 30 Aug 2024 16:48:43 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=AF=E7=94=B1=E3=80=81=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/{api => router}/iml.go | 18 +- controller/{api/api.go => router/router.go} | 16 +- controller/system/iml.go | 6 +- controller/system/import.go | 24 +-- frontend/frontend.go | 4 +- module/api/api.go | 50 ----- module/{api => router}/dto/input.go | 72 ++----- module/{api => router}/dto/output.go | 20 +- module/{api => router}/iml.go | 209 ++++++++++---------- module/router/router.go | 48 +++++ plugins/core/api.go | 12 +- plugins/core/core.go | 7 +- plugins/core/dynamic-module.go | 2 +- resources/access/access.yaml | 38 ++-- resources/access/role.yaml | 20 +- service/api-doc/iml.go | 10 +- service/api-doc/service.go | 37 ++-- service/api/iml.go | 102 +++++----- service/api/model.go | 52 ++--- service/api/service.go | 6 +- stores/api/api.go | 4 +- stores/api/model.go | 19 +- 22 files changed, 386 insertions(+), 390 deletions(-) rename controller/{api => router}/iml.go (81%) rename controller/{api/api.go => router/router.go} (68%) delete mode 100644 module/api/api.go rename module/{api => router}/dto/input.go (57%) rename module/{api => router}/dto/output.go (91%) rename module/{api => router}/iml.go (56%) create mode 100644 module/router/router.go diff --git a/controller/api/iml.go b/controller/router/iml.go similarity index 81% rename from controller/api/iml.go rename to controller/router/iml.go index 9935c636..d4aa2023 100644 --- a/controller/api/iml.go +++ b/controller/router/iml.go @@ -1,33 +1,33 @@ -package api +package router import ( - "github.com/APIParkLab/APIPark/module/api" api_doc "github.com/APIParkLab/APIPark/module/api-doc" api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto" - api_dto "github.com/APIParkLab/APIPark/module/api/dto" + "github.com/APIParkLab/APIPark/module/router" + router_dto "github.com/APIParkLab/APIPark/module/router/dto" "github.com/gin-gonic/gin" "io" ) -var _ IAPIController = (*imlAPIController)(nil) +var _ IRouterController = (*imlAPIController)(nil) type imlAPIController struct { - module api.IApiModule `autowired:""` + module router.IRouterModule `autowired:""` } -func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) { +func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) { return i.module.Detail(ctx, serviceId, apiId) } -func (i *imlAPIController) Search(ctx *gin.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) { +func (i *imlAPIController) Search(ctx *gin.Context, keyword string, serviceId string) ([]*router_dto.Item, error) { return i.module.Search(ctx, keyword, serviceId) } -func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) { +func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) { return i.module.Create(ctx, serviceId, dto) } -func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) { +func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) { return i.module.Edit(ctx, serviceId, apiId, dto) } diff --git a/controller/api/api.go b/controller/router/router.go similarity index 68% rename from controller/api/api.go rename to controller/router/router.go index f0791865..a406947e 100644 --- a/controller/api/api.go +++ b/controller/router/router.go @@ -1,4 +1,4 @@ -package api +package router import ( api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto" @@ -8,18 +8,18 @@ import ( "github.com/eolinker/go-common/autowire" - api_dto "github.com/APIParkLab/APIPark/module/api/dto" + router_dto "github.com/APIParkLab/APIPark/module/router/dto" ) -type IAPIController interface { +type IRouterController interface { // Detail 获取API详情 - Detail(ctx *gin.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) + Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) // Search 获取API列表 - Search(ctx *gin.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) + Search(ctx *gin.Context, keyword string, serviceId string) ([]*router_dto.Item, error) // Create 创建API - Create(ctx *gin.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) + Create(ctx *gin.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) // Edit 编辑API - Edit(ctx *gin.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) + Edit(ctx *gin.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) // Delete 删除API Delete(ctx *gin.Context, serviceId string, apiId string) error // Prefix 获取API前缀 @@ -36,7 +36,7 @@ type IAPIDocController interface { } func init() { - autowire.Auto[IAPIController](func() reflect.Value { + autowire.Auto[IRouterController](func() reflect.Value { return reflect.ValueOf(new(imlAPIController)) }) diff --git a/controller/system/iml.go b/controller/system/iml.go index 5dc8c0d5..c471a6c4 100644 --- a/controller/system/iml.go +++ b/controller/system/iml.go @@ -5,9 +5,9 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/APIParkLab/APIPark/module/api" application_authorization "github.com/APIParkLab/APIPark/module/application-authorization" "github.com/APIParkLab/APIPark/module/catalogue" + "github.com/APIParkLab/APIPark/module/router" "github.com/APIParkLab/APIPark/module/service" "github.com/APIParkLab/APIPark/module/subscribe" "github.com/APIParkLab/APIPark/module/team" @@ -23,7 +23,7 @@ type imlExportConfigController struct { teamModule team.ITeamExportModule `autowired:""` serviceModule service.IExportServiceModule `autowired:""` appModule service.IExportAppModule `autowired:""` - apiModule api.IExportApiModule `autowired:""` + routerModule router.IExportRouterModule `autowired:""` upstreamModule upstream.IExportUpstreamModule `autowired:""` applicationAuthorizationModule application_authorization.IExportAuthorizationModule `autowired:""` catalogueModule catalogue.IExportCatalogueModule `autowired:""` @@ -114,7 +114,7 @@ func (i *imlExportConfigController) appendFiles(ctx *gin.Context) ([]*ExportFile }, { exportFunc: func(ctx *gin.Context) (interface{}, error) { - return i.apiModule.ExportAll(ctx) + return i.routerModule.ExportAll(ctx) }, driver: "api", }, diff --git a/controller/system/import.go b/controller/system/import.go index ebab4f25..cfcc23a6 100644 --- a/controller/system/import.go +++ b/controller/system/import.go @@ -6,8 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/APIParkLab/APIPark/module/api" - api_dto "github.com/APIParkLab/APIPark/module/api/dto" application_authorization "github.com/APIParkLab/APIPark/module/application-authorization" application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto" "github.com/APIParkLab/APIPark/module/catalogue" @@ -16,6 +14,8 @@ import ( "github.com/APIParkLab/APIPark/module/publish/dto" "github.com/APIParkLab/APIPark/module/release" dto2 "github.com/APIParkLab/APIPark/module/release/dto" + "github.com/APIParkLab/APIPark/module/router" + router_dto "github.com/APIParkLab/APIPark/module/router/dto" "github.com/APIParkLab/APIPark/module/service" service_dto "github.com/APIParkLab/APIPark/module/service/dto" "github.com/APIParkLab/APIPark/module/subscribe" @@ -52,7 +52,7 @@ type imlImportConfigController struct { teamModule team.ITeamModule `autowired:""` serviceModule service.IServiceModule `autowired:""` appModule service.IAppModule `autowired:""` - apiModule api.IApiModule `autowired:""` + apiModule router.IRouterModule `autowired:""` upstreamModule upstream.IUpstreamModule `autowired:""` applicationAuthorizationModule application_authorization.IAuthorizationModule `autowired:""` catalogueModule catalogue.ICatalogueModule `autowired:""` @@ -231,14 +231,14 @@ func (i *imlImportConfigController) importApplications(ctx context.Context) erro } func (i *imlImportConfigController) importApis(ctx context.Context) error { - data, err := unmarshal[api_dto.ExportAPI]("api") + data, err := unmarshal[router_dto.Export]("api") if err != nil { return err } for _, d := range data { - var proxy *api_dto.InputProxy + var proxy *router_dto.InputProxy if d.Proxy != nil { - proxy = &api_dto.InputProxy{ + proxy = &router_dto.InputProxy{ Path: d.Proxy.Path, Timeout: d.Proxy.Timeout, Retry: d.Proxy.Retry, @@ -253,11 +253,10 @@ func (i *imlImportConfigController) importApis(ctx context.Context) error { if !errors.Is(err, gorm.ErrRecordNotFound) { return err } - _, err = i.apiModule.Create(ctx, d.Service, &api_dto.CreateApi{ + _, err = i.apiModule.Create(ctx, d.Service, &router_dto.Create{ Id: d.Id, - Name: d.Name, Path: d.Path, - Method: d.Method, + Methods: d.Method, Description: d.Description, MatchRules: d.MatchRules, Proxy: proxy, @@ -268,11 +267,8 @@ func (i *imlImportConfigController) importApis(ctx context.Context) error { continue } - info := &api_dto.EditApi{ - Info: api_dto.EditInfo{ - Name: &d.Name, - Description: &d.Description, - }, + info := &router_dto.Edit{ + Proxy: proxy, //Doc: &d.Doc, } diff --git a/frontend/frontend.go b/frontend/frontend.go index fb85f8ce..d7d91afc 100644 --- a/frontend/frontend.go +++ b/frontend/frontend.go @@ -81,10 +81,10 @@ func IndexHtml(ginCtx *gin.Context) { func (f *Frontend) Api() []pm3.Api { return []pm3.Api{ - pm3.CreateApiSimple(http.MethodGet, "/favicon.ico", func(ginCtx *gin.Context) { + pm3.CreateRouterSimple(http.MethodGet, "/favicon.ico", func(ginCtx *gin.Context) { ginCtx.Data(http.StatusOK, iconType, iconContent) }), - pm3.CreateApiSimple(http.MethodGet, "/vite.svg", func(ginCtx *gin.Context) { + pm3.CreateRouterSimple(http.MethodGet, "/vite.svg", func(ginCtx *gin.Context) { ginCtx.Data(http.StatusOK, viteContentType, viteContent) }), } diff --git a/module/api/api.go b/module/api/api.go deleted file mode 100644 index eef6916f..00000000 --- a/module/api/api.go +++ /dev/null @@ -1,50 +0,0 @@ -package api - -import ( - "context" - "github.com/APIParkLab/APIPark/module/system" - "reflect" - - "github.com/eolinker/go-common/autowire" - - api_dto "github.com/APIParkLab/APIPark/module/api/dto" -) - -type IApiModule interface { - // Detail 获取API详情 - Detail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) - // SimpleDetail 获取API简要详情 - SimpleDetail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiSimpleDetail, error) - // Search 获取API列表 - Search(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) - // SimpleSearch 获取API简要列表 - SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiSimpleItem, error) - SimpleList(ctx context.Context, serviceId string) ([]*api_dto.ApiSimpleItem, error) - // Create 创建API - Create(ctx context.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) - // Edit 编辑API - Edit(ctx context.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) - // Delete 删除API - Delete(ctx context.Context, serviceId string, apiId string) error - // Copy 复制API - Copy(ctx context.Context, serviceId string, apiId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) - // Prefix 获取API前缀 - Prefix(ctx context.Context, serviceId string) (string, error) - - //ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, error) -} - -type IExportApiModule interface { - system.IExportModule[api_dto.ExportAPI] -} - -func init() { - apiModule := new(imlApiModule) - autowire.Auto[IApiModule](func() reflect.Value { - return reflect.ValueOf(apiModule) - }) - - autowire.Auto[IExportApiModule](func() reflect.Value { - return reflect.ValueOf(apiModule) - }) -} diff --git a/module/api/dto/input.go b/module/router/dto/input.go similarity index 57% rename from module/api/dto/input.go rename to module/router/dto/input.go index 3d4e2232..f281e1e2 100644 --- a/module/api/dto/input.go +++ b/module/router/dto/input.go @@ -1,7 +1,6 @@ -package api_dto +package router_dto import ( - "encoding/json" "errors" "fmt" "github.com/eolinker/go-common/utils" @@ -20,14 +19,15 @@ var validMethods = map[string]struct{}{ "OPTIONS": {}, } -type CreateApi struct { +type Create struct { Id string `json:"id"` - Name string `json:"name"` Path string `json:"path"` - Method string `json:"method"` + Methods []string `json:"methods"` Description string `json:"description"` + Protocols []string `json:"protocols"` MatchRules []Match `json:"match"` Proxy *InputProxy `json:"proxy"` + Disable bool `json:"disable"` } type InputProxy struct { @@ -45,46 +45,28 @@ type Match struct { Pattern string `json:"pattern"` } -func (a *CreateApi) Validate() error { +func (a *Create) Validate() error { if a.Id == "" { return errors.New("id is null") } - if a.Name == "" { - return errors.New("name is null") - } a.Path = fmt.Sprintf("/%s", strings.TrimPrefix(a.Path, "/")) - a.Method = strings.ToUpper(a.Method) - if _, ok := validMethods[a.Method]; !ok { - return fmt.Errorf("method(%s) is invalid", a.Method) + for _, method := range a.Methods { + if _, ok := validMethods[method]; !ok { + return fmt.Errorf("method(%s) is invalid", method) + } } + return nil } -func (a *CreateApi) ToServiceRouter() *api.Router { - router := &api.Router{ - Method: a.Method, - Path: a.Path, - } - for _, match := range a.MatchRules { - router.MatchRules = append(router.MatchRules, &api.Match{ - Position: match.Position, - MatchType: match.MatchType, - Key: match.Key, - Pattern: match.Pattern, - }) - } - return router -} - -type EditApi struct { - Info EditInfo `json:"info"` - Proxy *InputProxy `json:"proxy"` - //Doc *map[string]interface{} `json:"doc"` -} - -type EditInfo struct { - Name *string `json:"name"` - Description *string `json:"description"` +type Edit struct { + Description *string `json:"description"` + Proxy *InputProxy `json:"proxy"` + Path *string `json:"path"` + Methods *[]string `json:"methods"` + Protocols *[]string `json:"protocols"` + MatchRules *[]Match `json:"match"` + Disable *bool `json:"disable"` } func ToServiceProxy(proxy *InputProxy) *api.Proxy { @@ -100,8 +82,7 @@ func ToServiceProxy(proxy *InputProxy) *api.Proxy { }) return &api.Proxy{ - Path: proxy.Path, - //Upstream: proxy.Upstream, + Path: proxy.Path, Timeout: proxy.Timeout, Retry: proxy.Retry, Extends: proxy.Extends, @@ -110,19 +91,6 @@ func ToServiceProxy(proxy *InputProxy) *api.Proxy { } } -func ToServiceDocument(doc map[string]interface{}) *api.Document { - if doc == nil { - return &api.Document{ - Content: "{}", - } - } - content, _ := json.Marshal(doc) - - return &api.Document{ - Content: string(content), - } -} - type ListInput struct { Projects []string `json:"projects"` } diff --git a/module/api/dto/output.go b/module/router/dto/output.go similarity index 91% rename from module/api/dto/output.go rename to module/router/dto/output.go index 9064c098..35765abb 100644 --- a/module/api/dto/output.go +++ b/module/router/dto/output.go @@ -1,4 +1,4 @@ -package api_dto +package router_dto import ( "encoding/json" @@ -9,7 +9,7 @@ import ( "github.com/eolinker/go-common/auto" ) -type ApiItem struct { +type Item struct { Id string `json:"id"` Name string `json:"name"` Methods []string `json:"methods"` @@ -22,27 +22,27 @@ type ApiItem struct { CanDelete bool `json:"can_delete"` } -type ApiSimpleItem struct { +type SimpleItem struct { Id string `json:"id"` Name string `json:"name"` Method string `json:"method"` Path string `json:"request_path"` } -type ApiDetail struct { - ApiSimpleDetail +type Detail struct { + SimpleDetail Proxy *Proxy `json:"proxy"` //Doc map[string]interface{} `json:"doc"` } -func GenApiSimpleDetail(api *api.Info) *ApiSimpleDetail { +func GenSimpleDetail(api *api.Info) *SimpleDetail { match := make([]Match, 0) if api.Match == "" { api.Match = "[]" } json.Unmarshal([]byte(api.Match), &match) - return &ApiSimpleDetail{ + return &SimpleDetail{ Id: api.UUID, Name: api.Name, Description: api.Description, @@ -56,7 +56,7 @@ func GenApiSimpleDetail(api *api.Info) *ApiSimpleDetail { } } -type ApiSimpleDetail struct { +type SimpleDetail struct { Id string `json:"id"` Name string `json:"name"` Description string `json:"description"` @@ -106,11 +106,11 @@ type Header struct { Opt string `json:"opt"` } -type ExportAPI struct { +type Export struct { Id string `json:"id"` Name string `json:"name"` Description string `json:"description"` - Method string `json:"method"` + Method []string `json:"method"` Path string `json:"path"` MatchRules []Match `json:"match"` Service string `json:"service"` diff --git a/module/api/iml.go b/module/router/iml.go similarity index 56% rename from module/api/iml.go rename to module/router/iml.go index dd1005f1..edb258b9 100644 --- a/module/api/iml.go +++ b/module/router/iml.go @@ -1,4 +1,4 @@ -package api +package router import ( "context" @@ -24,12 +24,12 @@ import ( "github.com/APIParkLab/APIPark/service/api" - api_dto "github.com/APIParkLab/APIPark/module/api/dto" + router_dto "github.com/APIParkLab/APIPark/module/router/dto" ) var ( - _ IApiModule = (*imlApiModule)(nil) - _ IExportApiModule = (*imlApiModule)(nil) + _ IRouterModule = (*imlRouterModule)(nil) + _ IExportRouterModule = (*imlRouterModule)(nil) ) var ( asServer = map[string]bool{ @@ -37,7 +37,7 @@ var ( } ) -type imlApiModule struct { +type imlRouterModule struct { teamService team.ITeamService `autowired:""` serviceService service.IServiceService `autowired:""` apiService api.IAPIService `autowired:""` @@ -45,7 +45,7 @@ type imlApiModule struct { transaction store.ITransaction `autowired:""` } -func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, error) { +func (i *imlRouterModule) ExportAll(ctx context.Context) ([]*router_dto.Export, error) { apiList, err := i.apiService.ListInfo(ctx) if err != nil { @@ -62,13 +62,13 @@ func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, err return c.Target }) - return utils.SliceToSlice(apiList, func(a *api.Info) *api_dto.ExportAPI { - match := make([]api_dto.Match, 0) + return utils.SliceToSlice(apiList, func(a *api.Info) *router_dto.Export { + match := make([]router_dto.Match, 0) if a.Match == "" { a.Match = "[]" } json.Unmarshal([]byte(a.Match), &match) - info := &api_dto.ExportAPI{ + info := &router_dto.Export{ Id: a.UUID, Name: a.Name, Description: a.Description, @@ -78,14 +78,14 @@ func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, err Team: a.Team, } if v, ok := proxyCommitMap[a.UUID]; ok { - info.Proxy = api_dto.FromServiceProxy(v.Data) + info.Proxy = router_dto.FromServiceProxy(v.Data) } return info }), nil } -func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api_dto.ApiSimpleItem, error) { +func (i *imlRouterModule) SimpleList(ctx context.Context, serviceId string) ([]*router_dto.SimpleItem, error) { list, err := i.apiService.ListForService(ctx, serviceId) apiInfos, err := i.apiService.ListInfo(ctx, utils.SliceToSlice(list, func(s *api.API) string { @@ -95,8 +95,8 @@ func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api return nil, err } - out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiSimpleItem { - return &api_dto.ApiSimpleItem{ + out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.SimpleItem { + return &router_dto.SimpleItem{ Id: item.UUID, Name: item.Name, Path: item.Path, @@ -105,7 +105,7 @@ func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api return out, nil } -func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) { +func (i *imlRouterModule) Detail(ctx context.Context, serviceId string, apiId string) (*router_dto.Detail, error) { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err @@ -116,8 +116,8 @@ func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId strin return nil, err } - apiDetail := &api_dto.ApiDetail{ - ApiSimpleDetail: *api_dto.GenApiSimpleDetail(detail), + apiDetail := &router_dto.Detail{ + SimpleDetail: *router_dto.GenSimpleDetail(detail), } proxy, err := i.apiService.LatestProxy(ctx, apiId) if err != nil { @@ -126,13 +126,13 @@ func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId strin } } if proxy != nil { - apiDetail.Proxy = api_dto.FromServiceProxy(proxy.Data) + apiDetail.Proxy = router_dto.FromServiceProxy(proxy.Data) } return apiDetail, nil } -func (i *imlApiModule) SimpleDetail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiSimpleDetail, error) { +func (i *imlRouterModule) SimpleDetail(ctx context.Context, serviceId string, apiId string) (*router_dto.SimpleDetail, error) { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err @@ -143,10 +143,10 @@ func (i *imlApiModule) SimpleDetail(ctx context.Context, serviceId string, apiId return nil, err } - return api_dto.GenApiSimpleDetail(detail), nil + return router_dto.GenSimpleDetail(detail), nil } -func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) { +func (i *imlRouterModule) Search(ctx context.Context, keyword string, serviceId string) ([]*router_dto.Item, error) { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err @@ -167,8 +167,8 @@ func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId str utils.Sort(apiInfos, func(a, b *api.Info) bool { return a.UpdateAt.After(b.UpdateAt) }) - out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiItem { - return &api_dto.ApiItem{ + out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.Item { + return &router_dto.Item{ Id: item.UUID, Name: item.Name, Methods: item.Methods, @@ -185,7 +185,7 @@ func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId str return out, nil } -func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiSimpleItem, error) { +func (i *imlRouterModule) SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*router_dto.SimpleItem, error) { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err @@ -203,8 +203,8 @@ func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, service if err != nil { return nil, err } - out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiSimpleItem { - return &api_dto.ApiSimpleItem{ + out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.SimpleItem { + return &router_dto.SimpleItem{ Id: item.UUID, Name: item.Name, //Methods: item.Methods, @@ -214,7 +214,7 @@ func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, service return out, nil } -func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) { +func (i *imlRouterModule) Create(ctx context.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) { info, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err @@ -233,24 +233,25 @@ func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dt } path := fmt.Sprintf("%s%s", prefix, dto.Path) - err = i.apiService.Exist(ctx, "", &api.ExistAPI{Path: dto.Path, Method: dto.Method}) + + err = i.apiService.Exist(ctx, "", &api.Exist{Path: dto.Path, Methods: dto.Methods}) if err != nil { - return fmt.Errorf("api path %s,method: %s already exist", dto.Path, dto.Method) + return err } - proxy := api_dto.ToServiceProxy(dto.Proxy) + + proxy := router_dto.ToServiceProxy(dto.Proxy) err = i.apiService.SaveProxy(ctx, dto.Id, proxy) if err != nil { return err } match, _ := json.Marshal(dto.MatchRules) - return i.apiService.Create(ctx, &api.CreateAPI{ + return i.apiService.Create(ctx, &api.Create{ UUID: dto.Id, - Name: dto.Name, Description: dto.Description, Service: serviceId, Team: info.Team, - Method: dto.Method, + Methods: dto.Methods, Path: path, Match: string(match), }) @@ -261,24 +262,32 @@ func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dt return i.SimpleDetail(ctx, serviceId, dto.Id) } -func (i *imlApiModule) Edit(ctx context.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) { +func (i *imlRouterModule) Edit(ctx context.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return nil, err } err = i.transaction.Transaction(ctx, func(ctx context.Context) error { - var up *string if dto.Proxy != nil { - err = i.apiService.SaveProxy(ctx, apiId, api_dto.ToServiceProxy(dto.Proxy)) + err = i.apiService.SaveProxy(ctx, apiId, router_dto.ToServiceProxy(dto.Proxy)) if err != nil { return err } } - err = i.apiService.Save(ctx, apiId, &api.EditAPI{ - Name: dto.Info.Name, - Description: dto.Info.Description, - Upstream: up, + var match *string + if dto.MatchRules != nil { + ml, _ := json.Marshal(dto.MatchRules) + m := string(ml) + match = &m + } + err = i.apiService.Save(ctx, apiId, &api.Edit{ + Description: dto.Description, + Methods: dto.Methods, + Protocols: dto.Protocols, + Disable: dto.Disable, + Path: dto.Path, + Match: match, }) if err != nil { return err @@ -293,7 +302,7 @@ func (i *imlApiModule) Edit(ctx context.Context, serviceId string, apiId string, return i.SimpleDetail(ctx, serviceId, apiId) } -func (i *imlApiModule) Delete(ctx context.Context, serviceId string, apiId string) error { +func (i *imlRouterModule) Delete(ctx context.Context, serviceId string, apiId string) error { _, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return err @@ -301,67 +310,67 @@ func (i *imlApiModule) Delete(ctx context.Context, serviceId string, apiId strin return i.apiService.Delete(ctx, apiId) } -func (i *imlApiModule) Copy(ctx context.Context, serviceId string, apiId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) { - info, err := i.serviceService.Check(ctx, serviceId, asServer) - if err != nil { - return nil, err - } - oldApi, err := i.apiService.Get(ctx, apiId) - if err != nil { - return nil, err - } - prefix, err := i.Prefix(ctx, serviceId) - if err != nil { - return nil, err - } - err = i.transaction.Transaction(ctx, func(ctx context.Context) error { - if dto.Id == "" { - dto.Id = uuid.New().String() - } - err = dto.Validate() - if err != nil { - return err - } +//func (i *imlRouterModule) Copy(ctx context.Context, serviceId string, apiId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) { +// info, err := i.serviceService.Check(ctx, serviceId, asServer) +// if err != nil { +// return nil, err +// } +// oldApi, err := i.apiService.Get(ctx, apiId) +// if err != nil { +// return nil, err +// } +// prefix, err := i.Prefix(ctx, serviceId) +// if err != nil { +// return nil, err +// } +// err = i.transaction.Transaction(ctx, func(ctx context.Context) error { +// if dto.Id == "" { +// dto.Id = uuid.New().String() +// } +// err = dto.Validate() +// if err != nil { +// return err +// } +// +// path := fmt.Sprintf("%s/%s", strings.TrimSuffix(prefix, "/"), strings.TrimPrefix(dto.Path, "/")) +// err = i.apiService.Exist(ctx, serviceId, &api.Exist{Path: path, Methods: dto.Methods}) +// if err != nil { +// return err +// } +// +// proxy, err := i.apiService.LatestProxy(ctx, oldApi.UUID) +// if err != nil { +// if !errors.Is(err, gorm.ErrRecordNotFound) { +// return err +// } +// } +// //upstreamId := "" +// if proxy != nil { +// err = i.apiService.SaveProxy(ctx, dto.Id, proxy.Data) +// if err != nil { +// return err +// } +// } +// +// match, _ := json.Marshal(dto.MatchRules) +// return i.apiService.Create(ctx, &api.Create{ +// UUID: dto.Id, +// Name: dto.Name, +// Service: serviceId, +// Team: info.Team, +// Methods: dto.Methods, +// Path: path, +// Match: string(match), +// }) +// +// }) +// if err != nil { +// return nil, err +// } +// return i.SimpleDetail(ctx, serviceId, dto.Id) +//} - path := fmt.Sprintf("%s/%s", strings.TrimSuffix(prefix, "/"), strings.TrimPrefix(dto.Path, "/")) - err = i.apiService.Exist(ctx, serviceId, &api.ExistAPI{Path: path, Method: dto.Method}) - if err != nil { - return err - } - - proxy, err := i.apiService.LatestProxy(ctx, oldApi.UUID) - if err != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return err - } - } - //upstreamId := "" - if proxy != nil { - err = i.apiService.SaveProxy(ctx, dto.Id, proxy.Data) - if err != nil { - return err - } - } - - match, _ := json.Marshal(dto.MatchRules) - return i.apiService.Create(ctx, &api.CreateAPI{ - UUID: dto.Id, - Name: dto.Name, - Service: serviceId, - Team: info.Team, - Method: dto.Method, - Path: path, - Match: string(match), - }) - - }) - if err != nil { - return nil, err - } - return i.SimpleDetail(ctx, serviceId, dto.Id) -} - -func (i *imlApiModule) Prefix(ctx context.Context, serviceId string) (string, error) { +func (i *imlRouterModule) Prefix(ctx context.Context, serviceId string) (string, error) { pInfo, err := i.serviceService.Check(ctx, serviceId, asServer) if err != nil { return "", err diff --git a/module/router/router.go b/module/router/router.go new file mode 100644 index 00000000..1a43b958 --- /dev/null +++ b/module/router/router.go @@ -0,0 +1,48 @@ +package router + +import ( + "context" + "github.com/APIParkLab/APIPark/module/system" + "reflect" + + "github.com/eolinker/go-common/autowire" + + router_dto "github.com/APIParkLab/APIPark/module/router/dto" +) + +type IRouterModule interface { + // Detail 获取API详情 + Detail(ctx context.Context, serviceId string, apiId string) (*router_dto.Detail, error) + // SimpleDetail 获取API简要详情 + SimpleDetail(ctx context.Context, serviceId string, apiId string) (*router_dto.SimpleDetail, error) + // Search 获取API列表 + Search(ctx context.Context, keyword string, serviceId string) ([]*router_dto.Item, error) + // SimpleSearch 获取API简要列表 + SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*router_dto.SimpleItem, error) + SimpleList(ctx context.Context, serviceId string) ([]*router_dto.SimpleItem, error) + // Create 创建API + Create(ctx context.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) + // Edit 编辑API + Edit(ctx context.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) + // Delete 删除API + Delete(ctx context.Context, serviceId string, apiId string) error + // Prefix 获取API前缀 + Prefix(ctx context.Context, serviceId string) (string, error) + + //ExportAll(ctx context.Context) ([]*router_dto.Export, error) +} + +type IExportRouterModule interface { + system.IExportModule[router_dto.Export] +} + +func init() { + apiModule := new(imlRouterModule) + autowire.Auto[IRouterModule](func() reflect.Value { + return reflect.ValueOf(apiModule) + }) + + autowire.Auto[IExportRouterModule](func() reflect.Value { + return reflect.ValueOf(apiModule) + }) +} diff --git a/plugins/core/api.go b/plugins/core/api.go index 42c84414..80a2c1ab 100644 --- a/plugins/core/api.go +++ b/plugins/core/api.go @@ -8,12 +8,12 @@ import ( func (p *plugin) apiApis() []pm3.Api { return []pm3.Api{ - pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/apis", []string{"context", "query:keyword", "query:service"}, []string{"apis"}, p.apiController.Search), - pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api/detail", []string{"context", "query:service", "query:api"}, []string{"api"}, p.apiController.Detail), - pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/service/api", []string{"context", "query:service", "body"}, []string{"api"}, p.apiController.Create), - pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/api", []string{"context", "query:service", "query:api", "body"}, []string{"api"}, p.apiController.Edit), - pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/service/api", []string{"context", "query:service", "query:api"}, nil, p.apiController.Delete), - pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api/define", []string{"context", "query:service"}, []string{"prefix", "force"}, p.apiController.Prefix), + pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/routers", []string{"context", "query:keyword", "query:service"}, []string{"routers"}, p.routerController.Search), + pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/router/detail", []string{"context", "query:service", "query:router"}, []string{"router"}, p.routerController.Detail), + pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/service/router", []string{"context", "query:service", "body"}, []string{"router"}, p.routerController.Create), + pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/router", []string{"context", "query:service", "query:router", "body"}, []string{"router"}, p.routerController.Edit), + pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/service/router", []string{"context", "query:service", "query:router"}, nil, p.routerController.Delete), + pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/router/define", []string{"context", "query:service"}, []string{"prefix", "force"}, p.routerController.Prefix), pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/api_doc", []string{"context", "query:service", "body"}, []string{"doc"}, p.apiDocController.UpdateDoc), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api_doc", []string{"context", "query:service"}, []string{"doc"}, p.apiDocController.GetDoc), diff --git a/plugins/core/core.go b/plugins/core/core.go index 60e7f7a8..9b870fb3 100644 --- a/plugins/core/core.go +++ b/plugins/core/core.go @@ -2,6 +2,7 @@ package core import ( "github.com/APIParkLab/APIPark/controller/monitor" + "github.com/APIParkLab/APIPark/controller/router" "github.com/APIParkLab/APIPark/controller/system" "net/http" @@ -21,8 +22,6 @@ import ( "github.com/APIParkLab/APIPark/controller/subscribe" - "github.com/APIParkLab/APIPark/controller/api" - "github.com/APIParkLab/APIPark/controller/upstream" "github.com/APIParkLab/APIPark/controller/service" @@ -66,8 +65,8 @@ type plugin struct { monitorConfigController monitor.IMonitorConfigController `autowired:""` catalogueController catalogue.ICatalogueController `autowired:""` upstreamController upstream.IUpstreamController `autowired:""` - apiController api.IAPIController `autowired:""` - apiDocController api.IAPIDocController `autowired:""` + routerController router.IRouterController `autowired:""` + apiDocController router.IAPIDocController `autowired:""` subscribeController subscribe.ISubscribeController `autowired:""` appAuthorizationController application_authorization.IAuthorizationController `autowired:""` releaseController release.IReleaseController `autowired:""` diff --git a/plugins/core/dynamic-module.go b/plugins/core/dynamic-module.go index 0c4e4305..94dd7e26 100644 --- a/plugins/core/dynamic-module.go +++ b/plugins/core/dynamic-module.go @@ -2,7 +2,7 @@ package core import ( "net/http" - + "github.com/eolinker/go-common/pm3" ) diff --git a/resources/access/access.yaml b/resources/access/access.yaml index 131511f9..9748dfba 100644 --- a/resources/access/access.yaml +++ b/resources/access/access.yaml @@ -235,28 +235,42 @@ team: cname: 服务 value: 'service' children: - - name: api - cname: API - value: 'api' + - name: router + cname: 路由 + value: 'router' children: - name: view cname: 查看 value: 'view' guest_allow: true apis: - - "GET:/api/v1/service/apis" - - "GET:/api/v1/service/api/detail" - - "GET:/api/v1/service/api/detail/simple" - - "GET:/api/v1/service/api/define" - - "GET:/api/v1/service/apis/simple" + - "GET:/api/v1/service/routers" + - "GET:/api/v1/service/router/detail" + - "GET:/api/v1/service/router/detail/simple" + - "GET:/api/v1/service/router/define" - name: manager cname: 管理 value: 'manager' apis: - - "POST:/api/v1/service/api" - - "PUT:/api/v1/service/api" - - "DELETE:/api/v1/service/api" - - "POST:/api/v1/service/api/copy" + - "POST:/api/v1/service/router" + - "PUT:/api/v1/service/router" + - "DELETE:/api/v1/service/router" + - name: api_doc + cname: API文档 + value: 'api_doc' + children: + - name: view + cname: 查看 + value: 'view' + guest_allow: true + apis: + - "GET:/api/v1/service/api_doc" + - name: manager + cname: 管理 + value: 'manager' + apis: + - "PUT:/api/v1/service/api_doc" + - "POST:/api/v1/service/api_doc/upload" - name: upstream cname: 上游 value: 'upstream' diff --git a/resources/access/role.yaml b/resources/access/role.yaml index 0bac3482..406b1006 100644 --- a/resources/access/role.yaml +++ b/resources/access/role.yaml @@ -83,8 +83,10 @@ team: - team.application.authorization.view - team.application.subscription.manager - team.application.subscription.view - - team.service.api.manager - - team.service.api.view + - team.service.api_doc.view + - team.service.api_doc.manager + - team.service.router.manager + - team.service.router.view - team.service.release.manager - team.service.release.view - team.service.service.manager @@ -103,8 +105,10 @@ team: - team.service.service.manager - team.service.upstream.manager - team.service.upstream.view - - team.service.api.manager - - team.service.api.view + - team.service.api_doc.view + - team.service.api_doc.manager + - team.service.router.manager + - team.service.router.view - team.service.subscription.manager - team.service.subscription.view - team.service.release.manager @@ -115,8 +119,10 @@ team: permits: - team.service.upstream.manager - team.service.upstream.view - - team.service.api.manager - - team.service.api.view + - team.service.api_doc.view + - team.service.api_doc.manager + - team.service.router.manager + - team.service.router.view - team.service.release.manager - team.service.release.view - team.team.member.view @@ -142,7 +148,7 @@ team: permits: - team.application.authorization.view - team.application.subscription.view - - team.service.api.view + - team.service.router.view - team.service.release.view - team.service.subscription.view - team.service.upstream.view diff --git a/service/api-doc/iml.go b/service/api-doc/iml.go index e55c674d..aa3f47a9 100644 --- a/service/api-doc/iml.go +++ b/service/api-doc/iml.go @@ -20,10 +20,14 @@ type imlAPIDocService struct { } func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, input *UpdateDoc) error { - // 校验内容格式是否正确 - if err := ValidDoc(input.Content); err != nil { + doc, err := NewDocLoader(input.Content) + if err != nil { return err } + if err := doc.Valid(); err != nil { + return err + } + info, err := i.store.First(ctx, map[string]interface{}{ "service": serviceId, }) @@ -38,10 +42,12 @@ func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, inpu Content: input.Content, Updater: operator, UpdateAt: time.Now(), + APICount: doc.APICount(), }) } info.Updater = operator info.UpdateAt = time.Now() + info.APICount = doc.APICount() return i.store.Save(ctx, info) } diff --git a/service/api-doc/service.go b/service/api-doc/service.go index 76408428..0a8ec7ac 100644 --- a/service/api-doc/service.go +++ b/service/api-doc/service.go @@ -30,29 +30,32 @@ var ( loader = openapi3.NewLoader() ) -func ValidDoc(content string) error { - doc, err := loader.LoadFromData([]byte(content)) - if err != nil { - return fmt.Errorf("failed to load OpenAPI document: %v", err) - } - err = doc.Validate(loader.Context) - if err != nil { - return fmt.Errorf("OpenAPI document is not valid: %v", err) - } - - return nil +type DocLoader struct { + doc *openapi3.T } -func DocAPICount(content string) (int64, error) { +func NewDocLoader(content string) (*DocLoader, error) { doc, err := loader.LoadFromData([]byte(content)) if err != nil { - return 0, err + return nil, fmt.Errorf("load doc error:%v", err) } - if doc.Paths == nil { - return 0, nil + return &DocLoader{doc: doc}, nil +} + +func (d *DocLoader) Valid() error { + if d.doc == nil { + return fmt.Errorf("doc is nil") + } + + return d.doc.Validate(loader.Context) +} + +func (d *DocLoader) APICount() int64 { + if d.doc == nil || d.doc.Paths == nil { + return 0 } var count int64 - for _, item := range doc.Paths.Map() { + for _, item := range d.doc.Paths.Map() { if item.Get != nil { count++ } @@ -78,5 +81,5 @@ func DocAPICount(content string) (int64, error) { count++ } } - return count, nil + return count } diff --git a/service/api/iml.go b/service/api/iml.go index 02eea2f1..4e72d159 100644 --- a/service/api/iml.go +++ b/service/api/iml.go @@ -50,7 +50,7 @@ func (i *imlAPIService) ListInfoForService(ctx context.Context, serviceId string apis, err := i.store.List(ctx, map[string]interface{}{ "service": serviceId, }) - aids := utils.SliceToSlice(apis, func(a *api.Api) int64 { + aids := utils.SliceToSlice(apis, func(a *api.API) int64 { return a.Id }) list, err := i.apiInfoStore.List(ctx, map[string]interface{}{ @@ -84,7 +84,7 @@ func (i *imlAPIService) GetInfo(ctx context.Context, aid string) (*Info, error) return FromEntityInfo(info), nil } -func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) error { +func (i *imlAPIService) Save(ctx context.Context, id string, model *Edit) error { if model == nil { return errors.New("input is nil") } @@ -93,12 +93,26 @@ func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) err if err != nil { return err } - if model.Name != nil { - ev.Name = *model.Name - } + if model.Description != nil { ev.Description = *model.Description } + if model.Protocols != nil { + ev.Protocol = *model.Protocols + } + if model.Path != nil { + ev.Path = *model.Path + } + if model.Match != nil { + ev.Match = *model.Match + } + if model.Methods != nil { + ev.Method = *model.Methods + } + if model.Disable != nil { + ev.Disable = *model.Disable + } + e := i.apiInfoStore.Save(ctx, ev) if e != nil { return e @@ -109,48 +123,31 @@ func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) err } func getLabels(input *api.Info, appends ...string) []string { labels := make([]string, 0, len(appends)+9) - labels = append(labels, input.UUID, input.Name, input.Description, input.Method, input.Path, input.Service, input.Team, input.Updater) + labels = append(labels, input.UUID, input.Name, input.Description, input.Path, input.Service, input.Team, input.Updater) labels = append(labels, appends...) return labels } -func (i *imlAPIService) Create(ctx context.Context, input *CreateAPI) (err error) { +func (i *imlAPIService) Create(ctx context.Context, input *Create) (err error) { operater := utils.UserId(ctx) return i.store.Transaction(ctx, func(ctx context.Context) error { - t, err := i.store.First(ctx, map[string]interface{}{ - "method": input.Method, - "path": input.Path, - }) - if err != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return err - } - } - - if t != nil { - return fmt.Errorf("method(%s),path(%s) is exist", input.Method, input.Path) - } if input.UUID != "" { - a, err := i.store.GetByUUID(ctx, input.UUID) + _, err = i.store.GetByUUID(ctx, input.UUID) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } - if a != nil { - return fmt.Errorf("api(%s) is exist", input.UUID) - } } else { input.UUID = uuid.NewString() } - ne := api.Api{ - Id: 0, + ne := api.API{ UUID: input.UUID, + Name: input.UUID, Service: input.Service, Team: input.Team, Creator: operater, CreateAt: time.Now(), - IsDelete: 0, - Method: input.Method, + Method: input.Methods, Path: input.Path, } err = i.store.Insert(ctx, &ne) @@ -160,18 +157,17 @@ func (i *imlAPIService) Create(ctx context.Context, input *CreateAPI) (err error ev := &api.Info{ Id: ne.Id, UUID: ne.UUID, - Name: input.Name, + Name: ne.UUID, Description: input.Description, Updater: operater, UpdateAt: time.Now(), Creator: operater, CreateAt: time.Now(), - //Upstream: input.Upstream, - Method: input.Method, - Path: input.Path, - Match: input.Match, - Service: input.Service, - Team: input.Team, + Method: input.Methods, + Path: input.Path, + Match: input.Match, + Service: input.Service, + Team: input.Team, } err = i.apiInfoStore.Save(ctx, ev) if err != nil { @@ -195,19 +191,29 @@ func (i *imlAPIService) CountByService(ctx context.Context, service string) (int }) } -func (i *imlAPIService) Exist(ctx context.Context, aid string, a *ExistAPI) error { - t, err := i.store.First(ctx, map[string]interface{}{ - "method": a.Method, - "path": a.Path, +func (i *imlAPIService) Exist(ctx context.Context, aid string, a *Exist) error { + list, err := i.store.Search(ctx, "", map[string]interface{}{ + "path": a.Path, }) if err != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - return err - } - return nil + return err } - if t.UUID != aid { - return fmt.Errorf("method(%s),path(%s) is exist", a.Method, a.Path) + existMethodMap := make(map[string]struct{}) + for _, t := range list { + if len(t.Method) == 0 { + if t.UUID != aid { + return fmt.Errorf("method(%v),path(%s) is exist", a.Methods, a.Path) + } + continue + } + for _, m := range t.Method { + existMethodMap[m] = struct{}{} + } + } + for _, m := range a.Methods { + if _, ok := existMethodMap[m]; ok { + return fmt.Errorf("method(%s),path(%s) is exist", m, a.Path) + } } return nil } @@ -219,7 +225,7 @@ func (i *imlAPIService) ListForService(ctx context.Context, serviceId string) ([ } return utils.SliceToSlice(list, FromEntity), nil } -func (i *imlAPIService) listForService(ctx context.Context, serviceId string, isDelete bool) ([]*api.Api, error) { +func (i *imlAPIService) listForService(ctx context.Context, serviceId string, isDelete bool) ([]*api.API, error) { return i.store.ListQuery(ctx, "service=? and is_delete=?", []interface{}{serviceId, isDelete}, "id") } func (i *imlAPIService) ListLatestCommitProxy(ctx context.Context, apiUUID ...string) ([]*commit.Commit[Proxy], error) { @@ -256,9 +262,9 @@ func (i *imlAPIService) GetLabels(ctx context.Context, ids ...string) map[string } func (i *imlAPIService) OnComplete() { - i.IServiceGet = universally.NewGetSoftDelete[API, api.Api](i.store, FromEntity) + i.IServiceGet = universally.NewGetSoftDelete[API, api.API](i.store, FromEntity) - i.IServiceDelete = universally.NewSoftDelete[api.Api](i.store) + i.IServiceDelete = universally.NewSoftDelete[api.API](i.store) auto.RegisterService("api", i) } diff --git a/service/api/model.go b/service/api/model.go index 47d8c603..e972e157 100644 --- a/service/api/model.go +++ b/service/api/model.go @@ -1,9 +1,6 @@ package api import ( - "encoding/json" - "net/http" - "strings" "time" "github.com/APIParkLab/APIPark/model/plugin_model" @@ -40,17 +37,8 @@ type Info struct { Disable bool } -func FromEntity(e *api.Api) *API { - methods := make([]string, 0) - if e.Method != "" { - err := json.Unmarshal([]byte(e.Method), &methods) - if err != nil { - m := strings.ToUpper(e.Method) - if m == http.MethodGet || m == http.MethodPost || m == http.MethodPut || m == http.MethodDelete || m == http.MethodPatch || m == http.MethodHead || m == http.MethodOptions { - methods = append(methods, m) - } - } - } +func FromEntity(e *api.API) *API { + return &API{ UUID: e.UUID, CreateAt: e.CreateAt, @@ -58,23 +46,13 @@ func FromEntity(e *api.Api) *API { Service: e.Service, Team: e.Team, Creator: e.Creator, - Method: methods, + Method: e.Method, Path: e.Path, Protocols: e.Protocol, } } func FromEntityInfo(e *api.Info) *Info { - methods := make([]string, 0) - if e.Method != "" { - err := json.Unmarshal([]byte(e.Method), &methods) - if err != nil { - m := strings.ToUpper(e.Method) - if m == http.MethodGet || m == http.MethodPost || m == http.MethodPut || m == http.MethodDelete || m == http.MethodPatch || m == http.MethodHead || m == http.MethodOptions { - methods = append(methods, m) - } - } - } return &Info{ UUID: e.UUID, Name: e.Name, @@ -85,7 +63,7 @@ func FromEntityInfo(e *api.Info) *Info { Team: e.Team, Creator: e.Creator, Updater: e.Updater, - Methods: methods, + Methods: e.Method, Protocols: e.Protocol, Path: e.Path, Match: e.Match, @@ -93,26 +71,30 @@ func FromEntityInfo(e *api.Info) *Info { } } -type CreateAPI struct { +type Create struct { UUID string - Name string Description string Service string Team string - Method string + Methods []string + Protocols []string + Disable bool Path string Match string } -type EditAPI struct { - Name *string - Upstream *string +type Edit struct { Description *string + Methods *[]string + Protocols *[]string + Disable *bool + Path *string + Match *string } -type ExistAPI struct { - Path string - Method string +type Exist struct { + Path string + Methods []string } type Document struct { diff --git a/service/api/service.go b/service/api/service.go index 40d38ea1..f054b829 100644 --- a/service/api/service.go +++ b/service/api/service.go @@ -15,7 +15,7 @@ type IAPIService interface { universally.IServiceDelete CountByService(ctx context.Context, service string) (int64, error) CountMapByService(ctx context.Context, service ...string) (map[string]int64, error) - Exist(ctx context.Context, aid string, api *ExistAPI) error + Exist(ctx context.Context, aid string, api *Exist) error ListForService(ctx context.Context, serviceId string) ([]*API, error) GetInfo(ctx context.Context, aid string) (*Info, error) ListInfo(ctx context.Context, aids ...string) ([]*Info, error) @@ -25,8 +25,8 @@ type IAPIService interface { GetProxyCommit(ctx context.Context, commitId string) (*commit.Commit[Proxy], error) ListProxyCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Proxy], error) SaveProxy(ctx context.Context, aid string, data *Proxy) error - Save(ctx context.Context, id string, model *EditAPI) error - Create(ctx context.Context, input *CreateAPI) (err error) + Save(ctx context.Context, id string, model *Edit) error + Create(ctx context.Context, input *Create) (err error) } var ( diff --git a/stores/api/api.go b/stores/api/api.go index dc988874..c8cb4d7a 100644 --- a/stores/api/api.go +++ b/stores/api/api.go @@ -8,11 +8,11 @@ import ( ) type IApiBaseStore interface { - store.ISearchStore[Api] + store.ISearchStore[API] } type IAPIInfoStore store.IBaseStore[Info] type imlApiBaseStore struct { - store.SearchStoreSoftDelete[Api] + store.SearchStoreSoftDelete[API] } type imlAPIDocStore struct { diff --git a/stores/api/model.go b/stores/api/model.go index 93fff571..ed1dca17 100644 --- a/stores/api/model.go +++ b/stores/api/model.go @@ -2,7 +2,7 @@ package api import "time" -type Api struct { +type API struct { Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"` UUID string `gorm:"type:varchar(36);not null;column:uuid;uniqueIndex:uuid;comment:UUID;"` Name string `gorm:"type:varchar(100);not null;column:name;comment:name"` @@ -12,7 +12,7 @@ type Api struct { Creator string `gorm:"size:36;not null;column:creator;comment:创建人;index:creator" aovalue:"creator"` // 创建人 CreateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_at;comment:创建时间"` IsDelete int `gorm:"type:tinyint(1);not null;column:is_delete;comment:是否删除 0:未删除 1:已删除"` - Method string `gorm:"size:36;not null;column:method;comment:请求方法"` + Method []string `gorm:"size:36;not null;column:method;comment:请求方法;serializer:json"` Protocol []string `gorm:"type:text;not null;column:protocol;comment:协议;serializer:json"` Path string `gorm:"size:512;not null;column:path;comment:请求路径"` } @@ -23,7 +23,7 @@ type Info struct { Description string `gorm:"size:255;not null;column:description;comment:description"` Service string `gorm:"size:36;not null;column:service;comment:服务;index:service"` Team string `gorm:"size:36;not null;column:team;comment:团队;index:team"` // 团队id - Method string `gorm:"size:36;not null;column:method;comment:请求方法" ` + Method []string `gorm:"size:36;not null;column:method;comment:请求方法;serializer:json" ` Path string `gorm:"size:512;not null;column:path;comment:请求路径"` Protocol []string `gorm:"type:text;null;column:protocol;comment:协议;serializer:json"` Match string `gorm:"type:text;null;column:match;comment:匹配规则"` @@ -42,10 +42,10 @@ func (i *Info) IdValue() int64 { return i.Id } -func (a *Api) IdValue() int64 { +func (a *API) IdValue() int64 { return a.Id } -func (a *Api) TableName() string { +func (a *API) TableName() string { return "api" } @@ -56,4 +56,13 @@ type Doc struct { Content string `gorm:"type:text;null;column:content;comment:文档内容"` Updater string `gorm:"size:36;not null;column:updater;comment:更新人;index:updater" aovalue:"updater"` UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:update_at;comment:更新时间"` + APICount int64 `gorm:"type:int(11);not null;column:api_count;comment:接口数量"` +} + +func (i *Doc) TableName() string { + return "api_doc" +} + +func (i *Doc) IdValue() int64 { + return i.Id }