mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
首次提交APIPark代码,面向开源
This commit is contained in:
@@ -0,0 +1,332 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
|
||||
"github.com/APIParkLab/APIPark/stores/api"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
"github.com/eolinker/go-common/auto"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
)
|
||||
|
||||
var (
|
||||
_ IAPIService = (*imlAPIService)(nil)
|
||||
)
|
||||
|
||||
type HistoryType string
|
||||
|
||||
const (
|
||||
HistoryDocument HistoryType = "doc"
|
||||
HistoryProxy HistoryType = "proxy"
|
||||
)
|
||||
|
||||
type imlAPIService struct {
|
||||
store api.IApiBaseStore `autowired:""`
|
||||
apiInfoStore api.IAPIInfoStore `autowired:""`
|
||||
proxyCommitService commit.ICommitWithKeyService[Proxy] `autowired:""`
|
||||
documentCommitService commit.ICommitWithKeyService[Document] `autowired:""`
|
||||
universally.IServiceGet[API]
|
||||
universally.IServiceDelete
|
||||
}
|
||||
|
||||
func (i *imlAPIService) CountMapByService(ctx context.Context, service ...string) (map[string]int64, error) {
|
||||
w := map[string]interface{}{}
|
||||
if len(service) > 0 {
|
||||
w["service"] = service
|
||||
}
|
||||
return i.store.CountByGroup(ctx, "", w, "service")
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListInfoForService(ctx context.Context, serviceId string) ([]*Info, error) {
|
||||
apis, err := i.store.List(ctx, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
})
|
||||
aids := utils.SliceToSlice(apis, func(a *api.Api) int64 {
|
||||
return a.Id
|
||||
})
|
||||
list, err := i.apiInfoStore.List(ctx, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
"id": aids,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(info *api.Info) *Info {
|
||||
return &Info{
|
||||
UUID: info.UUID,
|
||||
Name: info.Name,
|
||||
Description: info.Description,
|
||||
CreateAt: info.CreateAt,
|
||||
UpdateAt: info.UpdateAt,
|
||||
Service: info.Service,
|
||||
Team: info.Team,
|
||||
Creator: info.Creator,
|
||||
Updater: info.Updater,
|
||||
Method: info.Method,
|
||||
Path: info.Path,
|
||||
Match: info.Match,
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListInfo(ctx context.Context, aids ...string) ([]*Info, error) {
|
||||
list, err := i.apiInfoStore.List(ctx, map[string]interface{}{
|
||||
"uuid": aids,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(info *api.Info) *Info {
|
||||
return &Info{
|
||||
UUID: info.UUID,
|
||||
Name: info.Name,
|
||||
Description: info.Description,
|
||||
CreateAt: info.CreateAt,
|
||||
UpdateAt: info.UpdateAt,
|
||||
Service: info.Service,
|
||||
Team: info.Team,
|
||||
Creator: info.Creator,
|
||||
Updater: info.Updater,
|
||||
Method: info.Method,
|
||||
Path: info.Path,
|
||||
Match: info.Match,
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) GetInfo(ctx context.Context, aid string) (*Info, error) {
|
||||
|
||||
info, err := i.apiInfoStore.GetByUUID(ctx, aid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Info{
|
||||
UUID: info.UUID,
|
||||
Name: info.Name,
|
||||
Description: info.Description,
|
||||
CreateAt: info.CreateAt,
|
||||
UpdateAt: info.UpdateAt,
|
||||
Service: info.Service,
|
||||
Team: info.Team,
|
||||
Creator: info.Creator,
|
||||
Updater: info.Updater,
|
||||
Method: info.Method,
|
||||
Path: info.Path,
|
||||
Match: info.Match,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) error {
|
||||
if model == nil {
|
||||
return errors.New("input is nil")
|
||||
}
|
||||
return i.apiInfoStore.Transaction(ctx, func(ctx context.Context) error {
|
||||
ev, err := i.apiInfoStore.GetByUUID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if model.Name != nil {
|
||||
ev.Name = *model.Name
|
||||
}
|
||||
//if model.Upstream != nil {
|
||||
// ev.Upstream = *model.Upstream
|
||||
//}
|
||||
if model.Description != nil {
|
||||
ev.Description = *model.Description
|
||||
}
|
||||
e := i.apiInfoStore.Save(ctx, ev)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
return i.store.SetLabels(ctx, ev.Id, getLabels(ev)...)
|
||||
|
||||
})
|
||||
}
|
||||
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, appends...)
|
||||
return labels
|
||||
}
|
||||
func (i *imlAPIService) Create(ctx context.Context, input *CreateAPI) (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)
|
||||
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,
|
||||
UUID: input.UUID,
|
||||
Service: input.Service,
|
||||
Team: input.Team,
|
||||
Creator: operater,
|
||||
CreateAt: time.Now(),
|
||||
IsDelete: 0,
|
||||
Method: input.Method,
|
||||
Path: input.Path,
|
||||
}
|
||||
err = i.store.Insert(ctx, &ne)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ev := &api.Info{
|
||||
Id: ne.Id,
|
||||
UUID: ne.UUID,
|
||||
Name: input.Name,
|
||||
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,
|
||||
}
|
||||
err = i.apiInfoStore.Save(ctx, ev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = i.store.SetLabels(ctx, ne.Id, getLabels(ev)...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListProxyCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Proxy], error) {
|
||||
return i.proxyCommitService.List(ctx, commitId...)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListDocumentCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Document], error) {
|
||||
return i.documentCommitService.List(ctx, commitId...)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) CountByService(ctx context.Context, service string) (int64, error) {
|
||||
return i.store.CountWhere(ctx, map[string]interface{}{
|
||||
"service": service,
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if t.UUID != aid {
|
||||
return fmt.Errorf("method(%s),path(%s) is exist", a.Method, a.Path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListForService(ctx context.Context, serviceId string) ([]*API, error) {
|
||||
list, err := i.listForService(ctx, serviceId, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
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) {
|
||||
|
||||
return i.proxyCommitService.ListLatest(ctx, apiUUID...)
|
||||
|
||||
}
|
||||
func (i *imlAPIService) ListLatestCommitDocument(ctx context.Context, apiUUID ...string) ([]*commit.Commit[Document], error) {
|
||||
|
||||
return i.documentCommitService.ListLatest(ctx, apiUUID...)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) LatestProxy(ctx context.Context, aid string) (*commit.Commit[Proxy], error) {
|
||||
|
||||
return i.proxyCommitService.Latest(ctx, aid)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) LatestDocument(ctx context.Context, aid string) (*commit.Commit[Document], error) {
|
||||
|
||||
return i.documentCommitService.Latest(ctx, aid)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) GetProxyCommit(ctx context.Context, commitId string) (*commit.Commit[Proxy], error) {
|
||||
return i.proxyCommitService.Get(ctx, commitId)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) GetDocumentCommit(ctx context.Context, commitId string) (*commit.Commit[Document], error) {
|
||||
return i.documentCommitService.Get(ctx, commitId)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) SaveProxy(ctx context.Context, aid string, data *Proxy) error {
|
||||
|
||||
return i.proxyCommitService.Save(ctx, aid, data)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) SaveDocument(ctx context.Context, aid string, data *Document) error {
|
||||
|
||||
return i.documentCommitService.Save(ctx, aid, data)
|
||||
}
|
||||
|
||||
func (i *imlAPIService) GetLabels(ctx context.Context, ids ...string) map[string]string {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
list, err := i.apiInfoStore.ListQuery(ctx, "`uuid` in (?)", []interface{}{ids}, "id")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return utils.SliceToMapO(list, func(i *api.Info) (string, string) {
|
||||
return i.UUID, i.Name
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIService) OnComplete() {
|
||||
i.IServiceGet = universally.NewGetSoftDelete[API, api.Api](i.store, FromEntity)
|
||||
|
||||
i.IServiceDelete = universally.NewSoftDelete[api.Api](i.store)
|
||||
|
||||
auto.RegisterService("api", i)
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/model/plugin_model"
|
||||
|
||||
"github.com/APIParkLab/APIPark/stores/api"
|
||||
)
|
||||
|
||||
type API struct {
|
||||
UUID string
|
||||
Service string
|
||||
Team string
|
||||
Creator string
|
||||
Method string
|
||||
Path string
|
||||
CreateAt time.Time
|
||||
IsDelete bool
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
UUID string
|
||||
Name string
|
||||
Description string
|
||||
CreateAt time.Time
|
||||
UpdateAt time.Time
|
||||
Service string
|
||||
Team string
|
||||
Creator string
|
||||
Updater string
|
||||
Upstream string
|
||||
Method string
|
||||
Path string
|
||||
Match string
|
||||
}
|
||||
|
||||
func FromEntity(e *api.Api) *API {
|
||||
return &API{
|
||||
UUID: e.UUID,
|
||||
CreateAt: e.CreateAt,
|
||||
IsDelete: e.IsDelete != 0,
|
||||
Service: e.Service,
|
||||
Team: e.Team,
|
||||
Creator: e.Creator,
|
||||
Method: e.Method,
|
||||
Path: e.Path,
|
||||
}
|
||||
}
|
||||
|
||||
type CreateAPI struct {
|
||||
UUID string
|
||||
Name string
|
||||
Description string
|
||||
Service string
|
||||
Team string
|
||||
Method string
|
||||
Path string
|
||||
Match string
|
||||
}
|
||||
|
||||
type EditAPI struct {
|
||||
Name *string
|
||||
Upstream *string
|
||||
Description *string
|
||||
}
|
||||
|
||||
type ExistAPI struct {
|
||||
Path string
|
||||
Method string
|
||||
}
|
||||
|
||||
type Document struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
type PluginSetting struct {
|
||||
Disable bool `json:"disable"`
|
||||
Config plugin_model.ConfigType `json:"config"`
|
||||
}
|
||||
type Proxy struct {
|
||||
Path string `json:"path"`
|
||||
Timeout int `json:"timeout"`
|
||||
Retry int `json:"retry"`
|
||||
Plugins map[string]PluginSetting `json:"plugins"`
|
||||
Extends map[string]any `json:"extends"`
|
||||
Headers []*Header `json:"headers"`
|
||||
}
|
||||
|
||||
type Header struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Opt string `json:"opt"`
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
MatchRules []*Match `json:"match"`
|
||||
}
|
||||
|
||||
type Match struct {
|
||||
Position string `json:"position"`
|
||||
MatchType string `json:"match_type"`
|
||||
Key string `json:"key"`
|
||||
Pattern string `json:"pattern"`
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
)
|
||||
|
||||
type IAPIService interface {
|
||||
universally.IServiceGet[API]
|
||||
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
|
||||
ListForService(ctx context.Context, serviceId string) ([]*API, error)
|
||||
GetInfo(ctx context.Context, aid string) (*Info, error)
|
||||
ListInfo(ctx context.Context, aids ...string) ([]*Info, error)
|
||||
ListInfoForService(ctx context.Context, serviceId string) ([]*Info, error)
|
||||
ListLatestCommitProxy(ctx context.Context, aid ...string) ([]*commit.Commit[Proxy], error)
|
||||
ListLatestCommitDocument(ctx context.Context, aid ...string) ([]*commit.Commit[Document], error)
|
||||
LatestProxy(ctx context.Context, aid string) (*commit.Commit[Proxy], error)
|
||||
LatestDocument(ctx context.Context, aid string) (*commit.Commit[Document], error)
|
||||
GetProxyCommit(ctx context.Context, commitId string) (*commit.Commit[Proxy], error)
|
||||
ListProxyCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Proxy], error)
|
||||
GetDocumentCommit(ctx context.Context, commitId string) (*commit.Commit[Document], error)
|
||||
ListDocumentCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Document], error)
|
||||
SaveProxy(ctx context.Context, aid string, data *Proxy) error
|
||||
SaveDocument(ctx context.Context, aid string, data *Document) error
|
||||
Save(ctx context.Context, id string, model *EditAPI) error
|
||||
Create(ctx context.Context, input *CreateAPI) (err error)
|
||||
}
|
||||
|
||||
var (
|
||||
_ IAPIService = (*imlAPIService)(nil)
|
||||
)
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IAPIService](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlAPIService))
|
||||
})
|
||||
|
||||
commit.InitCommitWithKeyService[Proxy]("api", string(HistoryProxy))
|
||||
commit.InitCommitWithKeyService[Document]("api", string(HistoryDocument))
|
||||
}
|
||||
Reference in New Issue
Block a user