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 string) } type rest struct { connectorId uint url string timeout time.Duration mutex sync.Mutex timer *time.Timer sb strings.Builder } func NewRest(connectorId uint, url string, timeout time.Duration) RestInterface { r := rest{connectorId: connectorId, url: url, timeout: timeout} return &r } func (r *rest) Send(id string) { r.mutex.Lock() defer r.mutex.Unlock() r.sb.WriteString(id) if r.timer != nil { r.timer.Reset(timeout) } else { f := func() { s := r.sb.String() log.Printf("Send '%s'", s) go r.send(s) r.sb.Reset() } r.timer = time.AfterFunc(timeout, f) } } func (r *rest) send(id string) { tag := &MonitorIdTag{IdTag: id, ConnectorId: r.connectorId} //if r.connectorId > 0 { // tag.ConnectorId = &r.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(), r.timeout) byteReader := bytes.NewReader(b) if request, err = http.NewRequestWithContext(ctx, "POST", r.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() }