refactor(ipify): use generic http request

This commit is contained in:
Jan De Dobbeleer 2022-08-05 21:08:03 +02:00 committed by Jan De Dobbeleer
parent cccb502989
commit 929e460c4e
2 changed files with 49 additions and 57 deletions

View file

@ -3,13 +3,31 @@ package segments
import (
"net"
"oh-my-posh/environment"
"oh-my-posh/http"
"oh-my-posh/properties"
)
type ipData struct {
IP string `json:"ip"`
}
type IPAPI interface {
Get() (*ipData, error)
}
type ipAPI struct {
http.Request
}
func (i *ipAPI) Get() (*ipData, error) {
url := "https://api.ipify.org?format=json"
return http.Do[*ipData](&i.Request, url)
}
type IPify struct {
props properties.Properties
env environment.Environment
IP string
IP string
api IPAPI
}
const (
@ -33,40 +51,21 @@ func (i *IPify) Enabled() bool {
}
func (i *IPify) getResult() (string, error) {
cacheTimeout := i.props.GetInt(properties.CacheTimeout, properties.DefaultCacheTimeout)
url := i.props.GetString(IpifyURL, "https://api.ipify.org")
if cacheTimeout > 0 {
// check if data stored in cache
val, found := i.env.Cache().Get(url)
// we got something from te cache
if found {
return val, nil
}
}
httpTimeout := i.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
body, err := i.env.HTTPRequest(url, nil, httpTimeout)
data, err := i.api.Get()
if dnsErr, OK := err.(*net.DNSError); OK && dnsErr.IsNotFound {
return OFFLINE, nil
}
if err != nil {
return "", err
}
// convert the body to a string
response := string(body)
if cacheTimeout > 0 {
// persist public ip in cache
i.env.Cache().Set(url, response, cacheTimeout)
}
return response, nil
return data.IP, err
}
func (i *IPify) Init(props properties.Properties, env environment.Environment) {
i.props = props
i.env = env
request := &http.Request{}
request.Init(env, props)
i.api = &ipAPI{
Request: *request,
}
}

View file

@ -4,42 +4,41 @@ import (
"errors"
"net"
"oh-my-posh/mock"
"oh-my-posh/properties"
"testing"
"github.com/stretchr/testify/assert"
mock2 "github.com/stretchr/testify/mock"
)
const (
IPIFYAPIURL = "https://api.ipify.org"
)
type mockedipAPI struct {
mock2.Mock
}
func (s *mockedipAPI) Get() (*ipData, error) {
args := s.Called()
return args.Get(0).(*ipData), args.Error(1)
}
func TestIpifySegment(t *testing.T) {
cases := []struct {
Case string
Response string
IPDate *ipData
Error error
ExpectedString string
ExpectedEnabled bool
Template string
Error error
}{
{
Case: "IPv4",
Response: `127.0.0.1`,
Case: "IP data",
IPDate: &ipData{IP: "127.0.0.1"},
ExpectedString: "127.0.0.1",
ExpectedEnabled: true,
},
{
Case: "IPv6 (with template)",
Response: `0000:aaaa:1111:bbbb:2222:cccc:3333:dddd`,
ExpectedString: "Ext. IP: 0000:aaaa:1111:bbbb:2222:cccc:3333:dddd",
ExpectedEnabled: true,
Template: "Ext. IP: {{.IP}}",
},
{
Case: "Network Error",
Response: "nonsense",
ExpectedString: "",
Case: "Error",
Error: errors.New("network is unreachable"),
ExpectedEnabled: false,
},
@ -52,26 +51,20 @@ func TestIpifySegment(t *testing.T) {
}
for _, tc := range cases {
env := &mock.MockedEnvironment{}
props := properties.Map{
properties.CacheTimeout: 0,
}
env.On("HTTPRequest", IPIFYAPIURL).Return([]byte(tc.Response), tc.Error)
api := &mockedipAPI{}
api.On("Get").Return(tc.IPDate, tc.Error)
ipify := &IPify{
props: props,
env: env,
api: api,
}
enabled := ipify.Enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
if !enabled {
continue
}
if tc.Template == "" {
tc.Template = ipify.Template()
}
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, ipify), tc.Case)
assert.Equal(t, tc.ExpectedString, renderTemplate(&mock.MockedEnvironment{}, ipify.Template(), ipify), tc.Case)
}
}