You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.3 KiB
171 lines
3.3 KiB
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()
|
|
}
|
|
|