fix
This commit is contained in:
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Launch Package",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"args": ["sync"],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"program": "${workspaceFolder}/cmd/cli"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
|
"github.com/schollz/progressbar/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -37,15 +38,22 @@ func (p *RunCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
|
|||||||
return subcommands.ExitFailure
|
return subcommands.ExitFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pg := progressbar.New(len(datastore))
|
||||||
|
defer pg.Close()
|
||||||
|
|
||||||
for _, metadata := range datastore {
|
for _, metadata := range datastore {
|
||||||
|
pg.Describe("Scanning " + metadata.Name + "...")
|
||||||
metadataPath := filepath.Join(game.DatastorePath(), metadata.ID)
|
metadataPath := filepath.Join(game.DatastorePath(), metadata.ID)
|
||||||
err := archiveIfChanged(metadata.ID, metadata.Path, filepath.Join(metadataPath, "data.tar.gz"), filepath.Join(metadataPath, ".last_run"))
|
err := archiveIfChanged(metadata.ID, metadata.Path, filepath.Join(metadataPath, "data.tar.gz"), filepath.Join(metadataPath, ".last_run"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error: cannot process the data of %s: %s\n", metadata.ID, err)
|
fmt.Fprintf(os.Stderr, "error: cannot process the data of %s: %s\n", metadata.ID, err)
|
||||||
return subcommands.ExitFailure
|
return subcommands.ExitFailure
|
||||||
}
|
}
|
||||||
|
pg.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pg.Finish()
|
||||||
|
|
||||||
return subcommands.ExitSuccess
|
return subcommands.ExitSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +149,5 @@ func archiveIfChanged(id, srcDir, destTarGz, stateFile string) error {
|
|||||||
return fmt.Errorf("updating state file: %w", err)
|
return fmt.Errorf("updating state file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(id)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hremote, _ := client.Hash(r.GameID)
|
hremote, err := client.Hash(r.GameID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "error: failed to get the file hash from the remote:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
vlocal, err := game.Version(r.GameID)
|
vlocal, err := game.Version(r.GameID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -77,18 +81,21 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
vremote, _ := client.Version(r.GameID)
|
vremote, err := client.Version(r.GameID)
|
||||||
|
if err != nil {
|
||||||
if hlocal == hremote {
|
fmt.Fprintln(os.Stderr, "error: failed to get the file version from the remote:", err)
|
||||||
fmt.Println("already up-to-date")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if vremote == 0 {
|
if hlocal == hremote {
|
||||||
if err := push(r.GameID, m, client); err != nil {
|
if vlocal != vremote {
|
||||||
fmt.Fprintln(os.Stderr, "failed to push:", err)
|
slog.Debug("version is not the same, but the hash is equal. Updating local database")
|
||||||
return subcommands.ExitFailure
|
if err := game.SetVersion(r.GameID, vremote); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "error: failed to synchronize version number:", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("already up-to-date")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +108,14 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
|
|||||||
}
|
}
|
||||||
|
|
||||||
if vlocal < vremote {
|
if vlocal < vremote {
|
||||||
fmt.Println("pull")
|
if err := push(r.GameID, m, client); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "failed to push:", err)
|
||||||
|
return subcommands.ExitFailure
|
||||||
|
}
|
||||||
|
if err := game.SetVersion(r.GameID, vremote); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "error: failed to synchronize version number:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +123,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
|
|||||||
fmt.Println("conflict")
|
fmt.Println("conflict")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return subcommands.ExitSuccess
|
return subcommands.ExitSuccess
|
||||||
@@ -119,3 +134,9 @@ func push(gameID string, m game.Metadata, cli *client.Client) error {
|
|||||||
|
|
||||||
return cli.Push(gameID, archivePath, m)
|
return cli.Push(gameID, archivePath, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pull(gameID string, cli *client.Client) error {
|
||||||
|
archivePath := filepath.Join(game.DatastorePath(), gameID, "data.tar.gz")
|
||||||
|
|
||||||
|
return cli.Pull(gameID, archivePath)
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"cloudsave/cmd/cli/commands/version"
|
"cloudsave/cmd/cli/commands/version"
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
@@ -31,5 +32,9 @@ func main() {
|
|||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
os.Exit(int(subcommands.Execute(ctx)))
|
|
||||||
|
exitCode := subcommands.Execute(ctx)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
os.Exit(int(exitCode))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"cloudsave/cmd/server/data"
|
"cloudsave/cmd/server/data"
|
||||||
"cloudsave/pkg/game"
|
"cloudsave/pkg/game"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -227,7 +228,7 @@ func (s HTTPServer) hash(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Get checksum result
|
// Get checksum result
|
||||||
sum := hasher.Sum(nil)
|
sum := hasher.Sum(nil)
|
||||||
ok(sum, w, r)
|
ok(hex.EncodeToString(sum), w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s HTTPServer) version(w http.ResponseWriter, r *http.Request) {
|
func (s HTTPServer) version(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -269,7 +270,7 @@ func (s HTTPServer) version(w http.ResponseWriter, r *http.Request) {
|
|||||||
func parseFormMetadata(gameID string, values map[string][]string) (game.Metadata, error) {
|
func parseFormMetadata(gameID string, values map[string][]string) (game.Metadata, error) {
|
||||||
var name string
|
var name string
|
||||||
if v, ok := values["name"]; ok {
|
if v, ok := values["name"]; ok {
|
||||||
if len(v) != 0 {
|
if len(v) == 0 {
|
||||||
return game.Metadata{}, fmt.Errorf("error: corrupted metadata")
|
return game.Metadata{}, fmt.Errorf("error: corrupted metadata")
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -280,7 +281,7 @@ func parseFormMetadata(gameID string, values map[string][]string) (game.Metadata
|
|||||||
|
|
||||||
var version int
|
var version int
|
||||||
if v, ok := values["version"]; ok {
|
if v, ok := values["version"]; ok {
|
||||||
if len(v) != 0 {
|
if len(v) == 0 {
|
||||||
return game.Metadata{}, fmt.Errorf("error: corrupted metadata")
|
return game.Metadata{}, fmt.Errorf("error: corrupted metadata")
|
||||||
}
|
}
|
||||||
if v, err := strconv.Atoi(v[0]); err == nil {
|
if v, err := strconv.Atoi(v[0]); err == nil {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func Write(gameID, documentRoot string, r io.Reader) error {
|
|||||||
partPath := filepath.Join(dataFolderPath, "data.tar.gz.part")
|
partPath := filepath.Join(dataFolderPath, "data.tar.gz.part")
|
||||||
finalFilePath := filepath.Join(dataFolderPath, "data.tar.gz")
|
finalFilePath := filepath.Join(dataFolderPath, "data.tar.gz")
|
||||||
|
|
||||||
if err := os.MkdirAll(dataFolderPath, 0740); err != nil {
|
if err := makeDataFolder(gameID, documentRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +40,9 @@ func Write(gameID, documentRoot string, r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateMetadata(gameID, documentRoot string, m game.Metadata) error {
|
func UpdateMetadata(gameID, documentRoot string, m game.Metadata) error {
|
||||||
|
if err := makeDataFolder(gameID, documentRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
path := filepath.Join(documentRoot, "data", gameID, "metadata.json")
|
path := filepath.Join(documentRoot, "data", gameID, "metadata.json")
|
||||||
|
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0740)
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0740)
|
||||||
@@ -51,3 +54,7 @@ func UpdateMetadata(gameID, documentRoot string, m game.Metadata) error {
|
|||||||
e := json.NewEncoder(f)
|
e := json.NewEncoder(f)
|
||||||
return e.Encode(m)
|
return e.Encode(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeDataFolder(gameID, documentRoot string) error {
|
||||||
|
return os.MkdirAll(filepath.Join(documentRoot, "data", gameID), 0740)
|
||||||
|
}
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -5,8 +5,13 @@ go 1.24
|
|||||||
require (
|
require (
|
||||||
github.com/go-chi/chi/v5 v5.2.1
|
github.com/go-chi/chi/v5 v5.2.1
|
||||||
github.com/google/subcommands v1.2.0
|
github.com/google/subcommands v1.2.0
|
||||||
|
github.com/schollz/progressbar/v3 v3.18.0
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.38.0
|
||||||
golang.org/x/term v0.32.0
|
golang.org/x/term v0.32.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.33.0 // indirect
|
require (
|
||||||
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -1,10 +1,28 @@
|
|||||||
|
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
|
||||||
|
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||||
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
|
||||||
|
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (c *Client) Hash(gameID string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if h, ok := (o).(string); ok {
|
if h, ok := (o.Data).(string); ok {
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ func (c *Client) Version(gameID string) (int, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if h, ok := (o).(int); ok {
|
if h, ok := (o.Data).(float64); ok {
|
||||||
return h, nil
|
return int(h), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, errors.New("invalid payload sent by the server")
|
return 0, errors.New("invalid payload sent by the server")
|
||||||
@@ -121,6 +121,48 @@ func (c *Client) Push(gameID, archivePath string, m game.Metadata) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Pull(gameID, archivePath string) error {
|
||||||
|
u, err := url.JoinPath(c.baseURL, "api", "v1", "games", gameID, "data")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cli := http.Client{}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetBasicAuth(c.username, c.password)
|
||||||
|
|
||||||
|
f, err := os.OpenFile(archivePath+".part", os.O_CREATE|os.O_WRONLY, 0740)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open file: %w", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
res, err := cli.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot connect to remote: %w", err)
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("cannot connect to remote: server return code: %s", res.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(f, req.Body); err != nil {
|
||||||
|
return fmt.Errorf("an error occured while copying the file from the remote: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Rename(archivePath+".part", archivePath); err != nil {
|
||||||
|
return fmt.Errorf("failed to move temporary data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) Ping() bool {
|
func (c *Client) Ping() bool {
|
||||||
cli := http.Client{}
|
cli := http.Client{}
|
||||||
|
|
||||||
@@ -152,31 +194,31 @@ func (c *Client) Ping() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) get(url string) (any, error) {
|
func (c *Client) get(url string) (obj.HTTPObject, error) {
|
||||||
cli := http.Client{}
|
cli := http.Client{}
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return obj.HTTPObject{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req.SetBasicAuth(c.username, c.password)
|
req.SetBasicAuth(c.username, c.password)
|
||||||
|
|
||||||
res, err := cli.Do(req)
|
res, err := cli.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return obj.HTTPObject{}, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
if res.StatusCode != 200 {
|
if res.StatusCode != 200 {
|
||||||
return nil, fmt.Errorf("server returns an unexpected status code: %d %s (expected 200)", res.StatusCode, res.Status)
|
return obj.HTTPObject{}, fmt.Errorf("server returns an unexpected status code: %d %s (expected 200)", res.StatusCode, res.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpObject obj.HTTPObject
|
var httpObject obj.HTTPObject
|
||||||
d := json.NewDecoder(res.Body)
|
d := json.NewDecoder(res.Body)
|
||||||
err = d.Decode(&httpObject)
|
err = d.Decode(&httpObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return obj.HTTPObject{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpObject, nil
|
return httpObject, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user