mirror of
https://github.com/qdm12/gluetun.git
synced 2026-05-10 04:30:20 +02:00
feat(publicip): resilient public ip fetcher (#2518)
- `PUBLICIP_API` accepts a comma separated list of ip data sources, where the first one is the base default one, and sources after it are backup sources used if we are rate limited. - `PUBLICIP_API` defaults to `ipinfo,ifconfigco,ip2location,cloudflare` such that it now has `ifconfigco,ip2location,cloudflare` as backup ip data sources. - `PUBLICIP_API_TOKEN` accepts a comma separated list of ip data source tokens, each corresponding by position to the APIs listed in `PUBLICIP_API`. - logs ip data source when logging public ip information - assume a rate limiting error is for 30 days (no persistence) - ready for future live settings updates - consider an ip data source no longer banned if the token changes - keeps track of ban times when updating the list of fetchers
This commit is contained in:
+38
-13
@@ -3,12 +3,14 @@ package publicip
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/publicip/api"
|
||||
)
|
||||
|
||||
type Loop struct {
|
||||
@@ -17,9 +19,10 @@ type Loop struct {
|
||||
settingsMutex sync.RWMutex
|
||||
ipData models.PublicIP
|
||||
ipDataMutex sync.RWMutex
|
||||
fetcher *api.ResilientFetcher
|
||||
// Fixed injected objects
|
||||
fetcher Fetcher
|
||||
logger Logger
|
||||
httpClient *http.Client
|
||||
logger Logger
|
||||
// Fixed parameters
|
||||
puid int
|
||||
pgid int
|
||||
@@ -37,17 +40,34 @@ type Loop struct {
|
||||
timeNow func() time.Time
|
||||
}
|
||||
|
||||
func NewLoop(fetcher Fetcher, logger Logger,
|
||||
settings settings.PublicIP, puid, pgid int,
|
||||
) *Loop {
|
||||
return &Loop{
|
||||
settings: settings,
|
||||
fetcher: fetcher,
|
||||
logger: logger,
|
||||
puid: puid,
|
||||
pgid: pgid,
|
||||
timeNow: time.Now,
|
||||
func NewLoop(settings settings.PublicIP, puid, pgid int,
|
||||
httpClient *http.Client, logger Logger,
|
||||
) (loop *Loop, err error) {
|
||||
fetchers, err := api.New(makeNameTokenPairs(settings.APIs), httpClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating fetchers: %w", err)
|
||||
}
|
||||
|
||||
return &Loop{
|
||||
settings: settings,
|
||||
httpClient: httpClient,
|
||||
fetcher: api.NewResilient(fetchers, logger),
|
||||
logger: logger,
|
||||
puid: puid,
|
||||
pgid: pgid,
|
||||
timeNow: time.Now,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeNameTokenPairs(apis []settings.PublicIPAPI) (nameTokenPairs []api.NameToken) {
|
||||
nameTokenPairs = make([]api.NameToken, len(apis))
|
||||
for i := range apis {
|
||||
nameTokenPairs[i] = api.NameToken{
|
||||
Name: apis[i].Name,
|
||||
Token: apis[i].Token,
|
||||
}
|
||||
}
|
||||
return nameTokenPairs
|
||||
}
|
||||
|
||||
func (l *Loop) String() string {
|
||||
@@ -102,7 +122,8 @@ func (l *Loop) run(runCtx context.Context, runDone chan<- struct{},
|
||||
}
|
||||
|
||||
message := "Public IP address is " + result.IP.String()
|
||||
message += " (" + result.Country + ", " + result.Region + ", " + result.City + ")"
|
||||
message += " (" + result.Country + ", " + result.Region + ", " + result.City +
|
||||
" - source: " + l.fetcher.String() + ")"
|
||||
l.logger.Info(message)
|
||||
|
||||
l.ipDataMutex.Lock()
|
||||
@@ -159,3 +180,7 @@ func (l *Loop) Stop() (err error) {
|
||||
<-l.runDone
|
||||
return l.ClearData()
|
||||
}
|
||||
|
||||
func (l *Loop) Fetcher() (fetcher *api.ResilientFetcher) {
|
||||
return l.fetcher
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user