Feat: location data at /v1/publicip/ip

This commit is contained in:
Quentin McGaw (desktop)
2021-09-05 22:54:10 +00:00
parent 82ac568ee3
commit f9cb71027c
9 changed files with 62 additions and 42 deletions

View File

@@ -2,5 +2,5 @@ package publicip
import "github.com/qdm12/gluetun/internal/publicip/state"
type Getter = state.PublicIPGetter
type Getter = state.DataGetter
type SettingsGetSetter = state.SettingsGetSetter

View File

@@ -10,21 +10,16 @@ import (
"strings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/publicip/models"
)
type Result struct {
Region string `json:"region"`
Country string `json:"country"`
City string `json:"city"`
}
var (
ErrTooManyRequests = errors.New("too many requests sent for this month")
ErrBadHTTPStatus = errors.New("bad HTTP status received")
)
func Info(ctx context.Context, client *http.Client, ip net.IP) ( //nolint:interfacer
result Result, err error) {
result models.IPInfoData, err error) {
const baseURL = "https://ipinfo.io/"
url := baseURL + ip.String()
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)

View File

@@ -0,0 +1,27 @@
package models
import "net"
type IPInfoData struct {
IP net.IP `json:"public_ip"`
Region string `json:"region,omitempty"`
Country string `json:"country,omitempty"`
City string `json:"city,omitempty"`
Hostname string `json:"hostname,omitempty"`
Loc string `json:"loc,omitempty"`
Org string `json:"org,omitempty"`
Postal string `json:"postal,omitempty"`
Timezone string `json:"timezone,omitempty"`
}
func (i IPInfoData) Copy() (copied IPInfoData) {
copied = i
copied.IP = make(net.IP, len(i.IP))
copy(copied.IP, i.IP)
return copied
}
func (i *IPInfoData) SetIP(ip net.IP) {
i.IP = make(net.IP, len(ip))
copy(i.IP, ip)
}

View File

@@ -4,6 +4,8 @@ import (
"context"
"net"
"net/http"
"github.com/qdm12/gluetun/internal/publicip/models"
)
// MultiInfo obtains the public IP address information for every IP
@@ -13,12 +15,12 @@ import (
// an error is returned, so the results returned should be considered
// incomplete in this case.
func MultiInfo(ctx context.Context, client *http.Client, ips []net.IP) (
results []Result, err error) {
results []models.IPInfoData, err error) {
ctx, cancel := context.WithCancel(ctx)
type asyncResult struct {
index int
result Result
result models.IPInfoData
err error
}
resultsCh := make(chan asyncResult)
@@ -33,7 +35,7 @@ func MultiInfo(ctx context.Context, client *http.Client, ips []net.IP) (
}(i, ip)
}
results = make([]Result, len(ips))
results = make([]models.IPInfoData, len(ips))
for i := 0; i < len(ips); i++ {
aResult := <-resultsCh
if aResult.err != nil {

View File

@@ -1,7 +1,9 @@
package publicip
import "net"
import (
"github.com/qdm12/gluetun/internal/publicip/models"
)
func (l *Loop) GetPublicIP() (publicIP net.IP) {
return l.state.GetPublicIP()
func (l *Loop) GetData() (data models.IPInfoData) {
return l.state.GetData()
}

View File

@@ -70,7 +70,6 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
l.stopped <- struct{}{}
case ip := <-ipCh:
getCancel()
l.state.SetPublicIP(ip)
message := "Public IP address is " + ip.String()
result, err := Info(ctx, l.client, ip)
@@ -81,6 +80,9 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
}
l.logger.Info(message)
result.SetIP(ip)
l.state.SetData(result)
filepath := l.state.GetSettings().IPFilepath
err = persistPublicIP(filepath, ip.String(), l.puid, l.pgid)
if err != nil {

View File

@@ -1,29 +1,26 @@
package state
import (
"net"
"github.com/qdm12/gluetun/internal/publicip/models"
)
type PublicIPGetSetter interface {
PublicIPGetter
SetPublicIP(publicIP net.IP)
type DataGetSetter interface {
DataGetter
SetData(data models.IPInfoData)
}
type PublicIPGetter interface {
GetPublicIP() (publicIP net.IP)
type DataGetter interface {
GetData() (data models.IPInfoData)
}
func (s *State) GetPublicIP() (publicIP net.IP) {
s.publicIPMu.RLock()
defer s.publicIPMu.RUnlock()
publicIP = make(net.IP, len(s.publicIP))
copy(publicIP, s.publicIP)
return publicIP
func (s *State) GetData() (data models.IPInfoData) {
s.ipDataMu.RLock()
defer s.ipDataMu.RUnlock()
return s.ipData.Copy()
}
func (s *State) SetPublicIP(publicIP net.IP) {
s.settingsMu.Lock()
defer s.settingsMu.Unlock()
s.publicIP = make(net.IP, len(publicIP))
copy(s.publicIP, publicIP)
func (s *State) SetData(data models.IPInfoData) {
s.ipDataMu.Lock()
defer s.ipDataMu.Unlock()
s.ipData = data.Copy()
}

View File

@@ -1,18 +1,18 @@
package state
import (
"net"
"sync"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/loopstate"
"github.com/qdm12/gluetun/internal/publicip/models"
)
var _ Manager = (*State)(nil)
type Manager interface {
SettingsGetSetter
PublicIPGetSetter
DataGetSetter
}
func New(statusApplier loopstate.Applier,
@@ -31,8 +31,8 @@ type State struct {
settings configuration.PublicIP
settingsMu sync.RWMutex
publicIP net.IP
publicIPMu sync.RWMutex
ipData models.IPInfoData
ipDataMu sync.RWMutex
updateTicker chan<- struct{}
}