jldb/lib/rep/http-client.go

110 lines
2.0 KiB
Go
Raw Normal View History

2023-10-13 09:43:27 +00:00
package rep
import (
"encoding/json"
"net"
2023-10-16 08:50:19 +00:00
"net/http"
"strings"
2023-10-13 09:43:27 +00:00
"sync"
"time"
2023-10-16 08:50:19 +00:00
"git.crumpington.com/public/jldb/lib/errs"
"git.crumpington.com/public/jldb/lib/httpconn"
"git.crumpington.com/public/jldb/lib/wal"
2023-10-13 09:43:27 +00:00
)
type client struct {
2023-10-16 08:50:19 +00:00
client *http.Client
2023-10-13 09:43:27 +00:00
// The following are constant.
endpoint string
2023-10-16 08:50:19 +00:00
pskBytes [64]byte
2023-10-13 09:43:27 +00:00
timeout time.Duration
2023-10-16 08:50:19 +00:00
lock sync.Mutex
conn net.Conn
2023-10-13 09:43:27 +00:00
}
func newClient(endpoint, psk string, timeout time.Duration) *client {
2023-10-16 08:50:19 +00:00
httpClient := &http.Client{
Timeout: timeout,
}
if !strings.HasSuffix(endpoint, "/") {
endpoint += "/"
}
2023-10-13 09:43:27 +00:00
return &client{
2023-10-16 08:50:19 +00:00
client: httpClient,
2023-10-13 09:43:27 +00:00
endpoint: endpoint,
2023-10-16 08:50:19 +00:00
pskBytes: pskToBytes(psk),
2023-10-13 09:43:27 +00:00
timeout: timeout,
}
}
func (c *client) GetInfo() (info Info, err error) {
2023-10-16 08:50:19 +00:00
req, err := http.NewRequest(http.MethodGet, c.endpoint+pathGetInfo, nil)
if err != nil {
return info, errs.Unexpected.WithErr(err)
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
req.SetBasicAuth("", string(c.pskBytes[:]))
2023-10-13 09:43:27 +00:00
2023-10-16 08:50:19 +00:00
resp, err := c.client.Do(req)
if err != nil {
return info, errs.IO.WithErr(err)
}
defer resp.Body.Close()
2023-10-13 09:43:27 +00:00
2023-10-16 08:50:19 +00:00
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
return info, errs.IO.WithErr(err)
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
return info, nil
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
func (c *client) RecvState(recv func(net.Conn) error) error {
err := c.dialConnect(c.endpoint + pathSendState)
2023-10-13 09:43:27 +00:00
if err != nil {
return err
}
2023-10-16 08:50:19 +00:00
defer c.conn.Close()
2023-10-13 09:43:27 +00:00
2023-10-16 08:50:19 +00:00
return recv(c.conn)
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
func (c *client) StreamWAL(w *wal.WAL) error {
err := c.dialConnect(c.endpoint + pathStreamWAL)
2023-10-13 09:43:27 +00:00
if err != nil {
return err
}
2023-10-16 08:50:19 +00:00
defer c.conn.Close()
2023-10-13 09:43:27 +00:00
2023-10-16 08:50:19 +00:00
return w.Recv(c.conn, c.timeout)
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
func (c *client) Close() {
2023-10-13 09:43:27 +00:00
c.lock.Lock()
defer c.lock.Unlock()
2023-10-16 08:50:19 +00:00
if c.conn != nil {
c.conn.Close()
2023-10-13 09:43:27 +00:00
}
}
2023-10-16 08:50:19 +00:00
// ----------------------------------------------------------------------------
2023-10-13 09:43:27 +00:00
2023-10-16 08:50:19 +00:00
func (c *client) dialConnect(endpoint string) error {
conn, err := httpconn.Dial(endpoint)
if err != nil {
return err
2023-10-13 09:43:27 +00:00
}
2023-10-16 08:50:19 +00:00
conn.SetWriteDeadline(time.Now().Add(c.timeout))
if _, err := conn.Write(c.pskBytes[:]); err != nil {
2023-10-13 09:43:27 +00:00
return errs.IO.WithErr(err)
}
2023-10-16 08:50:19 +00:00
c.lock.Lock()
defer c.lock.Unlock()
c.conn = conn
2023-10-13 09:43:27 +00:00
return nil
}