-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Cody Littley <cody@eigenlabs.org>
- Loading branch information
1 parent
34ad649
commit cc009aa
Showing
11 changed files
with
356 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package pubip | ||
|
||
import "context" | ||
|
||
var _ Provider = (*mockProvider)(nil) | ||
|
||
// mockProvider is a mock implementation of the Provider interface. | ||
type mockProvider struct { | ||
} | ||
|
||
func (m mockProvider) Name() string { | ||
return "mockip" | ||
} | ||
|
||
func (m mockProvider) PublicIPAddress(ctx context.Context) (string, error) { | ||
return "localhost", nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package pubip | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
"strings" | ||
) | ||
|
||
var _ Provider = (*multiProvider)(nil) | ||
|
||
// An implementation of Provider that uses multiple providers. It attempts each provider in order until one succeeds. | ||
type multiProvider struct { | ||
logger logging.Logger | ||
providers []Provider | ||
} | ||
|
||
func (m *multiProvider) Name() string { | ||
sb := strings.Builder{} | ||
sb.WriteString("multiProvider(") | ||
for i, provider := range m.providers { | ||
sb.WriteString(provider.Name()) | ||
if i < len(m.providers)-1 { | ||
sb.WriteString(", ") | ||
} | ||
} | ||
sb.WriteString(")") | ||
return sb.String() | ||
} | ||
|
||
// NewMultiProvider creates a new multiProvider with the given providers. | ||
func NewMultiProvider( | ||
logger logging.Logger, | ||
providers ...Provider) Provider { | ||
|
||
return &multiProvider{ | ||
logger: logger, | ||
providers: providers, | ||
} | ||
} | ||
|
||
func (m *multiProvider) PublicIPAddress(ctx context.Context) (string, error) { | ||
for _, provider := range m.providers { | ||
ip, err := provider.PublicIPAddress(ctx) | ||
if err == nil { | ||
return ip, nil | ||
} | ||
m.logger.Warnf("failed to get public IP address from %s: %v", provider, err) | ||
} | ||
|
||
return "", fmt.Errorf("failed to get public IP address from any provider") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,80 @@ | ||
package pubip | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
"strings" | ||
) | ||
|
||
const ( | ||
SeepIPProvider = "seeip" | ||
IpifyProvider = "ipify" | ||
MockIpProvider = "mockip" | ||
) | ||
|
||
var ( | ||
SeeIP = &SimpleProvider{Name: "seeip", URL: "https://api.seeip.org"} | ||
Ipify = &SimpleProvider{Name: "ipify", URL: "https://api.ipify.org"} | ||
MockIp = &SimpleProvider{Name: "mockip", URL: ""} | ||
) | ||
|
||
type RequestDoer interface { | ||
Do(req *http.Request) (*http.Response, error) | ||
} | ||
|
||
type RequestDoerFunc func(req *http.Request) (*http.Response, error) | ||
SeeIPURL = "https://api.seeip.org" | ||
|
||
var _ RequestDoer = (RequestDoerFunc)(nil) | ||
IpifyProvider = "ipify" | ||
IpifyURL = "https://api.ipify.org" | ||
|
||
func (f RequestDoerFunc) Do(req *http.Request) (*http.Response, error) { | ||
return f(req) | ||
} | ||
MockIpProvider = "mockip" | ||
) | ||
|
||
// Provider is an interface for getting a machine's public IP address. | ||
type Provider interface { | ||
// Name returns the name of the provider | ||
Name() string | ||
// PublicIPAddress returns the public IP address of the node | ||
PublicIPAddress(ctx context.Context) (string, error) | ||
} | ||
|
||
type SimpleProvider struct { | ||
RequestDoer RequestDoer | ||
Name string | ||
URL string | ||
} | ||
|
||
var _ Provider = (*SimpleProvider)(nil) | ||
|
||
func (s *SimpleProvider) PublicIPAddress(ctx context.Context) (string, error) { | ||
if s.Name == MockIpProvider { | ||
return "localhost", nil | ||
// buildSimpleProviderByName returns a simple provider with the given name. | ||
// Returns nil if the name is not recognized. | ||
func buildSimpleProviderByName(name string) Provider { | ||
if name == SeepIPProvider { | ||
return NewSimpleProvider(SeepIPProvider, SeeIPURL) | ||
} else if name == IpifyProvider { | ||
return NewSimpleProvider(IpifyProvider, IpifyURL) | ||
} else if name == MockIpProvider { | ||
return &mockProvider{} | ||
} | ||
ip, err := s.doRequest(ctx, s.URL) | ||
if err != nil { | ||
return "", fmt.Errorf("%s: failed to retrieve public ip address: %w", s.Name, err) | ||
} | ||
return ip, nil | ||
return nil | ||
} | ||
|
||
func (s *SimpleProvider) doRequest(ctx context.Context, url string) (string, error) { | ||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | ||
if err != nil { | ||
return "", err | ||
} | ||
// buildDefaultProviders returns a default provider. | ||
func buildDefaultProvider(logger logging.Logger) Provider { | ||
return NewMultiProvider(logger, buildSimpleProviderByName(SeepIPProvider), buildSimpleProviderByName(IpifyProvider)) | ||
} | ||
|
||
if s.RequestDoer == nil { | ||
s.RequestDoer = http.DefaultClient | ||
} | ||
resp, err := s.RequestDoer.Do(req) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer func() { _ = resp.Body.Close() }() | ||
func providerOrDefault(logger logging.Logger, names ...string) Provider { | ||
|
||
if resp.StatusCode >= http.StatusBadRequest { | ||
return "", errors.New(resp.Status) | ||
for i, name := range names { | ||
names[i] = strings.ToLower(strings.TrimSpace(name)) | ||
} | ||
|
||
var b bytes.Buffer | ||
_, err = io.Copy(&b, resp.Body) | ||
if err != nil { | ||
return "", err | ||
if len(names) == 0 { | ||
return buildDefaultProvider(logger) | ||
} else if len(names) == 1 { | ||
provider := buildSimpleProviderByName(names[0]) | ||
if provider == nil { | ||
logger.Warnf("Unknown IP provider '%s'", names[0]) | ||
return buildDefaultProvider(logger) | ||
} | ||
return provider | ||
} else { | ||
providers := make([]Provider, len(names)) | ||
for i, name := range names { | ||
providers[i] = buildSimpleProviderByName(name) | ||
if providers[i] == nil { | ||
logger.Warnf("Unknown IP provider '%s'", name) | ||
return buildDefaultProvider(logger) | ||
} | ||
} | ||
|
||
return NewMultiProvider(logger, providers...) | ||
} | ||
return strings.TrimSpace(b.String()), nil | ||
} | ||
|
||
func ProviderOrDefault(name string) Provider { | ||
p := map[string]Provider{ | ||
SeepIPProvider: SeeIP, | ||
IpifyProvider: Ipify, | ||
MockIpProvider: MockIp, | ||
}[name] | ||
if p == nil { | ||
p = SeeIP | ||
} | ||
return p | ||
// ProviderOrDefault returns a provider with the provided name, or a default provider if the name is not recognized. | ||
// Provider strings are not case-sensitive. | ||
func ProviderOrDefault(logger logging.Logger, names ...string) Provider { | ||
provider := providerOrDefault(logger, names...) | ||
logger.Infof("Using IP provider '%s'", provider.Name()) | ||
return provider | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.