Maintenance: use native HTTP client for updater
This commit is contained in:
8
internal/updater/errors.go
Normal file
8
internal/updater/errors.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package updater
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrHTTPStatusCodeNotOK = errors.New("HTTP status code not OK")
|
||||||
|
ErrUnmarshalResponseBody = errors.New("cannot unmarshal response body")
|
||||||
|
)
|
||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateMullvad(ctx context.Context) (err error) {
|
func (u *updater) updateMullvad(ctx context.Context) (err error) {
|
||||||
@@ -26,15 +25,25 @@ func (u *updater) updateMullvad(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findMullvadServers(ctx context.Context, client network.Client) (servers []models.MullvadServer, err error) {
|
func findMullvadServers(ctx context.Context, client *http.Client) (servers []models.MullvadServer, err error) {
|
||||||
const url = "https://api.mullvad.net/www/relays/openvpn/"
|
const url = "https://api.mullvad.net/www/relays/openvpn/"
|
||||||
bytes, status, err := client.Get(ctx, url)
|
|
||||||
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if status != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("HTTP status code %d", status)
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("%w: %s for %s", ErrHTTPStatusCodeNotOK, response.Status, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(response.Body)
|
||||||
var data []struct {
|
var data []struct {
|
||||||
Country string `json:"country_name"`
|
Country string `json:"country_name"`
|
||||||
City string `json:"city_name"`
|
City string `json:"city_name"`
|
||||||
@@ -44,9 +53,14 @@ func findMullvadServers(ctx context.Context, client network.Client) (servers []m
|
|||||||
IPv4 string `json:"ipv4_addr_in"`
|
IPv4 string `json:"ipv4_addr_in"`
|
||||||
IPv6 string `json:"ipv6_addr_in"`
|
IPv6 string `json:"ipv6_addr_in"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(bytes, &data); err != nil {
|
if err := decoder.Decode(&data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
serversByKey := map[string]models.MullvadServer{}
|
serversByKey := map[string]models.MullvadServer{}
|
||||||
for _, jsonServer := range data {
|
for _, jsonServer := range data {
|
||||||
if !jsonServer.Active {
|
if !jsonServer.Active {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateNordvpn(ctx context.Context) (err error) {
|
func (u *updater) updateNordvpn(ctx context.Context) (err error) {
|
||||||
@@ -38,16 +37,26 @@ var (
|
|||||||
ErrInvalidIDInServerName = errors.New("invalid ID in server name")
|
ErrInvalidIDInServerName = errors.New("invalid ID in server name")
|
||||||
)
|
)
|
||||||
|
|
||||||
func findNordvpnServers(ctx context.Context, client network.Client) (
|
func findNordvpnServers(ctx context.Context, client *http.Client) (
|
||||||
servers []models.NordvpnServer, warnings []string, err error) {
|
servers []models.NordvpnServer, warnings []string, err error) {
|
||||||
const url = "https://nordvpn.com/api/server"
|
const url = "https://nordvpn.com/api/server"
|
||||||
bytes, status, err := client.Get(ctx, url)
|
|
||||||
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if status != http.StatusOK {
|
|
||||||
return nil, nil, fmt.Errorf("HTTP status code %d", status)
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, nil, fmt.Errorf("%w: %s for %s", ErrHTTPStatusCodeNotOK, response.Status, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(response.Body)
|
||||||
var data []struct {
|
var data []struct {
|
||||||
IPAddress string `json:"ip_address"`
|
IPAddress string `json:"ip_address"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -57,9 +66,14 @@ func findNordvpnServers(ctx context.Context, client network.Client) (
|
|||||||
TCP bool `json:"openvpn_tcp"`
|
TCP bool `json:"openvpn_tcp"`
|
||||||
} `json:"features"`
|
} `json:"features"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(bytes, &data); err != nil {
|
if err := decoder.Decode(&data); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
sort.Slice(data, func(i, j int) bool {
|
sort.Slice(data, func(i, j int) bool {
|
||||||
if data[i].Country == data[j].Country {
|
if data[i].Country == data[j].Country {
|
||||||
return data[i].Name < data[j].Name
|
return data[i].Name < data[j].Name
|
||||||
|
|||||||
@@ -5,22 +5,39 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updatePIA(ctx context.Context) (err error) {
|
func (u *updater) updatePIA(ctx context.Context) (err error) {
|
||||||
const url = "https://serverlist.piaservers.net/vpninfo/servers/v5"
|
const url = "https://serverlist.piaservers.net/vpninfo/servers/v5"
|
||||||
b, status, err := u.client.Get(ctx, url)
|
|
||||||
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if status != http.StatusOK {
|
|
||||||
return fmt.Errorf("HTTP status code %d: %s", status, strings.ReplaceAll(string(b), "\n", ""))
|
response, err := u.client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("%w: %s for %s", ErrHTTPStatusCodeNotOK, response.Status, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove key/signature at the bottom
|
// remove key/signature at the bottom
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updatePrivado(ctx context.Context) (err error) {
|
func (u *updater) updatePrivado(ctx context.Context) (err error) {
|
||||||
@@ -27,7 +27,7 @@ func (u *updater) updatePrivado(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findPrivadoServersFromZip(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
|
func findPrivadoServersFromZip(ctx context.Context, client *http.Client, lookupIP lookupIPFunc) (
|
||||||
servers []models.PrivadoServer, warnings []string, err error) {
|
servers []models.PrivadoServer, warnings []string, err error) {
|
||||||
const zipURL = "https://privado.io/apps/ovpn_configs.zip"
|
const zipURL = "https://privado.io/apps/ovpn_configs.zip"
|
||||||
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/publicip"
|
"github.com/qdm12/gluetun/internal/publicip"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updatePurevpn(ctx context.Context) (err error) {
|
func (u *updater) updatePurevpn(ctx context.Context) (err error) {
|
||||||
@@ -31,7 +30,7 @@ func (u *updater) updatePurevpn(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findPurevpnServers(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
|
func findPurevpnServers(ctx context.Context, client *http.Client, lookupIP lookupIPFunc) (
|
||||||
servers []models.PurevpnServer, warnings []string, err error) {
|
servers []models.PurevpnServer, warnings []string, err error) {
|
||||||
const zipURL = "https://s3-us-west-1.amazonaws.com/heartbleed/windows/New+OVPN+Files.zip"
|
const zipURL = "https://s3-us-west-1.amazonaws.com/heartbleed/windows/New+OVPN+Files.zip"
|
||||||
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
||||||
@@ -70,10 +69,7 @@ func findPurevpnServers(ctx context.Context, client network.Client, lookupIP loo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove once we move away from network.Client
|
country, region, city, err := publicip.Info(ctx, client, IPs[0])
|
||||||
const httpTimeout = 3 * time.Second
|
|
||||||
httpClient := &http.Client{Timeout: httpTimeout}
|
|
||||||
country, region, city, err := publicip.Info(ctx, httpClient, IPs[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateSurfshark(ctx context.Context) (err error) {
|
func (u *updater) updateSurfshark(ctx context.Context) (err error) {
|
||||||
@@ -32,21 +31,36 @@ func (u *updater) updateSurfshark(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:deadcode,unused
|
//nolint:deadcode,unused
|
||||||
func findSurfsharkServersFromAPI(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
|
func findSurfsharkServersFromAPI(ctx context.Context, client *http.Client, lookupIP lookupIPFunc) (
|
||||||
servers []models.SurfsharkServer, warnings []string, err error) {
|
servers []models.SurfsharkServer, warnings []string, err error) {
|
||||||
const url = "https://my.surfshark.com/vpn/api/v4/server/clusters"
|
const url = "https://my.surfshark.com/vpn/api/v4/server/clusters"
|
||||||
b, status, err := client.Get(ctx, url)
|
|
||||||
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
} else if status != http.StatusOK {
|
|
||||||
return nil, nil, fmt.Errorf("HTTP status code %d", status)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, nil, fmt.Errorf("%w: %s for %s", ErrHTTPStatusCodeNotOK, response.Status, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(response.Body)
|
||||||
var jsonServers []struct {
|
var jsonServers []struct {
|
||||||
Host string `json:"connectionName"`
|
Host string `json:"connectionName"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(b, &jsonServers); err != nil {
|
if err := decoder.Decode(&jsonServers); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +94,7 @@ func findSurfsharkServersFromAPI(ctx context.Context, client network.Client, loo
|
|||||||
return servers, warnings, nil
|
return servers, warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findSurfsharkServersFromZip(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
|
func findSurfsharkServersFromZip(ctx context.Context, client *http.Client, lookupIP lookupIPFunc) (
|
||||||
servers []models.SurfsharkServer, warnings []string, err error) {
|
servers []models.SurfsharkServer, warnings []string, err error) {
|
||||||
const zipURL = "https://my.surfshark.com/vpn/api/v1/server/configurations"
|
const zipURL = "https://my.surfshark.com/vpn/api/v1/server/configurations"
|
||||||
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateTorguard(ctx context.Context) (err error) {
|
func (u *updater) updateTorguard(ctx context.Context) (err error) {
|
||||||
@@ -30,7 +30,7 @@ func (u *updater) updateTorguard(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findTorguardServersFromZip(ctx context.Context, client network.Client) (
|
func findTorguardServersFromZip(ctx context.Context, client *http.Client) (
|
||||||
servers []models.TorguardServer, warnings []string, err error) {
|
servers []models.TorguardServer, warnings []string, err error) {
|
||||||
// Note: all servers do both TCP and UDP
|
// Note: all servers do both TCP and UDP
|
||||||
const zipURL = "https://torguard.net/downloads/OpenVPN-TCP-Linux.zip"
|
const zipURL = "https://torguard.net/downloads/OpenVPN-TCP-Linux.zip"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/configuration"
|
"github.com/qdm12/gluetun/internal/configuration"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/logging"
|
"github.com/qdm12/golibs/logging"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Updater interface {
|
type Updater interface {
|
||||||
@@ -29,7 +28,7 @@ type updater struct {
|
|||||||
timeNow func() time.Time
|
timeNow func() time.Time
|
||||||
println func(s string)
|
println func(s string)
|
||||||
lookupIP lookupIPFunc
|
lookupIP lookupIPFunc
|
||||||
client network.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(settings configuration.Updater, httpClient *http.Client,
|
func New(settings configuration.Updater, httpClient *http.Client,
|
||||||
@@ -38,13 +37,12 @@ func New(settings configuration.Updater, httpClient *http.Client,
|
|||||||
settings.DNSAddress = "1.1.1.1"
|
settings.DNSAddress = "1.1.1.1"
|
||||||
}
|
}
|
||||||
resolver := newResolver(settings.DNSAddress)
|
resolver := newResolver(settings.DNSAddress)
|
||||||
const clientTimeout = 10 * time.Second
|
|
||||||
return &updater{
|
return &updater{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
timeNow: time.Now,
|
timeNow: time.Now,
|
||||||
println: func(s string) { fmt.Println(s) },
|
println: func(s string) { fmt.Println(s) },
|
||||||
lookupIP: newLookupIP(resolver),
|
lookupIP: newLookupIP(resolver),
|
||||||
client: network.NewClient(clientTimeout),
|
client: httpClient,
|
||||||
options: settings,
|
options: settings,
|
||||||
servers: currentServers,
|
servers: currentServers,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateVyprvpn(ctx context.Context) (err error) {
|
func (u *updater) updateVyprvpn(ctx context.Context) (err error) {
|
||||||
@@ -28,7 +28,7 @@ func (u *updater) updateVyprvpn(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findVyprvpnServers(ctx context.Context, client network.Client, lookupIP lookupIPFunc) (
|
func findVyprvpnServers(ctx context.Context, client *http.Client, lookupIP lookupIPFunc) (
|
||||||
servers []models.VyprvpnServer, warnings []string, err error) {
|
servers []models.VyprvpnServer, warnings []string, err error) {
|
||||||
const zipURL = "https://support.vyprvpn.com/hc/article_attachments/360052617332/Vypr_OpenVPN_20200320.zip"
|
const zipURL = "https://support.vyprvpn.com/hc/article_attachments/360052617332/Vypr_OpenVPN_20200320.zip"
|
||||||
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
contents, err := fetchAndExtractFiles(ctx, client, zipURL)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
||||||
@@ -26,16 +25,27 @@ func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findWindscribeServers(ctx context.Context, client network.Client) (servers []models.WindscribeServer, err error) {
|
func findWindscribeServers(ctx context.Context, client *http.Client) (servers []models.WindscribeServer, err error) {
|
||||||
const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/"
|
const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/"
|
||||||
cacheBreaker := time.Now().Unix()
|
cacheBreaker := time.Now().Unix()
|
||||||
url := fmt.Sprintf("%s%d", baseURL, cacheBreaker)
|
url := fmt.Sprintf("%s%d", baseURL, cacheBreaker)
|
||||||
content, status, err := client.Get(ctx, url)
|
|
||||||
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if status != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf(http.StatusText(status))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrHTTPStatusCodeNotOK, response.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(response.Body)
|
||||||
var jsonData struct {
|
var jsonData struct {
|
||||||
Data []struct {
|
Data []struct {
|
||||||
Region string `json:"name"`
|
Region string `json:"name"`
|
||||||
@@ -48,9 +58,14 @@ func findWindscribeServers(ctx context.Context, client network.Client) (servers
|
|||||||
} `json:"groups"`
|
} `json:"groups"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(content, &jsonData); err != nil {
|
if err := decoder.Decode(&jsonData); err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrUnmarshalResponseBody, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, regionBlock := range jsonData.Data {
|
for _, regionBlock := range jsonData.Data {
|
||||||
region := regionBlock.Region
|
region := regionBlock.Region
|
||||||
for _, group := range regionBlock.Groups {
|
for _, group := range regionBlock.Groups {
|
||||||
|
|||||||
@@ -4,31 +4,42 @@ import (
|
|||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/golibs/network"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func fetchAndExtractFiles(ctx context.Context, client *http.Client, urls ...string) (
|
||||||
ErrBadStatusCode = errors.New("bad HTTP status code")
|
|
||||||
)
|
|
||||||
|
|
||||||
func fetchAndExtractFiles(ctx context.Context, client network.Client, urls ...string) (
|
|
||||||
contents map[string][]byte, err error) {
|
contents map[string][]byte, err error) {
|
||||||
contents = make(map[string][]byte)
|
contents = make(map[string][]byte)
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
zipBytes, status, err := client.Get(ctx, url)
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if status != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("%w: fetching url %s: %d", ErrBadStatusCode, url, status)
|
|
||||||
}
|
}
|
||||||
newContents, err := zipExtractAll(zipBytes)
|
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("%w: %s for %s", ErrHTTPStatusCodeNotOK, response.Status, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := response.Body.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newContents, err := zipExtractAll(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user