424 lines
12 KiB
Go
424 lines
12 KiB
Go
package saashttp
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.algo.com.cn/public/saasapi"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
type ResponseEncoder int
|
|
|
|
const (
|
|
RESPONSE_ENCODER_PROTOBUF ResponseEncoder = iota
|
|
RESPONSE_ENCODER_JSON = 1
|
|
)
|
|
|
|
type SaasClient struct {
|
|
Client *http.Client
|
|
ApiUrls *ApiUrls
|
|
Auth *Auth
|
|
ResponseEncoder ResponseEncoder
|
|
}
|
|
|
|
func (c *SaasClient) Info(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.InfoPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) Write(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.WritePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) Read(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ReadPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ColumnWrite(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ColumnWritePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskCreatePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskInfo(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskInfoPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskRun(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskRunPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TaskUpload(sha256 string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskUploadPath, "sha256", sha256)
|
|
return c.upload(postUrl, file, offset, size)
|
|
}
|
|
|
|
func (c *SaasClient) TaskDownload(sha256 string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TaskDownloadPath, "sha256", sha256)
|
|
return c.download(postUrl, file, offset, size)
|
|
}
|
|
|
|
func (c *SaasClient) TargetList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TargetListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TargetCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TargetCreatePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) TargetDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.TargetDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) BindSet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.BindSetPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) BindDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.BindDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ScriptRun(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptRunPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ExpList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ExpGet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGetPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) GrantList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) GrantAdd(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantAddPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) GrantDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.GrantDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ExpGrantList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ExpGrantAdd(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantAddPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ExpGrantDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ExpGrantDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) makeUrl(baseUrl, path string, params ...string) string {
|
|
url, err := url.Parse(baseUrl)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
url = url.JoinPath(path)
|
|
queryValues := url.Query()
|
|
switch c.ResponseEncoder {
|
|
case RESPONSE_ENCODER_PROTOBUF:
|
|
queryValues.Add("resmode", "protobuf")
|
|
case RESPONSE_ENCODER_JSON:
|
|
queryValues.Add("resmode", "json")
|
|
default:
|
|
queryValues.Add("resmode", "protobuf")
|
|
}
|
|
|
|
for i := 0; i < len(params); i += 2 {
|
|
queryValues.Add(params[i], params[i+1])
|
|
}
|
|
url.RawQuery = queryValues.Encode()
|
|
|
|
return url.String()
|
|
}
|
|
|
|
func (c *SaasClient) post(url string, saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postBuf, err := proto.Marshal(saasReq)
|
|
if err != nil {
|
|
fmt.Println("marshal saas req error", err)
|
|
return nil, err
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(postBuf))
|
|
if err != nil {
|
|
fmt.Println("http new request error", err)
|
|
return nil, err
|
|
}
|
|
|
|
timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
|
|
md5byte := md5.Sum([]byte(c.Auth.Account + c.Auth.Token + timeStamp))
|
|
authorization := hex.EncodeToString(md5byte[:])
|
|
|
|
req.Header.Add("Account", c.Auth.Account)
|
|
req.Header.Add("Time", timeStamp)
|
|
req.Header.Add("Authorization", authorization)
|
|
req.Header.Add("Content-Type", "application/x-protobuf")
|
|
res, err := c.Client.Do(req)
|
|
if err != nil {
|
|
fmt.Println("http send error", err)
|
|
return nil, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
resBody, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
fmt.Println("http read body error", err)
|
|
return nil, err
|
|
}
|
|
|
|
saasRes = &saasapi.SaasRes{}
|
|
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
|
|
err = proto.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to protobuf error", err)
|
|
return nil, err
|
|
}
|
|
} else {
|
|
err = json.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to json error", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return saasRes, nil
|
|
}
|
|
|
|
func (c *SaasClient) upload(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
|
|
if file == nil {
|
|
return nil, fmt.Errorf("file is nil")
|
|
}
|
|
|
|
if size <= 0 {
|
|
return nil, fmt.Errorf("size is invalid")
|
|
}
|
|
|
|
buf := make([]byte, size)
|
|
n, err := file.ReadAt(buf, offset)
|
|
if err != nil {
|
|
fmt.Println("read file error", err)
|
|
return nil, err
|
|
}
|
|
if n != size {
|
|
return nil, fmt.Errorf("read file error")
|
|
}
|
|
|
|
var gzBuf bytes.Buffer
|
|
gz := gzip.NewWriter(&gzBuf)
|
|
|
|
if _, err := gz.Write(buf); err != nil {
|
|
fmt.Println("gzip write error", err)
|
|
return nil, err
|
|
}
|
|
|
|
if err = gz.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(gzBuf.Bytes()))
|
|
if err != nil {
|
|
fmt.Println("http new request error", err)
|
|
return nil, err
|
|
}
|
|
|
|
timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
|
|
md5byte := md5.Sum([]byte(c.Auth.Account + c.Auth.Token + timeStamp))
|
|
authorization := hex.EncodeToString(md5byte[:])
|
|
|
|
req.Header.Add("Account", c.Auth.Account)
|
|
req.Header.Add("Time", timeStamp)
|
|
req.Header.Add("Authorization", authorization)
|
|
req.Header.Add("Content-Type", "application/octet-stream")
|
|
req.Header.Add("Content-Encoding", "gzip")
|
|
res, err := c.Client.Do(req)
|
|
if err != nil {
|
|
fmt.Println("http send error", err)
|
|
return nil, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
resBody, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
fmt.Println("http read body error", err)
|
|
return nil, err
|
|
}
|
|
|
|
saasRes = &saasapi.SaasRes{}
|
|
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
|
|
err = proto.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to protobuf error", err)
|
|
return nil, err
|
|
}
|
|
} else {
|
|
err = json.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to json error", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return saasRes, nil
|
|
}
|
|
|
|
func (c *SaasClient) download(url string, file *os.File, offset int64, size int) (saasRes *saasapi.SaasRes, err error) {
|
|
if file == nil {
|
|
return nil, fmt.Errorf("file is nil")
|
|
}
|
|
|
|
if size <= 0 {
|
|
return nil, fmt.Errorf("size is invalid")
|
|
}
|
|
|
|
req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
|
|
if err != nil {
|
|
fmt.Println("http new request error", err)
|
|
return nil, err
|
|
}
|
|
|
|
timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
|
|
md5byte := md5.Sum([]byte(c.Auth.Account + c.Auth.Token + timeStamp))
|
|
authorization := hex.EncodeToString(md5byte[:])
|
|
|
|
req.Header.Add("Account", c.Auth.Account)
|
|
req.Header.Add("Time", timeStamp)
|
|
req.Header.Add("Authorization", authorization)
|
|
req.Header.Add("Accept-Encoding", "gzip")
|
|
|
|
res, err := c.Client.Do(req)
|
|
if err != nil {
|
|
fmt.Println("http send error", err)
|
|
return nil, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
if res.StatusCode != 200 {
|
|
err = fmt.Errorf("NOT 200. %v", res.StatusCode)
|
|
fmt.Println("http state error", err)
|
|
return nil, err
|
|
}
|
|
|
|
bodyReader := res.Body
|
|
if strings.Contains(res.Header.Get("Content-Encoding"), "gzip") {
|
|
gz, err := gzip.NewReader(res.Body)
|
|
if err != nil {
|
|
fmt.Println("gzip newreader error", err)
|
|
return nil, err
|
|
}
|
|
defer gz.Close()
|
|
bodyReader = gz
|
|
}
|
|
|
|
resBody, err := io.ReadAll(bodyReader)
|
|
if err != nil {
|
|
fmt.Println("read body error", err)
|
|
return nil, err
|
|
}
|
|
saasRes = &saasapi.SaasRes{}
|
|
|
|
if strings.Contains(res.Header.Get("Content-Type"), "application/octet-stream") {
|
|
if len(resBody) == size {
|
|
file.WriteAt(resBody, offset)
|
|
} else {
|
|
err = fmt.Errorf("body size error. body:%v, want:%v", len(resBody), size)
|
|
fmt.Println("http read body error", err)
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if c.ResponseEncoder == RESPONSE_ENCODER_PROTOBUF {
|
|
err = proto.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to protobuf error", err)
|
|
return nil, err
|
|
}
|
|
} else {
|
|
err = json.Unmarshal(resBody, saasRes)
|
|
if err != nil {
|
|
fmt.Println("unmarshal response body to json error", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
|
|
return saasRes, nil
|
|
}
|
|
|
|
func (c *SaasClient) ScriptCreate(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptCreatePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ScriptList(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptListPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ScriptDelete(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptDeletePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ScriptGet(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptGetPath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|
|
|
|
func (c *SaasClient) ScriptUse(saasReq *saasapi.SaasReq) (saasRes *saasapi.SaasRes, err error) {
|
|
postUrl := c.makeUrl(c.ApiUrls.BaseUrl, c.ApiUrls.ScriptUsePath)
|
|
return c.post(postUrl, saasReq)
|
|
}
|