| @@ -12,6 +12,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types" | ||||
| v1 "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/v1" | v1 "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/v1" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/services" | "gitlink.org.cn/cloudream/jcs-pub/client/internal/services" | ||||
| "golang.org/x/net/http2" | |||||
| ) | ) | ||||
| type ServerEventChan = async.UnboundChannel[ServerEvent] | type ServerEventChan = async.UnboundChannel[ServerEvent] | ||||
| @@ -58,6 +59,7 @@ func (s *Server) Start() *ServerEventChan { | |||||
| s.httpSrv.TLSConfig = &tls.Config{ | s.httpSrv.TLSConfig = &tls.Config{ | ||||
| GetConfigForClient: s.auth.TLSConfigSelector, | GetConfigForClient: s.auth.TLSConfigSelector, | ||||
| } | } | ||||
| http2.ConfigureServer(s.httpSrv, &http2.Server{}) | |||||
| s.v1Svr.InitRouters(engine.Group("/v1"), s.auth) | s.v1Svr.InitRouters(engine.Group("/v1"), s.auth) | ||||
| @@ -1,7 +1,12 @@ | |||||
| package api | package api | ||||
| import ( | |||||
| "crypto/tls" | |||||
| "crypto/x509" | |||||
| ) | |||||
| type Config struct { | type Config struct { | ||||
| URL string `json:"url"` | |||||
| AccessKey string `json:"accessKey"` | |||||
| SecretKey string `json:"secretKey"` | |||||
| EndPoint string | |||||
| RootCA *x509.CertPool | |||||
| Cert tls.Certificate | |||||
| } | } | ||||
| @@ -34,7 +34,7 @@ func (r *BucketGetByNameResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *BucketService) GetByName(req BucketGetByName) (*BucketGetByNameResp, error) { | func (c *BucketService) GetByName(req BucketGetByName) (*BucketGetByNameResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &BucketGetByNameResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &BucketGetByNameResp{}) | |||||
| } | } | ||||
| const BucketCreatePath = "/bucket/create" | const BucketCreatePath = "/bucket/create" | ||||
| @@ -56,7 +56,7 @@ func (r *BucketCreateResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *BucketService) Create(req BucketCreate) (*BucketCreateResp, error) { | func (c *BucketService) Create(req BucketCreate) (*BucketCreateResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &BucketCreateResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &BucketCreateResp{}) | |||||
| } | } | ||||
| const BucketDeletePath = "/bucket/delete" | const BucketDeletePath = "/bucket/delete" | ||||
| @@ -76,7 +76,7 @@ func (r *BucketDeleteResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *BucketService) Delete(req BucketDelete) error { | func (c *BucketService) Delete(req BucketDelete) error { | ||||
| return JSONAPINoData(c.cfg, http.DefaultClient, &req) | |||||
| return JSONAPINoData(&c.cfg, c.httpCli, &req) | |||||
| } | } | ||||
| const BucketListAllPath = "/bucket/listAll" | const BucketListAllPath = "/bucket/listAll" | ||||
| @@ -97,5 +97,5 @@ func (r *BucketListAllResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *BucketService) ListAll(req BucketListAll) (*BucketListAllResp, error) { | func (c *BucketService) ListAll(req BucketListAll) (*BucketListAllResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &BucketListAllResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &BucketListAllResp{}) | |||||
| } | } | ||||
| @@ -26,6 +26,6 @@ func (r *CacheMovePackageResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) CacheMovePackage(req CacheMovePackageReq) (*CacheMovePackageResp, error) { | func (c *Client) CacheMovePackage(req CacheMovePackageReq) (*CacheMovePackageResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &CacheMovePackageResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &CacheMovePackageResp{}) | |||||
| } | } | ||||
| */ | */ | ||||
| @@ -1,8 +1,13 @@ | |||||
| package api | package api | ||||
| import ( | import ( | ||||
| "crypto/tls" | |||||
| "net/http" | |||||
| "gitlink.org.cn/cloudream/common/sdks" | "gitlink.org.cn/cloudream/common/sdks" | ||||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/auth" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api" | "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api" | ||||
| "golang.org/x/net/http2" | |||||
| ) | ) | ||||
| type response[T any] struct { | type response[T any] struct { | ||||
| @@ -19,34 +24,23 @@ func (r *response[T]) ToError() *sdks.CodeMessageError { | |||||
| } | } | ||||
| type Client struct { | type Client struct { | ||||
| cfg *api.Config | |||||
| } | |||||
| func NewClient(cfg *api.Config) *Client { | |||||
| return &Client{ | |||||
| cfg: cfg, | |||||
| cfg api.Config | |||||
| httpCli *http.Client | |||||
| } | |||||
| func NewClient(cfg api.Config) *Client { | |||||
| httpCli := &http.Client{ | |||||
| Transport: &http2.Transport{ | |||||
| TLSClientConfig: &tls.Config{ | |||||
| RootCAs: cfg.RootCA, | |||||
| Certificates: []tls.Certificate{cfg.Cert}, | |||||
| ServerName: auth.ClientInternalSNI, | |||||
| NextProtos: []string{"h2"}, | |||||
| }, | |||||
| }, | |||||
| } | } | ||||
| } | |||||
| type Pool interface { | |||||
| Acquire() (*Client, error) | |||||
| Release(cli *Client) | |||||
| } | |||||
| type pool struct { | |||||
| cfg *api.Config | |||||
| } | |||||
| func NewPool(cfg *api.Config) Pool { | |||||
| return &pool{ | |||||
| cfg: cfg, | |||||
| return &Client{ | |||||
| cfg: cfg, | |||||
| httpCli: httpCli, | |||||
| } | } | ||||
| } | } | ||||
| func (p *pool) Acquire() (*Client, error) { | |||||
| cli := NewClient(p.cfg) | |||||
| return cli, nil | |||||
| } | |||||
| func (p *pool) Release(cli *Client) { | |||||
| } | |||||
| @@ -34,7 +34,7 @@ func (r *MountDumpStatusResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *MountService) DumpStatus(req MountDumpStatus) (*MountDumpStatusResp, error) { | func (c *MountService) DumpStatus(req MountDumpStatus) (*MountDumpStatusResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &MountDumpStatusResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &MountDumpStatusResp{}) | |||||
| } | } | ||||
| const MountStartReclaimSpacePath = "/mount/startReclaimSpace" | const MountStartReclaimSpacePath = "/mount/startReclaimSpace" | ||||
| @@ -52,5 +52,5 @@ func (r *StartMountReclaimSpaceResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *MountService) StartReclaimSpace(req StartMountReclaimSpace) (*StartMountReclaimSpaceResp, error) { | func (c *MountService) StartReclaimSpace(req StartMountReclaimSpace) (*StartMountReclaimSpaceResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &StartMountReclaimSpaceResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &StartMountReclaimSpaceResp{}) | |||||
| } | } | ||||
| @@ -1,7 +1,6 @@ | |||||
| package api | package api | ||||
| import ( | import ( | ||||
| "context" | |||||
| "fmt" | "fmt" | ||||
| "io" | "io" | ||||
| "mime" | "mime" | ||||
| @@ -10,8 +9,6 @@ import ( | |||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | |||||
| "github.com/aws/aws-sdk-go-v2/credentials" | |||||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | "gitlink.org.cn/cloudream/common/consts/errorcode" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/iterator" | "gitlink.org.cn/cloudream/common/pkgs/iterator" | ||||
| "gitlink.org.cn/cloudream/common/sdks" | "gitlink.org.cn/cloudream/common/sdks" | ||||
| @@ -57,7 +54,7 @@ func (r *ObjectListByPathResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) ListByPath(req ObjectListByPath) (*ObjectListByPathResp, error) { | func (c *ObjectService) ListByPath(req ObjectListByPath) (*ObjectListByPathResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectListByPathResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectListByPathResp{}) | |||||
| } | } | ||||
| const ObjectListByIDsPath = "/object/listByIDs" | const ObjectListByIDsPath = "/object/listByIDs" | ||||
| @@ -79,7 +76,7 @@ func (r *ObjectListByIDsResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) ListByIDs(req ObjectListByIDs) (*ObjectListByIDsResp, error) { | func (c *ObjectService) ListByIDs(req ObjectListByIDs) (*ObjectListByIDsResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectListByIDsResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectListByIDsResp{}) | |||||
| } | } | ||||
| const ObjectUploadPath = "/object/upload" | const ObjectUploadPath = "/object/upload" | ||||
| @@ -112,7 +109,7 @@ func (c *ObjectService) Upload(req ObjectUpload) (*ObjectUploadResp, error) { | |||||
| Info string `url:"info"` | Info string `url:"info"` | ||||
| } | } | ||||
| url, err := url.JoinPath(c.cfg.URL, ObjectUploadPath) | |||||
| url, err := url.JoinPath(c.cfg.EndPoint, "v1", ObjectUploadPath) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -122,7 +119,7 @@ func (c *ObjectService) Upload(req ObjectUpload) (*ObjectUploadResp, error) { | |||||
| return nil, fmt.Errorf("upload info to json: %w", err) | return nil, fmt.Errorf("upload info to json: %w", err) | ||||
| } | } | ||||
| resp, err := PostMultiPart(c.cfg, url, | |||||
| resp, err := PostMultiPart(&c.cfg, url, | |||||
| uploadInfo{Info: string(infoJSON)}, | uploadInfo{Info: string(infoJSON)}, | ||||
| iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) { | iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) { | ||||
| return &http2.IterMultiPartFile{ | return &http2.IterMultiPartFile{ | ||||
| @@ -172,26 +169,12 @@ type DownloadingObject struct { | |||||
| } | } | ||||
| func (c *ObjectService) Download(req ObjectDownload) (*DownloadingObject, error) { | func (c *ObjectService) Download(req ObjectDownload) (*DownloadingObject, error) { | ||||
| httpReq, err := req.MakeParam().MakeRequest(c.cfg.URL) | |||||
| httpReq, err := req.MakeParam().MakeRequest(c.cfg.EndPoint) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| if c.cfg.AccessKey != "" && c.cfg.SecretKey != "" { | |||||
| prod := credentials.NewStaticCredentialsProvider(c.cfg.AccessKey, c.cfg.SecretKey, "") | |||||
| cred, err := prod.Retrieve(context.TODO()) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| signer := v4.NewSigner() | |||||
| err = signer.SignHTTP(context.Background(), cred, httpReq, "", AuthService, AuthRegion, time.Now()) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| } | |||||
| resp, err := http.DefaultClient.Do(httpReq) | |||||
| resp, err := c.httpCli.Do(httpReq) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -232,26 +215,12 @@ func (r *ObjectDownloadByPath) MakeParam() *sdks.RequestParam { | |||||
| } | } | ||||
| func (c *ObjectService) DownloadByPath(req ObjectDownloadByPath) (*DownloadingObject, error) { | func (c *ObjectService) DownloadByPath(req ObjectDownloadByPath) (*DownloadingObject, error) { | ||||
| httpReq, err := req.MakeParam().MakeRequest(c.cfg.URL) | |||||
| httpReq, err := req.MakeParam().MakeRequest(c.cfg.EndPoint) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| if c.cfg.AccessKey != "" && c.cfg.SecretKey != "" { | |||||
| prod := credentials.NewStaticCredentialsProvider(c.cfg.AccessKey, c.cfg.SecretKey, "") | |||||
| cred, err := prod.Retrieve(context.TODO()) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| signer := v4.NewSigner() | |||||
| err = signer.SignHTTP(context.Background(), cred, httpReq, "", AuthService, AuthRegion, time.Now()) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| } | |||||
| resp, err := http.DefaultClient.Do(httpReq) | |||||
| resp, err := c.httpCli.Do(httpReq) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -306,7 +275,7 @@ func (r *ObjectUpdateInfoResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) UpdateInfo(req ObjectUpdateInfo) (*ObjectUpdateInfoResp, error) { | func (c *ObjectService) UpdateInfo(req ObjectUpdateInfo) (*ObjectUpdateInfoResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectUpdateInfoResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectUpdateInfoResp{}) | |||||
| } | } | ||||
| const ObjectUpdateInfoByPathPath = "/object/updateInfoByPath" | const ObjectUpdateInfoByPathPath = "/object/updateInfoByPath" | ||||
| @@ -328,7 +297,7 @@ func (r *ObjectUpdateInfoByPathResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) UpdateInfoByPath(req ObjectUpdateInfoByPath) (*ObjectUpdateInfoByPathResp, error) { | func (c *ObjectService) UpdateInfoByPath(req ObjectUpdateInfoByPath) (*ObjectUpdateInfoByPathResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectUpdateInfoByPathResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectUpdateInfoByPathResp{}) | |||||
| } | } | ||||
| const ObjectMovePath = "/object/move" | const ObjectMovePath = "/object/move" | ||||
| @@ -361,7 +330,7 @@ func (r *ObjectMoveResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) Move(req ObjectMove) (*ObjectMoveResp, error) { | func (c *ObjectService) Move(req ObjectMove) (*ObjectMoveResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectMoveResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectMoveResp{}) | |||||
| } | } | ||||
| const ObjectDeletePath = "/object/delete" | const ObjectDeletePath = "/object/delete" | ||||
| @@ -381,7 +350,7 @@ func (r *ObjectDeleteResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) Delete(req ObjectDelete) error { | func (c *ObjectService) Delete(req ObjectDelete) error { | ||||
| return JSONAPINoData(c.cfg, http.DefaultClient, &req) | |||||
| return JSONAPINoData(&c.cfg, c.httpCli, &req) | |||||
| } | } | ||||
| const ObjectDeleteByPathPath = "/object/deleteByPath" | const ObjectDeleteByPathPath = "/object/deleteByPath" | ||||
| @@ -402,7 +371,7 @@ func (r *ObjectDeleteByPathResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) DeleteByPath(req ObjectDeleteByPath) error { | func (c *ObjectService) DeleteByPath(req ObjectDeleteByPath) error { | ||||
| return JSONAPINoData(c.cfg, http.DefaultClient, &req) | |||||
| return JSONAPINoData(&c.cfg, c.httpCli, &req) | |||||
| } | } | ||||
| const ObjectClonePath = "/object/clone" | const ObjectClonePath = "/object/clone" | ||||
| @@ -430,7 +399,7 @@ func (r *ObjectCloneResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) Clone(req ObjectClone) (*ObjectCloneResp, error) { | func (c *ObjectService) Clone(req ObjectClone) (*ObjectCloneResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectCloneResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectCloneResp{}) | |||||
| } | } | ||||
| const ObjectGetPackageObjectsPath = "/object/getPackageObjects" | const ObjectGetPackageObjectsPath = "/object/getPackageObjects" | ||||
| @@ -452,7 +421,7 @@ func (r *ObjectGetPackageObjectsResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *ObjectService) GetPackageObjects(req ObjectGetPackageObjects) (*ObjectGetPackageObjectsResp, error) { | func (c *ObjectService) GetPackageObjects(req ObjectGetPackageObjects) (*ObjectGetPackageObjectsResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectGetPackageObjectsResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectGetPackageObjectsResp{}) | |||||
| } | } | ||||
| const ObjectNewMultipartUploadPath = "/object/newMultipartUpload" | const ObjectNewMultipartUploadPath = "/object/newMultipartUpload" | ||||
| @@ -475,7 +444,7 @@ func (r *ObjectNewMultipartUploadResp) ParseResponse(resp *http.Response) error | |||||
| } | } | ||||
| func (c *ObjectService) NewMultipartUpload(req ObjectNewMultipartUpload) (*ObjectNewMultipartUploadResp, error) { | func (c *ObjectService) NewMultipartUpload(req ObjectNewMultipartUpload) (*ObjectNewMultipartUploadResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectNewMultipartUploadResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectNewMultipartUploadResp{}) | |||||
| } | } | ||||
| const ObjectUploadPartPath = "/object/uploadPart" | const ObjectUploadPartPath = "/object/uploadPart" | ||||
| @@ -493,7 +462,7 @@ type ObjectUploadPartInfo struct { | |||||
| type ObjectUploadPartResp struct{} | type ObjectUploadPartResp struct{} | ||||
| func (c *ObjectService) UploadPart(req ObjectUploadPart) (*ObjectUploadPartResp, error) { | func (c *ObjectService) UploadPart(req ObjectUploadPart) (*ObjectUploadPartResp, error) { | ||||
| url, err := url.JoinPath(c.cfg.URL, ObjectUploadPartPath) | |||||
| url, err := url.JoinPath(c.cfg.EndPoint, ObjectUploadPartPath) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -552,5 +521,5 @@ func (r *ObjectCompleteMultipartUploadResp) ParseResponse(resp *http.Response) e | |||||
| } | } | ||||
| func (c *ObjectService) CompleteMultipartUpload(req ObjectCompleteMultipartUpload) (*ObjectCompleteMultipartUploadResp, error) { | func (c *ObjectService) CompleteMultipartUpload(req ObjectCompleteMultipartUpload) (*ObjectCompleteMultipartUploadResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &ObjectCompleteMultipartUploadResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &ObjectCompleteMultipartUploadResp{}) | |||||
| } | } | ||||
| @@ -40,7 +40,7 @@ func (r *PackageGetResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *PackageService) Get(req PackageGetReq) (*PackageGetResp, error) { | func (c *PackageService) Get(req PackageGetReq) (*PackageGetResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &PackageGetResp{}) | |||||
| } | } | ||||
| const PackageGetByFullNamePath = "/package/getByFullName" | const PackageGetByFullNamePath = "/package/getByFullName" | ||||
| @@ -63,7 +63,7 @@ func (r *PackageGetByFullNameResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *PackageService) GetByName(req PackageGetByFullName) (*PackageGetByFullNameResp, error) { | func (c *PackageService) GetByName(req PackageGetByFullName) (*PackageGetByFullNameResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetByFullNameResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &PackageGetByFullNameResp{}) | |||||
| } | } | ||||
| const PackageCreatePath = "/package/create" | const PackageCreatePath = "/package/create" | ||||
| @@ -86,7 +86,7 @@ func (r *PackageCreateResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (s *PackageService) Create(req PackageCreate) (*PackageCreateResp, error) { | func (s *PackageService) Create(req PackageCreate) (*PackageCreateResp, error) { | ||||
| return JSONAPI(s.cfg, http.DefaultClient, &req, &PackageCreateResp{}) | |||||
| return JSONAPI(&s.cfg, s.httpCli, &req, &PackageCreateResp{}) | |||||
| } | } | ||||
| const PackageCreateUploadPath = "/package/createUpload" | const PackageCreateUploadPath = "/package/createUpload" | ||||
| @@ -107,7 +107,7 @@ type PackageCreateUploadResp struct { | |||||
| } | } | ||||
| func (c *PackageService) CreateUpload(req PackageCreateUpload) (*PackageCreateUploadResp, error) { | func (c *PackageService) CreateUpload(req PackageCreateUpload) (*PackageCreateUploadResp, error) { | ||||
| url, err := url.JoinPath(c.cfg.URL, PackageCreateUploadPath) | |||||
| url, err := url.JoinPath(c.cfg.EndPoint, "v1", PackageCreateUploadPath) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -117,7 +117,7 @@ func (c *PackageService) CreateUpload(req PackageCreateUpload) (*PackageCreateUp | |||||
| return nil, fmt.Errorf("upload info to json: %w", err) | return nil, fmt.Errorf("upload info to json: %w", err) | ||||
| } | } | ||||
| resp, err := PostMultiPart(c.cfg, url, | |||||
| resp, err := PostMultiPart(&c.cfg, url, | |||||
| map[string]string{"info": string(infoJSON)}, | map[string]string{"info": string(infoJSON)}, | ||||
| iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) { | iterator.Map(req.Files, func(src *UploadingObject) (*http2.IterMultiPartFile, error) { | ||||
| return &http2.IterMultiPartFile{ | return &http2.IterMultiPartFile{ | ||||
| @@ -159,7 +159,7 @@ func (r *PackageDeleteResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *PackageService) Delete(req PackageDelete) error { | func (c *PackageService) Delete(req PackageDelete) error { | ||||
| return JSONAPINoData(c.cfg, http.DefaultClient, &req) | |||||
| return JSONAPINoData(&c.cfg, c.httpCli, &req) | |||||
| } | } | ||||
| const PackageClonePath = "/package/clone" | const PackageClonePath = "/package/clone" | ||||
| @@ -183,7 +183,7 @@ func (r *PackageCloneResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *PackageService) Clone(req PackageClone) (*PackageCloneResp, error) { | func (c *PackageService) Clone(req PackageClone) (*PackageCloneResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageCloneResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &PackageCloneResp{}) | |||||
| } | } | ||||
| const PackageListBucketPackagesPath = "/package/listBucketPackages" | const PackageListBucketPackagesPath = "/package/listBucketPackages" | ||||
| @@ -205,7 +205,7 @@ func (r *PackageListBucketPackagesResp) ParseResponse(resp *http.Response) error | |||||
| } | } | ||||
| func (c *PackageService) ListBucketPackages(req PackageListBucketPackages) (*PackageListBucketPackagesResp, error) { | func (c *PackageService) ListBucketPackages(req PackageListBucketPackages) (*PackageListBucketPackagesResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageListBucketPackagesResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &PackageListBucketPackagesResp{}) | |||||
| } | } | ||||
| const PackageGetCachedStoragesPath = "/package/getCachedStorages" | const PackageGetCachedStoragesPath = "/package/getCachedStorages" | ||||
| @@ -228,6 +228,6 @@ func (r *PackageGetCachedStoragesResp) ParseResponse(resp *http.Response) error | |||||
| } | } | ||||
| func (c *PackageService) GetCachedStorages(req PackageGetCachedStoragesReq) (*PackageGetCachedStoragesResp, error) { | func (c *PackageService) GetCachedStorages(req PackageGetCachedStoragesReq) (*PackageGetCachedStoragesResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &PackageGetCachedStoragesResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &PackageGetCachedStoragesResp{}) | |||||
| } | } | ||||
| */ | */ | ||||
| @@ -1,15 +1,8 @@ | |||||
| package api | package api | ||||
| import ( | import ( | ||||
| "context" | |||||
| "fmt" | |||||
| "net/http" | "net/http" | ||||
| "net/url" | |||||
| "time" | |||||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | |||||
| "github.com/aws/aws-sdk-go-v2/credentials" | |||||
| "github.com/google/go-querystring/query" | |||||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | ||||
| ) | ) | ||||
| @@ -120,32 +113,33 @@ func (c *PresignedService) ObjectCompleteMultipartUpload(req PresignedObjectComp | |||||
| } | } | ||||
| func (c *PresignedService) presign(req any, path string, method string, expireIn int) (string, error) { | func (c *PresignedService) presign(req any, path string, method string, expireIn int) (string, error) { | ||||
| u, err := url.Parse(c.cfg.URL) | |||||
| if err != nil { | |||||
| return "", err | |||||
| } | |||||
| u = u.JoinPath(path) | |||||
| us, err := query.Values(req) | |||||
| if err != nil { | |||||
| return "", err | |||||
| } | |||||
| us.Add("X-Expires", fmt.Sprintf("%v", expireIn)) | |||||
| u.RawQuery = us.Encode() | |||||
| prod := credentials.NewStaticCredentialsProvider(c.cfg.AccessKey, c.cfg.SecretKey, "") | |||||
| cred, err := prod.Retrieve(context.TODO()) | |||||
| if err != nil { | |||||
| return "", err | |||||
| } | |||||
| r, err := http.NewRequest(method, u.String(), nil) | |||||
| if err != nil { | |||||
| return "", err | |||||
| } | |||||
| signer := v4.NewSigner() | |||||
| signedURL, _, err := signer.PresignHTTP(context.Background(), cred, r, "", AuthService, AuthRegion, time.Now()) | |||||
| return signedURL, err | |||||
| // u, err := url.Parse(c.cfg.EndPoint) | |||||
| // if err != nil { | |||||
| // return "", err | |||||
| // } | |||||
| // u = u.JoinPath(path) | |||||
| // us, err := query.Values(req) | |||||
| // if err != nil { | |||||
| // return "", err | |||||
| // } | |||||
| // us.Add("X-Expires", fmt.Sprintf("%v", expireIn)) | |||||
| // u.RawQuery = us.Encode() | |||||
| // prod := credentials.NewStaticCredentialsProvider(c.cfg.AccessKey, c.cfg.SecretKey, "") | |||||
| // cred, err := prod.Retrieve(context.TODO()) | |||||
| // if err != nil { | |||||
| // return "", err | |||||
| // } | |||||
| // r, err := http.NewRequest(method, u.String(), nil) | |||||
| // if err != nil { | |||||
| // return "", err | |||||
| // } | |||||
| // signer := v4.NewSigner() | |||||
| // signedURL, _, err := signer.PresignHTTP(context.Background(), cred, r, "", AuthService, AuthRegion, time.Now()) | |||||
| // return signedURL, err | |||||
| return "", nil | |||||
| } | } | ||||
| @@ -9,10 +9,8 @@ import ( | |||||
| ) | ) | ||||
| func Test_Presigned(t *testing.T) { | func Test_Presigned(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("下载文件", t, func() { | Convey("下载文件", t, func() { | ||||
| @@ -39,10 +37,8 @@ func Test_Presigned(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedObjectListByPath(t *testing.T) { | func Test_PresignedObjectListByPath(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("下载文件", t, func() { | Convey("下载文件", t, func() { | ||||
| @@ -63,10 +59,8 @@ func Test_PresignedObjectListByPath(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedObjectDownloadByPath(t *testing.T) { | func Test_PresignedObjectDownloadByPath(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("下载文件", t, func() { | Convey("下载文件", t, func() { | ||||
| @@ -83,10 +77,8 @@ func Test_PresignedObjectDownloadByPath(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedObjectDownload(t *testing.T) { | func Test_PresignedObjectDownload(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("下载文件", t, func() { | Convey("下载文件", t, func() { | ||||
| @@ -102,8 +94,8 @@ func Test_PresignedObjectDownload(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedObjectUpload(t *testing.T) { | func Test_PresignedObjectUpload(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("上传文件", t, func() { | Convey("上传文件", t, func() { | ||||
| @@ -118,8 +110,8 @@ func Test_PresignedObjectUpload(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedNewMultipartUpload(t *testing.T) { | func Test_PresignedNewMultipartUpload(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("启动分片上传", t, func() { | Convey("启动分片上传", t, func() { | ||||
| @@ -134,10 +126,8 @@ func Test_PresignedNewMultipartUpload(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedObjectUploadPart(t *testing.T) { | func Test_PresignedObjectUploadPart(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("上传分片", t, func() { | Convey("上传分片", t, func() { | ||||
| @@ -152,10 +142,8 @@ func Test_PresignedObjectUploadPart(t *testing.T) { | |||||
| } | } | ||||
| func Test_PresignedCompleteMultipartUpload(t *testing.T) { | func Test_PresignedCompleteMultipartUpload(t *testing.T) { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| Convey("合并分片", t, func() { | Convey("合并分片", t, func() { | ||||
| @@ -15,8 +15,8 @@ import ( | |||||
| func Test_PackageGet(t *testing.T) { | func Test_PackageGet(t *testing.T) { | ||||
| Convey("上传后获取Package信息", t, func() { | Convey("上传后获取Package信息", t, func() { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| fileData := make([]byte, 4096) | fileData := make([]byte, 4096) | ||||
| @@ -65,8 +65,8 @@ func Test_PackageGet(t *testing.T) { | |||||
| func Test_Object(t *testing.T) { | func Test_Object(t *testing.T) { | ||||
| Convey("上传,下载,删除", t, func() { | Convey("上传,下载,删除", t, func() { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| fileData := make([]byte, 4096) | fileData := make([]byte, 4096) | ||||
| @@ -120,8 +120,8 @@ func Test_Object(t *testing.T) { | |||||
| func Test_ObjectList(t *testing.T) { | func Test_ObjectList(t *testing.T) { | ||||
| Convey("路径查询", t, func() { | Convey("路径查询", t, func() { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| resp, err := cli.Object().ListByPath(ObjectListByPath{ | resp, err := cli.Object().ListByPath(ObjectListByPath{ | ||||
| @@ -136,8 +136,8 @@ func Test_ObjectList(t *testing.T) { | |||||
| func Test_Storage(t *testing.T) { | func Test_Storage(t *testing.T) { | ||||
| Convey("上传后调度文件", t, func() { | Convey("上传后调度文件", t, func() { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890", | |||||
| }) | }) | ||||
| fileData := make([]byte, 4096) | fileData := make([]byte, 4096) | ||||
| @@ -233,10 +233,8 @@ func Test_Storage(t *testing.T) { | |||||
| */ | */ | ||||
| func Test_Sign(t *testing.T) { | func Test_Sign(t *testing.T) { | ||||
| Convey("签名接口", t, func() { | Convey("签名接口", t, func() { | ||||
| cli := NewClient(&api.Config{ | |||||
| URL: "http://localhost:7890/v1", | |||||
| AccessKey: "123456", | |||||
| SecretKey: "123456", | |||||
| cli := NewClient(api.Config{ | |||||
| EndPoint: "http://localhost:7890/v1", | |||||
| }) | }) | ||||
| fileData := make([]byte, 4096) | fileData := make([]byte, 4096) | ||||
| @@ -27,7 +27,7 @@ func (r *UserSpaceDownloadPackageResp) ParseResponse(resp *http.Response) error | |||||
| } | } | ||||
| func (c *Client) UserSpaceDownloadPackage(req UserSpaceDownloadPackageReq) (*UserSpaceDownloadPackageResp, error) { | func (c *Client) UserSpaceDownloadPackage(req UserSpaceDownloadPackageReq) (*UserSpaceDownloadPackageResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceDownloadPackageResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceDownloadPackageResp{}) | |||||
| } | } | ||||
| const UserSpaceCreatePackagePath = "/userspace/createPackage" | const UserSpaceCreatePackagePath = "/userspace/createPackage" | ||||
| @@ -53,7 +53,7 @@ func (r *UserSpaceCreatePackageResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceCreatePackage(req UserSpaceCreatePackageReq) (*UserSpaceCreatePackageResp, error) { | func (c *Client) UserSpaceCreatePackage(req UserSpaceCreatePackageReq) (*UserSpaceCreatePackageResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceCreatePackageResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceCreatePackageResp{}) | |||||
| } | } | ||||
| const UserSpaceGetPath = "/userspace/get" | const UserSpaceGetPath = "/userspace/get" | ||||
| @@ -75,7 +75,7 @@ func (r *UserSpaceGetResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceGet(req UserSpaceGet) (*UserSpaceGetResp, error) { | func (c *Client) UserSpaceGet(req UserSpaceGet) (*UserSpaceGetResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceGetResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceGetResp{}) | |||||
| } | } | ||||
| // 创建用户空间 | // 创建用户空间 | ||||
| @@ -103,7 +103,7 @@ func (r *UserSpaceCreateResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceCreate(req UserSpaceCreate) (*UserSpaceCreateResp, error) { | func (c *Client) UserSpaceCreate(req UserSpaceCreate) (*UserSpaceCreateResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceCreateResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceCreateResp{}) | |||||
| } | } | ||||
| // 更新用户空间。一些重要的配置不可再二次修改 | // 更新用户空间。一些重要的配置不可再二次修改 | ||||
| @@ -129,7 +129,7 @@ func (r *UserSpaceUpdateResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceUpdate(req UserSpaceUpdate) (*UserSpaceUpdateResp, error) { | func (c *Client) UserSpaceUpdate(req UserSpaceUpdate) (*UserSpaceUpdateResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceUpdateResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceUpdateResp{}) | |||||
| } | } | ||||
| // 删除用户空间 | // 删除用户空间 | ||||
| @@ -150,7 +150,7 @@ func (r *UserSpaceDeleteResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceDelete(req UserSpaceDelete) (*UserSpaceDeleteResp, error) { | func (c *Client) UserSpaceDelete(req UserSpaceDelete) (*UserSpaceDeleteResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceDeleteResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceDeleteResp{}) | |||||
| } | } | ||||
| // 测试给定用户空间的配置是否有效 | // 测试给定用户空间的配置是否有效 | ||||
| @@ -175,7 +175,7 @@ func (r *UserSpaceTestResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceTest(req UserSpaceTest) (*UserSpaceTestResp, error) { | func (c *Client) UserSpaceTest(req UserSpaceTest) (*UserSpaceTestResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceTestResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceTestResp{}) | |||||
| } | } | ||||
| // 存储服务间直传 | // 存储服务间直传 | ||||
| @@ -201,5 +201,5 @@ func (r *UserSpaceSpaceToSpaceResp) ParseResponse(resp *http.Response) error { | |||||
| } | } | ||||
| func (c *Client) UserSpaceSpaceToSpace(req UserSpaceSpaceToSpace) (*UserSpaceSpaceToSpaceResp, error) { | func (c *Client) UserSpaceSpaceToSpace(req UserSpaceSpaceToSpace) (*UserSpaceSpaceToSpaceResp, error) { | ||||
| return JSONAPI(c.cfg, http.DefaultClient, &req, &UserSpaceSpaceToSpaceResp{}) | |||||
| return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceSpaceToSpaceResp{}) | |||||
| } | } | ||||
| @@ -7,8 +7,8 @@ import ( | |||||
| "io" | "io" | ||||
| "mime/multipart" | "mime/multipart" | ||||
| "net/http" | "net/http" | ||||
| "net/url" | |||||
| ul "net/url" | ul "net/url" | ||||
| "path/filepath" | |||||
| "strings" | "strings" | ||||
| "github.com/google/go-querystring/query" | "github.com/google/go-querystring/query" | ||||
| @@ -20,10 +20,6 @@ import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api" | "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api" | ||||
| ) | ) | ||||
| func MakeIPFSFilePath(fileHash string) string { | |||||
| return filepath.Join("ipfs", fileHash) | |||||
| } | |||||
| func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) { | func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) { | ||||
| var ret TBody | var ret TBody | ||||
| contType := resp.Header.Get("Content-Type") | contType := resp.Header.Get("Content-Type") | ||||
| @@ -49,16 +45,14 @@ func JSONAPI[Resp sdks.APIResponse, Req sdks.APIRequest](cfg *api.Config, cli *h | |||||
| param := req.MakeParam() | param := req.MakeParam() | ||||
| httpReq, err := param.MakeRequest(cfg.URL) | |||||
| v1EndPoint, err := url.JoinPath(cfg.EndPoint, "v1") | |||||
| if err != nil { | if err != nil { | ||||
| return resp, err | return resp, err | ||||
| } | } | ||||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||||
| err = SignWithPayloadHash(httpReq, calcSha256(param.Body), cfg.AccessKey, cfg.SecretKey) | |||||
| if err != nil { | |||||
| return resp, err | |||||
| } | |||||
| httpReq, err := param.MakeRequest(v1EndPoint) | |||||
| if err != nil { | |||||
| return resp, err | |||||
| } | } | ||||
| httpResp, err := cli.Do(httpReq) | httpResp, err := cli.Do(httpReq) | ||||
| @@ -73,16 +67,14 @@ func JSONAPI[Resp sdks.APIResponse, Req sdks.APIRequest](cfg *api.Config, cli *h | |||||
| func JSONAPINoData[Req sdks.APIRequest](cfg *api.Config, cli *http.Client, req Req) error { | func JSONAPINoData[Req sdks.APIRequest](cfg *api.Config, cli *http.Client, req Req) error { | ||||
| param := req.MakeParam() | param := req.MakeParam() | ||||
| httpReq, err := param.MakeRequest(cfg.URL) | |||||
| v1EndPoint, err := url.JoinPath(cfg.EndPoint, "v1") | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||||
| err = SignWithPayloadHash(httpReq, calcSha256(param.Body), cfg.AccessKey, cfg.SecretKey) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| httpReq, err := param.MakeRequest(v1EndPoint) | |||||
| if err != nil { | |||||
| return err | |||||
| } | } | ||||
| resp, err := cli.Do(httpReq) | resp, err := cli.Do(httpReq) | ||||
| @@ -166,13 +158,6 @@ func PostMultiPart(cfg *api.Config, url string, info any, files http2.MultiPartF | |||||
| req.Body = pr | req.Body = pr | ||||
| if cfg.AccessKey != "" && cfg.SecretKey != "" { | |||||
| err = SignWithoutBody(req, cfg.AccessKey, cfg.SecretKey) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| } | |||||
| cli := http.Client{} | cli := http.Client{} | ||||
| resp, err := cli.Do(req) | resp, err := cli.Do(req) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -0,0 +1,5 @@ | |||||
| package all | |||||
| import ( | |||||
| _ "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd/bucket" | |||||
| ) | |||||
| @@ -0,0 +1,14 @@ | |||||
| package bucket | |||||
| import ( | |||||
| "github.com/spf13/cobra" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd" | |||||
| ) | |||||
| var BucketCmd = &cobra.Command{ | |||||
| Use: "bucket", | |||||
| } | |||||
| func init() { | |||||
| cmd.RootCmd.AddCommand(BucketCmd) | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| package bucket | |||||
| import ( | |||||
| "fmt" | |||||
| "github.com/jedib0t/go-pretty/v6/table" | |||||
| "github.com/spf13/cobra" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd" | |||||
| ) | |||||
| func init() { | |||||
| var opt lsOpt | |||||
| cmd := cobra.Command{ | |||||
| Use: "ls", | |||||
| Run: func(c *cobra.Command, args []string) { | |||||
| ctx := cmd.GetCmdCtx(c) | |||||
| ls(c, ctx, opt) | |||||
| }, | |||||
| } | |||||
| cmd.Flags().BoolVarP(&opt.Long, "", "l", false, "listing in long format") | |||||
| BucketCmd.AddCommand(&cmd) | |||||
| } | |||||
| type lsOpt struct { | |||||
| Long bool | |||||
| } | |||||
| func ls(c *cobra.Command, ctx *cmd.CommandContext, opt lsOpt) { | |||||
| resp, err := ctx.Client.Bucket().ListAll(api.BucketListAll{}) | |||||
| if err != nil { | |||||
| cmd.ErrorExitln(err.Error()) | |||||
| } | |||||
| if opt.Long { | |||||
| fmt.Printf("total: %d\n", len(resp.Buckets)) | |||||
| tb := table.NewWriter() | |||||
| tb.AppendHeader(table.Row{"Bucket ID", "Name", "Create Time"}) | |||||
| for _, b := range resp.Buckets { | |||||
| tb.AppendRow(table.Row{b.BucketID, b.Name, b.CreateTime}) | |||||
| } | |||||
| fmt.Println(tb.Render()) | |||||
| } else { | |||||
| for _, b := range resp.Buckets { | |||||
| fmt.Println(b.Name) | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,118 @@ | |||||
| package cmd | |||||
| import ( | |||||
| "context" | |||||
| "crypto/tls" | |||||
| "crypto/x509" | |||||
| "fmt" | |||||
| "os" | |||||
| "path/filepath" | |||||
| "github.com/spf13/cobra" | |||||
| "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api" | |||||
| cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" | |||||
| ) | |||||
| const ( | |||||
| defaultCAFileName = "ca_cert.pem" | |||||
| defaultCertFileName = "client_cert.pem" | |||||
| defaultKeyFileName = "client_key.pem" | |||||
| ) | |||||
| var RootCmd = cobra.Command{} | |||||
| type CommandContext struct { | |||||
| Client *cliapi.Client | |||||
| RootCA *x509.CertPool | |||||
| Cert tls.Certificate | |||||
| } | |||||
| func GetCmdCtx(cmd *cobra.Command) *CommandContext { | |||||
| return cmd.Context().Value("cmdCtx").(*CommandContext) | |||||
| } | |||||
| func RootExecute() { | |||||
| var ca string | |||||
| var cert string | |||||
| var key string | |||||
| var endpoint string | |||||
| RootCmd.Flags().StringVar(&ca, "ca", "", "CA certificate file path") | |||||
| RootCmd.Flags().StringVar(&cert, "cert", "", "client certificate file path") | |||||
| RootCmd.Flags().StringVar(&key, "key", "", "client key file path") | |||||
| RootCmd.Flags().StringVarP(&endpoint, "endpoint", "e", "", "API endpoint") | |||||
| RootCmd.MarkFlagsRequiredTogether("ca", "cert", "key") | |||||
| if ca == "" { | |||||
| certDir := searchCertDir() | |||||
| if certDir == "" { | |||||
| fmt.Printf("cert files not found, please specify --ca, --cert and --key\n") | |||||
| os.Exit(1) | |||||
| } | |||||
| ca = filepath.Join(certDir, defaultCAFileName) | |||||
| cert = filepath.Join(certDir, defaultCertFileName) | |||||
| key = filepath.Join(certDir, defaultKeyFileName) | |||||
| } | |||||
| rootCAPool := x509.NewCertPool() | |||||
| rootCAPem, err := os.ReadFile(ca) | |||||
| if err != nil { | |||||
| fmt.Printf("reading CA file: %v\n", err) | |||||
| os.Exit(1) | |||||
| } | |||||
| if !rootCAPool.AppendCertsFromPEM(rootCAPem) { | |||||
| fmt.Printf("parsing CA failed") | |||||
| os.Exit(1) | |||||
| } | |||||
| clientCert, err := tls.LoadX509KeyPair(cert, key) | |||||
| if err != nil { | |||||
| fmt.Printf("loading client cert/key: %v\n", err) | |||||
| os.Exit(1) | |||||
| } | |||||
| if endpoint == "" { | |||||
| endpoint = "https://127.0.0.1:7890" | |||||
| } | |||||
| cli := cliapi.NewClient(api.Config{ | |||||
| EndPoint: endpoint, | |||||
| RootCA: rootCAPool, | |||||
| Cert: clientCert, | |||||
| }) | |||||
| RootCmd.ExecuteContext(context.WithValue(context.Background(), "cmdCtx", &CommandContext{ | |||||
| Client: cli, | |||||
| RootCA: rootCAPool, | |||||
| Cert: clientCert, | |||||
| })) | |||||
| } | |||||
| func searchCertDir() string { | |||||
| execPath, err := os.Executable() | |||||
| if err == nil { | |||||
| execDir := filepath.Dir(execPath) | |||||
| ca, err := os.Stat(filepath.Join(execDir, defaultCAFileName)) | |||||
| if err == nil && !ca.IsDir() { | |||||
| return execDir | |||||
| } | |||||
| } | |||||
| workDir, err := os.Getwd() | |||||
| if err == nil { | |||||
| ca, err := os.Stat(filepath.Join(workDir, defaultCAFileName)) | |||||
| if err == nil && !ca.IsDir() { | |||||
| return workDir | |||||
| } | |||||
| } | |||||
| return "" | |||||
| } | |||||
| func loadCert() { | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package cmd | |||||
| import ( | |||||
| "fmt" | |||||
| "os" | |||||
| ) | |||||
| func ErrorExitf(format string, args ...interface{}) { | |||||
| fmt.Printf(format, args...) | |||||
| os.Exit(1) | |||||
| } | |||||
| func ErrorExitln(msg string) { | |||||
| fmt.Println(msg) | |||||
| os.Exit(1) | |||||
| } | |||||
| @@ -0,0 +1,11 @@ | |||||
| package main | |||||
| import ( | |||||
| "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd" | |||||
| _ "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd/all" | |||||
| _ "google.golang.org/grpc/balancer/grpclb" | |||||
| ) | |||||
| func main() { | |||||
| cmd.RootExecute() | |||||
| } | |||||
| @@ -46,6 +46,9 @@ func Bin() error { | |||||
| if err := Coordinator(); err != nil { | if err := Coordinator(); err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| if err := Jcsctl(); err != nil { | |||||
| return err | |||||
| } | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -122,3 +125,12 @@ func Coordinator() error { | |||||
| EntryFile: "coordinator/main.go", | EntryFile: "coordinator/main.go", | ||||
| }) | }) | ||||
| } | } | ||||
| func Jcsctl() error { | |||||
| return magefiles.Build(magefiles.BuildArgs{ | |||||
| OutputName: "jcsctl", | |||||
| OutputDir: "jcsctl", | |||||
| AssetsDir: "assets", | |||||
| EntryFile: "jcsctl/main.go", | |||||
| }) | |||||
| } | |||||