Feat: location data at /v1/publicip/ip
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
27
internal/publicip/models/ipinfo.go
Normal file
27
internal/publicip/models/ipinfo.go
Normal 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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
@@ -38,14 +38,9 @@ func (h *publicIPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
type publicIPWrapper struct {
|
||||
PublicIP string `json:"public_ip"`
|
||||
}
|
||||
|
||||
func (h *publicIPHandler) getPublicIP(w http.ResponseWriter) {
|
||||
publicIP := h.looper.GetPublicIP()
|
||||
data := h.looper.GetData()
|
||||
encoder := json.NewEncoder(w)
|
||||
data := publicIPWrapper{PublicIP: publicIP.String()}
|
||||
if err := encoder.Encode(data); err != nil {
|
||||
h.logger.Warn(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
Reference in New Issue
Block a user