2024-11-16 10:38:32 -04:00

96 lines
2.2 KiB
Go

// Package that will query for IP
package checker
import (
"errors"
"io"
"log/slog"
"net"
"net/http"
"strings"
"github.com/maximotejeda/ddns/config"
)
type client struct {
urls []string
method string
headers map[string][]string
reqs []*http.Request
log *slog.Logger
}
type Response struct {
IP *net.IP `json:"ip,omitempty" yaml:"ip,omitempty"`
IPSTR string `json:"ip_str,omitempty" yaml:"ip_str,omitempty"`
Version string `json:"version" yaml:"version,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Identifyer string `json:"identifyer" yaml:"identifyer"`
}
func NewClient(log *slog.Logger, provider string) *client {
c := &client{}
c.urls = strings.Split(config.GetServiceVerifyURL("IP_VERIFY_PROVIDER_URL"), ",")
c.method = http.MethodGet
for _, url := range c.urls {
req, _ := http.NewRequest(c.method, url, nil)
c.reqs = append(c.reqs, req)
}
log = log.With("location", "Checker")
c.log = log
return c
}
// Do
// Make a request to retrieve the ip of the machine
func (c *client) Do() (res *Response, err error) {
r := &Response{}
client := http.DefaultClient
if len(c.reqs) <= 0 {
c.log.Error("no request on struct")
return nil, errors.New("no request on client struct")
}
resp, err := client.Do(c.reqs[0])
r.Identifyer = c.urls[0]
if err != nil {
c.log.Error("doing request for ip", "err", err, "identidyer", c.reqs[0])
c.log.Info("retrying on other provider")
resp, err = client.Do(c.reqs[1])
r.Identifyer = c.urls[1]
if err != nil {
c.log.Error("doing request for ip", "err", err, "identidyer", c.reqs[1])
return nil, err
}
}
defer resp.Body.Close()
ipSTR, err := io.ReadAll(resp.Body)
if err != nil {
c.log.Error("reading body", "error", err.Error())
}
ipi := net.ParseIP(string(ipSTR))
r.IP = &ipi
//check ip is not nil
if r.IP == nil {
return nil, errors.New("ip not found")
}
// check if ip is private
if r.IP.IsPrivate() {
return nil, errors.New("ip is a private ip")
}
// check if is loop back ip
if r.IP.IsLoopback() {
return nil, errors.New("ip is a loopback ip")
}
if r.IP.To4() != nil {
r.Version = "V4"
r.Type = "A"
}else {
r.Version = "V6"
r.Type = "AAAA"
}
return r, err
}