Skip to content

Commit

Permalink
use /api/js endpoint as new primary endpoint for server list fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
redradrat committed Nov 26, 2021
1 parent a83af84 commit 83b44c5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 29 deletions.
10 changes: 5 additions & 5 deletions speedtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
}
Expand Down
73 changes: 50 additions & 23 deletions speedtest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package speedtest

import (
"context"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
Expand All @@ -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"`
Expand Down Expand Up @@ -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

var list ServerList
if err := decoder.Decode(&list); err != nil {
return list, err
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)

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)
Expand All @@ -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 {
Expand All @@ -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)
Expand All @@ -151,7 +178,7 @@ 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
Expand Down
2 changes: 1 addition & 1 deletion speedtest/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ func TestFetchServerList(t *testing.T) {
Lon: "138.44",
Isp: "Hello",
}
serverList, err := FetchServerList(&user)
serverList, err := FetchServers(&user)
if err != nil {
t.Errorf(err.Error())
}
Expand Down

0 comments on commit 83b44c5

Please sign in to comment.