chord/chord/httpnode/client.go
2025-03-11 08:52:20 -04:00

58 lines
1.5 KiB
Go

package httpnode
import (
"context"
"errors"
"fmt"
"net/http"
"net/netip"
"net/url"
"path"
"git.sunturtle.xyz/zephyr/chord/chord"
)
type Client struct {
// HTTP is the client used to make requests.
HTTP http.Client
// APIBase is the path under which the Chord API is served.
APIBase string
}
// FindSuccessor asks s to find the first peer in the network preceding id.
func (cl *Client) FindSuccessor(ctx context.Context, s chord.Peer, id chord.ID) (chord.Peer, error) {
_, addr := s.Values()
if !addr.IsValid() {
return chord.Peer{}, errors.New("FindSuccessor with invalid peer")
}
url := url.URL{
Scheme: "http",
Host: addr.String(),
Path: path.Join("/", cl.APIBase, "succ"),
RawQuery: url.Values{"s": {id.String()}}.Encode(),
}
req, err := http.NewRequestWithContext(ctx, "GET", url.String(), nil)
if err != nil {
return chord.Peer{}, err
}
resp, err := cl.HTTP.Do(req)
if err != nil {
return chord.Peer{}, err
}
p, err := readResponse[netip.AddrPort](resp)
if err != nil {
return chord.Peer{}, fmt.Errorf("%w (%s)", err, resp.Status)
}
return chord.Address(p), nil
}
// Notify tells s we believe n to be its predecessor.
func (cl *Client) Notify(ctx context.Context, n *chord.Node, s chord.Peer) error {
panic("not implemented") // TODO: Implement
}
// Neighbors requests a peer's beliefs about its own neighbors.
func (cl *Client) Neighbors(ctx context.Context, p chord.Peer) (pred chord.Peer, succ []chord.Peer, err error) {
panic("not implemented") // TODO: Implement
}