From 267969bc16243eb99b9ec57b75f6cef3609bb59b Mon Sep 17 00:00:00 2001 From: "v.veselskiy" Date: Thu, 6 Feb 2025 18:25:34 +0300 Subject: [PATCH] Add code for client. --- client.go | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 15 ++++++ go.sum | 18 +++++++ http_client.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 http_client.go diff --git a/client.go b/client.go index d00e386..af13405 100644 --- a/client.go +++ b/client.go @@ -1,5 +1,21 @@ package push_client +import ( + "context" + "strconv" + + "git.bit5.ru/backend/errors" + "git.bit5.ru/backend/push_common" + + "github.com/go-logr/logr" + + "go.opentelemetry.io/otel" +) + +const tracerName = "git.bit5.ru/backend/push_client" + +var tracer = otel.Tracer(tracerName) + type Client struct { Addr string } @@ -9,3 +25,112 @@ func NewClient(addr string) *Client { Addr: addr, } } + +func (c *Client) ServerInfo() (*push_common.ServerInfo, error) { + var info push_common.ServerInfo + err := httpGet(c.Addr+"/api/server_info", &info) + return &info, err +} + +func (c *Client) UserPushPreviews(ctx context.Context) ([]*push_common.PushPreview, error) { + var previews []*push_common.PushPreview + if err := httpGet(c.Addr+"/api/push/previews/user", &previews); err != nil { + return nil, err + } + return previews, nil +} + +func (c *Client) AutoPushPreviews() ([]*push_common.PushPreview, error) { + var previews []*push_common.PushPreview + if err := httpGet(c.Addr+"/api/push/previews/auto", &previews); err != nil { + return nil, err + } + return previews, nil +} + +func (c *Client) NewPush(req push_common.PushRequest) (int, error) { + resp, err := httpPostDataDeprecated(c.Addr+"/api/push/add", req) + if err != nil { + return 0, err + } + return strconv.Atoi(resp) +} + +func (c *Client) SchedulePush(ctx context.Context, def *push_common.PushDef) (int, error) { + _, span := tracer.Start(ctx, "Client.SchedulePush") + defer span.End() + + resp, err := httpPostDataDeprecated(c.Addr+"/api/push/schedule", def) + if err != nil { + return 0, err + } + return strconv.Atoi(resp) +} + +func (c *Client) StartPush(id int) error { + return httpPost(c.Addr + "/api/push/start/" + strconv.Itoa(id)) +} + +func (c *Client) PausePush(id int) error { + return httpPost(c.Addr + "/api/push/pause/" + strconv.Itoa(id)) +} + +/* +func (c *Client) ArchivePush(ctx context.Context, id int) error { + return httpPost(c.Addr + "/api/push/archive/" + strconv.Itoa(id)) +} +*/ + +func (c *Client) DelPush(ctx context.Context, id int) error { + return httpPost(c.Addr + "/api/push/del/" + strconv.Itoa(id)) +} + +func (c *Client) GetPush(id int) (*push_common.Push, error) { + var push push_common.Push + err := httpGet(c.Addr+"/api/push/get/"+strconv.Itoa(id), &push) + return &push, err +} + +func (c *Client) GetPushPayload(id int) (*push_common.PushPayload, error) { + var payload *push_common.PushPayload + if err := httpGet(c.Addr+"/api/push/get_payload/"+strconv.Itoa(id), &payload); err != nil { + return nil, err + } + return payload, nil +} + +func (c *Client) EditPushRequest(id int, payload push_common.PushPayload) error { + _, err := httpPostDataDeprecated(c.Addr+"/api/push/edit/"+strconv.Itoa(id), payload) + return err +} + +func (c *Client) GetIncomingPushes(ctx context.Context) ([]*push_common.IncomingPushInfo, error) { + _, span := tracer.Start(ctx, "Client.GetIncomingPushes") + defer span.End() + + var pushes []*push_common.IncomingPushInfo + if err := httpGet(c.Addr+"/api/push/incoming_pushes", &pushes); err != nil { + return nil, errors.WithMessage(err, "Can not load incoming pushes.") + } + + return pushes, nil +} + +func (c *Client) GetPushesToClean(ctx context.Context) ([]*push_common.Push, error) { + _, span := tracer.Start(ctx, "Client.GetPushesToClean") + defer span.End() + + var lst []*push_common.Push + if err := httpGet(c.Addr+"/api/push/list_to_clean", &lst); err != nil { + return nil, errors.WithMessage(err, "Can not load list_to_clean.") + } + return lst, nil +} + +func (c *Client) LaunchPush(ctx context.Context, logger logr.Logger, launchRequest *push_common.PushLaunchRequest) error { + _, span := tracer.Start(ctx, "Client.LaunchPush") + defer span.End() + + _, err := httpPostData(logger, c.Addr+"/api/push/launch", launchRequest) + return err +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..392e9ac --- /dev/null +++ b/go.mod @@ -0,0 +1,15 @@ +module git.bit5.ru/backend/push_client + +go 1.19 + +require ( + git.bit5.ru/backend/errors v1.0.0 + git.bit5.ru/backend/push_common v1.0.11 + github.com/go-logr/logr v1.4.2 + go.opentelemetry.io/otel v1.11.1 +) + +require ( + github.com/go-logr/stdr v1.2.2 // indirect + go.opentelemetry.io/otel/trace v1.11.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d64ac77 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +git.bit5.ru/backend/errors v1.0.0 h1:WWJ0sly44q1HQjN01X75ZAGKZwwY5Ml+XVDXMjCkToA= +git.bit5.ru/backend/errors v1.0.0/go.mod h1:75faRwsnpM0Se00/Bh7fysWQXV8oMjNJFQ6f7+r9k3Y= +git.bit5.ru/backend/push_common v1.0.11 h1:KoH2dGRBLu5fKYIO4vZt2HedvbL+2HeWB8zOlxWfzyU= +git.bit5.ru/backend/push_common v1.0.11/go.mod h1:vE9XGM1HsKjtGsT7R2gzHpdGGHn0rUyf9qsxVMGFvAU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4= +go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= +go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= +go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/http_client.go b/http_client.go new file mode 100644 index 0000000..1a50edf --- /dev/null +++ b/http_client.go @@ -0,0 +1,119 @@ +package push_client + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + + "github.com/go-logr/logr" + + "git.bit5.ru/backend/errors" +) + +func httpGet(url string, result any) error { + resp, err := http.Get(url) + if err != nil { + return errors.Wrapf(err, "Got error from http.Get. url: %q.", url) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return errors.Wrapf(err, "HTTP GET response body reading error. url: %q.", url) + } + + if resp.StatusCode != 200 { + return errors.New(string(body)) + } + + if err := json.Unmarshal(body, result); err != nil { + return errors.Wrapf(err, "HTTP GET response body parsing error. url: %q.", url) + } + return nil +} + +func httpPost(url string) error { + resp, err := http.Post(url, "application/text", nil) + if err != nil { + return errors.Wrapf(err, "Can not send POST. Network error. url: %q.", url) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return errors.Wrapf(err, "HTTP POST response body reading error. url: %q.", url) + } + + if resp.StatusCode != 200 { + return errors.New(string(body)) + } + + return nil +} + +func httpPostData(logger logr.Logger, url string, data any) (s string, resultErr error) { + + defer func() { + if r := recover(); r != nil { + logger.Error(nil, "Can not send POST request", "Panic", r) + resultErr = errors.New("panic in httpPostData") + } + }() + + reqBytes, err := json.Marshal(data) + if err != nil { + return "", errors.Wrapf(err, "Can not send POST. Can not convert data to bytes. url: %q.", url) + } + + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(reqBytes)) + if err != nil { + return "", errors.WithStack(err) + } + + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + logger.Info("Got error from client.Do") + return "", errors.Wrapf(err, "Can not send POST. Got error from client.Do(). url: %q.", url) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", errors.Wrapf(err, "HTTP POST response body reading error. url: %q.", url) + } + + if resp.StatusCode != 200 { + return "", errors.New(string(body)) + } + + return string(body), nil +} + +func httpPostDataDeprecated(url string, data any) (string, error) { + jsbytes, err := json.Marshal(data) + if err != nil { + return "", errors.Wrapf(err, "Can not send POST. Can not convert data to bytes. url: %q.", url) + } + + resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsbytes)) + if err != nil { + return "", errors.Wrapf(err, "Can not send POST. Network error. url: %q.", url) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", errors.Wrapf(err, "HTTP POST response body reading error. url: %q.", url) + } + + if resp.StatusCode != 200 { + return "", errors.New(string(body)) + } + + return string(body), nil +}