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 ( import (
"net" "net"
"oh-my-posh/environment" "oh-my-posh/environment"
"oh-my-posh/http"
"oh-my-posh/properties" "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 { type IPify struct {
props properties.Properties IP string
env environment.Environment
IP string api IPAPI
} }
const ( const (
@ -33,40 +51,21 @@ func (i *IPify) Enabled() bool {
} }
func (i *IPify) getResult() (string, error) { func (i *IPify) getResult() (string, error) {
cacheTimeout := i.props.GetInt(properties.CacheTimeout, properties.DefaultCacheTimeout) data, err := i.api.Get()
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)
if dnsErr, OK := err.(*net.DNSError); OK && dnsErr.IsNotFound { if dnsErr, OK := err.(*net.DNSError); OK && dnsErr.IsNotFound {
return OFFLINE, nil return OFFLINE, nil
} }
if err != nil { if err != nil {
return "", err return "", err
} }
return data.IP, 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
} }
func (i *IPify) Init(props properties.Properties, env environment.Environment) { func (i *IPify) Init(props properties.Properties, env environment.Environment) {
i.props = props request := &http.Request{}
i.env = env request.Init(env, props)
i.api = &ipAPI{
Request: *request,
}
} }

View file

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