package main import ( "bytes" "context" "encoding/json" "fmt" "io" "log" "net/http" "strings" "sync" "time" ) const timeout = 1 * time.Second type MonitorIdTag struct { ConnectorId uint `json:"connectorId"` IdTag string `json:"idTag"` } type ResponseEntity struct { Timestamp *time.Time `json:"timestamp"` Status uint `json:"status"` Error *string `json:"error"` Path *string `json:"path"` } type RestInterface interface { Send(id rune) } type rest struct { connectorId uint url string timeout time.Duration mutex sync.Mutex timer *time.Timer sb strings.Builder nospace bool } func NewRest(connectorId uint, url string, timeout time.Duration, nospace bool) RestInterface { r := rest{connectorId: connectorId, url: url, timeout: timeout, nospace: nospace} return &r } func (c *rest) Send(r rune) { c.mutex.Lock() defer c.mutex.Unlock() if !(c.nospace && r == ' ') { c.sb.WriteRune(r) } if c.timer != nil { c.timer.Reset(timeout) } else { f := func() { s := c.sb.String() log.Printf("Sent '%s'", s) go c.send(s) c.sb.Reset() } c.timer = time.AfterFunc(timeout, f) } } func (c *rest) send(id string) { tag := &MonitorIdTag{IdTag: id, ConnectorId: c.connectorId} //if c.connectorId > 0 { // tag.ConnectorId = &c.connectorId //} var b []byte var err error var request *http.Request var response *http.Response if b, err = json.Marshal(tag); err != nil { log.Printf("Can't marschal request: %e\n", err) return } ctx, _ := context.WithTimeout(context.Background(), c.timeout) byteReader := bytes.NewReader(b) if request, err = http.NewRequestWithContext(ctx, "POST", c.url, byteReader); err != nil { log.Printf("Can't build new request: %e\n", err) return } request.Header.Add("Content-Type", "application/json") if response, err = http.DefaultClient.Do(request); err != nil { log.Printf("Error while rerforming request: %e\n", err) return } switch response.StatusCode { case 200: log.Printf("Result OK for id '%s'\n", id) case 401: log.Printf("Result UNAUTHORIZED for id '%s'\n", id) default: log.Printf("Recieve non sucess status code '%d' for id '%s'\n", response.StatusCode, id) } if response.ContentLength == 0 { log.Println("Response body empty") return } if b, err = io.ReadAll(response.Body); err != nil { log.Printf("Can't read replay body: %e\n", err) return } if err = response.Body.Close(); err != nil { log.Printf("Error while closing response body: %e\n", err) return } entity := &ResponseEntity{} if err = json.Unmarshal(b, entity); err != nil { log.Printf("Can't unmarschal response body: %e\n", err) return } log.Printf("ResponseEntity: %v\n", entity) } func (r *ResponseEntity) String() string { var sb strings.Builder if r.Path != nil { sb.WriteString("path = '") sb.WriteString(*r.Path) sb.WriteString("'") } if r.Error != nil { if sb.Len() > 0 { sb.WriteString(", ") } sb.WriteString("error = '") sb.WriteString(*r.Error) sb.WriteString("'") } if r.Timestamp != nil { if sb.Len() > 0 { sb.WriteString(", ") } sb.WriteString("timestamp = '") sb.WriteString(r.Timestamp.String()) sb.WriteString("'") } if sb.Len() > 0 { sb.WriteString(", ") } sb.WriteString("status = ") sb.WriteString(fmt.Sprint(r.Status)) return sb.String() }