From 65f51cc1655ddcba47fce9984455d30d18609e50 Mon Sep 17 00:00:00 2001 From: Lisa Seelye Date: Thu, 17 Feb 2022 22:12:17 -0500 Subject: [PATCH] Apply upstream 63 Applying https://github.com/showwin/speedtest-go/pull/63 to test locally Signed-off-by: Lisa Seelye --- speedtest.go | 10 ++--- speedtest/server.go | 84 ++++++++++++++++++++++++++++------------ speedtest/server_test.go | 17 ++++---- 3 files changed, 73 insertions(+), 38 deletions(-) diff --git a/speedtest.go b/speedtest.go index 2cff6f1..ea55cbd 100644 --- a/speedtest.go +++ b/speedtest.go @@ -36,14 +36,14 @@ func main() { showUser(user) } - serverList, err := speedtest.FetchServerList(user) + servers, err := speedtest.FetchServers(user) checkError(err) if *showList { - showServerList(serverList) + showServerList(servers) return } - targets, err := serverList.FindServer(*serverIds) + targets, err := servers.FindServer(*serverIds) checkError(err) startTest(targets, *savingMode, *jsonOutput) @@ -140,8 +140,8 @@ func showUser(user *speedtest.User) { } } -func showServerList(serverList speedtest.ServerList) { - for _, s := range serverList.Servers { +func showServerList(servers speedtest.Servers) { + for _, s := range servers { fmt.Printf("[%4s] %8.2fkm ", s.ID, s.Distance) fmt.Printf(s.Name + " (" + s.Country + ") by " + s.Sponsor + "\n") } diff --git a/speedtest/server.go b/speedtest/server.go index bdfa730..1a7cc6d 100644 --- a/speedtest/server.go +++ b/speedtest/server.go @@ -2,6 +2,7 @@ package speedtest import ( "context" + "encoding/json" "encoding/xml" "errors" "fmt" @@ -12,9 +13,17 @@ import ( "time" ) -const speedTestServersUrl = "https://www.speedtest.net/speedtest-servers-static.php" +const speedTestServersUrl = "https://www.speedtest.net/api/js/servers?engine=js&limit=10" const speedTestServersAlternativeUrl = "https://www.speedtest.net/speedtest-servers-static.php" +type PayloadType int + +const ( + JSONPayload PayloadType = iota + XMLPayload +) + + // Server information type Server struct { URL string `xml:"url,attr" json:"url"` @@ -60,50 +69,68 @@ func (b ByDistance) Less(i, j int) bool { return b.Servers[i].Distance < b.Servers[j].Distance } -// FetchServerList retrieves a list of available servers -func FetchServerList(user *User) (ServerList, error) { +// FetchServers retrieves a list of available servers +func FetchServers(user *User) (Servers, error) { return FetchServerListContext(context.Background(), user) } // FetchServerListContext retrieves a list of available servers, observing the given context. -func FetchServerListContext(ctx context.Context, user *User) (ServerList, error) { +func FetchServerListContext(ctx context.Context, user *User) (Servers, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, speedTestServersUrl, nil) if err != nil { - return ServerList{}, err + return Servers{}, err } resp, err := http.DefaultClient.Do(req) if err != nil { - return ServerList{}, err + return Servers{}, err } + payloadType := JSONPayload + if resp.ContentLength == 0 { resp.Body.Close() req, err = http.NewRequestWithContext(ctx, http.MethodGet, speedTestServersAlternativeUrl, nil) if err != nil { - return ServerList{}, err + return Servers{}, err } resp, err = http.DefaultClient.Do(req) if err != nil { - return ServerList{}, err + return Servers{}, err } + + payloadType = XMLPayload } defer resp.Body.Close() - // Decode xml - decoder := xml.NewDecoder(resp.Body) + var servers Servers + + switch payloadType { + case JSONPayload: + // Decode xml + decoder := json.NewDecoder(resp.Body) + + if err := decoder.Decode(&servers); err != nil { + return servers, err + } + case XMLPayload: + var list ServerList + // Decode xml + decoder := xml.NewDecoder(resp.Body) - var list ServerList - if err := decoder.Decode(&list); err != nil { - return list, err + if err := decoder.Decode(&list); err != nil { + return servers, err + } + servers = list.Servers + default: + return servers, fmt.Errorf("response payload decoding not implemented") } // Calculate distance - for i := range list.Servers { - server := list.Servers[i] + for _, server := range servers { sLat, _ := strconv.ParseFloat(server.Lat, 64) sLon, _ := strconv.ParseFloat(server.Lon, 64) uLat, _ := strconv.ParseFloat(user.Lat, 64) @@ -112,13 +139,13 @@ func FetchServerListContext(ctx context.Context, user *User) (ServerList, error) } // Sort by distance - sort.Sort(ByDistance{list.Servers}) + sort.Sort(ByDistance{servers}) - if len(list.Servers) <= 0 { - return list, errors.New("unable to retrieve server list") + if len(servers) <= 0 { + return servers, errors.New("unable to retrieve server list") } - return list, nil + return servers, nil } func distance(lat1 float64, lon1 float64, lat2 float64, lon2 float64) float64 { @@ -134,15 +161,15 @@ func distance(lat1 float64, lon1 float64, lat2 float64, lon2 float64) float64 { } // FindServer finds server by serverID -func (l *ServerList) FindServer(serverID []int) (Servers, error) { +func (l Servers) FindServer(serverID []int) (Servers, error) { servers := Servers{} - if len(l.Servers) <= 0 { + if len(l) <= 0 { return servers, errors.New("no servers available") } for _, sid := range serverID { - for _, s := range l.Servers { + for _, s := range l { id, _ := strconv.Atoi(s.ID) if sid == id { servers = append(servers, s) @@ -151,14 +178,14 @@ func (l *ServerList) FindServer(serverID []int) (Servers, error) { } if len(servers) == 0 { - servers = append(servers, l.Servers[0]) + servers = append(servers, l[0]) } return servers, nil } // String representation of ServerList -func (l *ServerList) String() string { +func (l ServerList) String() string { slr := "" for _, s := range l.Servers { slr += s.String() @@ -166,6 +193,15 @@ func (l *ServerList) String() string { return slr } +// String representation of Servers +func (l Servers) String() string { + slr := "" + for _, s := range l { + slr += s.String() + } + return slr +} + // String representation of Server func (s *Server) String() string { return fmt.Sprintf("[%4s] %8.2fkm \n%s (%s) by %s\n", s.ID, s.Distance, s.Name, s.Country, s.Sponsor) diff --git a/speedtest/server_test.go b/speedtest/server_test.go index 6537682..f8f44d3 100644 --- a/speedtest/server_test.go +++ b/speedtest/server_test.go @@ -9,15 +9,15 @@ func TestFetchServerList(t *testing.T) { Lon: "138.44", Isp: "Hello", } - serverList, err := FetchServerList(&user) + servers, err := FetchServers(&user) if err != nil { t.Errorf(err.Error()) } - if len(serverList.Servers) == 0 { + if len(servers) == 0 { t.Errorf("Failed to fetch server list.") } - if len(serverList.Servers[0].Country) == 0 { - t.Errorf("got unexpected country name '%v'", serverList.Servers[0].Country) + if len(servers[0].Country) == 0 { + t.Errorf("got unexpected country name '%v'", servers[0].Country) } } @@ -45,7 +45,7 @@ func TestDistance(t *testing.T) { } func TestFindServer(t *testing.T) { - servers := []*Server{ + servers := Servers{ &Server{ ID: "1", }, @@ -56,10 +56,9 @@ func TestFindServer(t *testing.T) { ID: "3", }, } - serverList := ServerList{Servers: servers} serverID := []int{} - s, err := serverList.FindServer(serverID) + s, err := servers.FindServer(serverID) if err != nil { t.Errorf(err.Error()) } @@ -71,7 +70,7 @@ func TestFindServer(t *testing.T) { } serverID = []int{2} - s, err = serverList.FindServer(serverID) + s, err = servers.FindServer(serverID) if err != nil { t.Errorf(err.Error()) } @@ -83,7 +82,7 @@ func TestFindServer(t *testing.T) { } serverID = []int{3, 1} - s, err = serverList.FindServer(serverID) + s, err = servers.FindServer(serverID) if err != nil { t.Errorf(err.Error()) }