factor error and cleanup
This commit is contained in:
parent
fff782569f
commit
2d1fdc1314
18
cmd/photos-api-cli/error.go
Normal file
18
cmd/photos-api-cli/error.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResponseError struct {
|
||||||
|
Err string `json:"error"`
|
||||||
|
Details []string `json:"details"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ResponseError) Error() string {
|
||||||
|
if len(u.Details) == 0 {
|
||||||
|
return u.Err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s: \n - %s", u.Err, strings.Join(u.Details, "\n - "))
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
@ -18,10 +17,6 @@ type LoginRequest struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoginError struct {
|
|
||||||
Error string
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoginResponse struct {
|
type LoginResponse struct {
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
@ -35,16 +30,16 @@ func (c *LoginCommand) Execute(args []string) error {
|
|||||||
R().
|
R().
|
||||||
SetBody(&LoginRequest{c.Login, c.Password}).
|
SetBody(&LoginRequest{c.Login, c.Password}).
|
||||||
SetResult(&LoginResponse{}).
|
SetResult(&LoginResponse{}).
|
||||||
SetError(&LoginError{}).
|
SetError(&ResponseError{}).
|
||||||
Post("/account/login")
|
Post("/account/login")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := resp.Error().(*LoginError); ok {
|
if resp.IsError() {
|
||||||
logger.Printf("Login failed!")
|
logger.Printf("Login failed!")
|
||||||
return errors.New(err.Error)
|
return resp.Error().(*ResponseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("Login succeed!")
|
logger.Println("Login succeed!")
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,13 +15,6 @@ type RegisterRequest struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegisterResponse struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegisterError struct {
|
|
||||||
Error string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RegisterCommand) Execute(args []string) error {
|
func (c *RegisterCommand) Execute(args []string) error {
|
||||||
logger.Printf("Registering on %s...\n", c.Url)
|
logger.Printf("Registering on %s...\n", c.Url)
|
||||||
|
|
||||||
@ -31,18 +22,17 @@ func (c *RegisterCommand) Execute(args []string) error {
|
|||||||
|
|
||||||
resp, err := cli.
|
resp, err := cli.
|
||||||
R().
|
R().
|
||||||
|
SetError(&ResponseError{}).
|
||||||
SetBody(&RegisterRequest{c.Login, c.Password}).
|
SetBody(&RegisterRequest{c.Login, c.Password}).
|
||||||
SetResult(&RegisterResponse{}).
|
|
||||||
SetError(&RegisterError{}).
|
|
||||||
Post("/account/signup")
|
Post("/account/signup")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := resp.Error().(*RegisterError); ok {
|
if resp.IsError() {
|
||||||
logger.Println("Registering failed!")
|
logger.Println("Registering failed!")
|
||||||
return errors.New(err.Error)
|
return resp.Error().(*ResponseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("Registering succeed!")
|
logger.Println("Registering succeed!")
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
"github.com/schollz/progressbar/v3"
|
"github.com/schollz/progressbar/v3"
|
||||||
@ -24,18 +20,6 @@ type UploadCommand struct {
|
|||||||
Workers uint32 `short:"w" long:"workers" description:"Number of workers for uploading chunks" default:"4"`
|
Workers uint32 `short:"w" long:"workers" description:"Number of workers for uploading chunks" default:"4"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UploadError struct {
|
|
||||||
Err string `json:"error"`
|
|
||||||
Details []string `json:"details"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UploadError) Error() string {
|
|
||||||
if len(u.Details) == 0 {
|
|
||||||
return u.Err
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s: \n - %s", u.Err, strings.Join(u.Details, "\n - "))
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadCreate struct {
|
type UploadCreate struct {
|
||||||
UploadId string `json:"upload_id"`
|
UploadId string `json:"upload_id"`
|
||||||
}
|
}
|
||||||
@ -47,171 +31,19 @@ type UploadPartResult struct {
|
|||||||
PartSha256 string `json:"sha256"`
|
PartSha256 string `json:"sha256"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UploadCompleteRequest struct {
|
|
||||||
Sha256 string `json:"sha256" binding:"required,sha256"`
|
|
||||||
Name string `json:"name" binding:"required"`
|
|
||||||
Parts uint `json:"parts" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadFileRequest struct {
|
|
||||||
Name string
|
|
||||||
Checksum string
|
|
||||||
Chunks []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type UploadFileResponse struct {
|
|
||||||
Sum string
|
|
||||||
NbChunks uint32
|
|
||||||
Size uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UploadCommand) Cli() *resty.Client {
|
func (c *UploadCommand) Cli() *resty.Client {
|
||||||
return resty.New().SetBaseURL(c.Url).SetAuthScheme("Private").SetAuthToken(c.Token)
|
return resty.New().SetBaseURL(c.Url).SetAuthScheme("Private").SetAuthToken(c.Token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UploadCommand) FileExists() (string, error) {
|
|
||||||
f, err := os.Open(c.File)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
st, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
progress := progressbar.DefaultBytes(st.Size(), fmt.Sprintf("Checking %s", filepath.Base(c.File)))
|
|
||||||
defer progress.Close()
|
|
||||||
tee := io.TeeReader(f, progress)
|
|
||||||
checksum := sha1.New()
|
|
||||||
io.Copy(checksum, tee)
|
|
||||||
sum := hex.EncodeToString(checksum.Sum(nil))
|
|
||||||
|
|
||||||
resp, err := c.Cli().R().Head(fmt.Sprintf("/file/%s", sum))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if resp.IsSuccess() {
|
|
||||||
return "", errors.New("file already exists")
|
|
||||||
}
|
|
||||||
return sum, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UploadCommand) FileUpload(sum string) error {
|
|
||||||
f, err := os.Open(c.File)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
st, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nbChunks := st.Size() / photosapi.CHUNK_SIZE
|
|
||||||
if st.Size()%photosapi.CHUNK_SIZE > 0 {
|
|
||||||
nbChunks++
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadFile := &UploadFileRequest{
|
|
||||||
Name: filepath.Base(c.File),
|
|
||||||
Chunks: make([]string, nbChunks),
|
|
||||||
Checksum: sum,
|
|
||||||
}
|
|
||||||
|
|
||||||
cli := c.Cli()
|
|
||||||
progress := progressbar.DefaultBytes(st.Size(), fmt.Sprintf("Uploading %s", uploadFile.Name))
|
|
||||||
defer progress.Close()
|
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
mu := sync.Mutex{}
|
|
||||||
wg.Add(4)
|
|
||||||
wgErrors := make([]error, c.Workers)
|
|
||||||
i := int64(0)
|
|
||||||
for w := uint32(0); w < c.Workers; w++ {
|
|
||||||
go func(w uint32) {
|
|
||||||
defer wg.Done()
|
|
||||||
b := make([]byte, photosapi.CHUNK_SIZE)
|
|
||||||
for {
|
|
||||||
mu.Lock()
|
|
||||||
part := i
|
|
||||||
i++
|
|
||||||
n, err := f.Read(b)
|
|
||||||
mu.Unlock()
|
|
||||||
if n == 0 {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
wgErrors[w] = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checksum := sha1.New()
|
|
||||||
checksum.Write(b[0:n])
|
|
||||||
sum := hex.EncodeToString(checksum.Sum(nil))
|
|
||||||
|
|
||||||
resp, err := cli.R().Head(fmt.Sprintf("/file/chunk/%s", sum))
|
|
||||||
if err != nil {
|
|
||||||
wgErrors[w] = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.IsSuccess() {
|
|
||||||
uploadFile.Chunks[part] = sum
|
|
||||||
progress.Add(n)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err = cli.R().SetError(&UploadError{}).SetBody(b[0:n]).Post("/file/chunk")
|
|
||||||
if err != nil {
|
|
||||||
wgErrors[w] = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err, ok := resp.Error().(*UploadError); ok {
|
|
||||||
wgErrors[w] = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadFile.Chunks[part] = sum
|
|
||||||
progress.Add(n)
|
|
||||||
}
|
|
||||||
}(w)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
for _, err := range wgErrors {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := cli.R().SetBody(uploadFile).SetError(&UploadError{}).SetResult(&UploadFileResponse{}).Post("/file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err, ok := resp.Error().(*UploadError); ok {
|
|
||||||
logger.Println("Upload failed")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if result, ok := resp.Result().(*UploadFileResponse); ok {
|
|
||||||
fmt.Printf("Upload succeed\nSum: %s\nNbChunks: %d\nSize: %d\n", result.Sum, result.NbChunks, result.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UploadCommand) Execute(args []string) error {
|
func (c *UploadCommand) Execute(args []string) error {
|
||||||
cli := c.Cli()
|
cli := c.Cli()
|
||||||
resp, err := cli.R().SetError(&UploadError{}).SetResult(&UploadCreate{}).Post("/upload")
|
resp, err := cli.R().SetError(&ResponseError{}).SetResult(&UploadCreate{}).Post("/upload")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := resp.Error().(*UploadError); ok {
|
if resp.IsError() {
|
||||||
return err
|
return resp.Error().(*ResponseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadId := resp.Result().(*UploadCreate).UploadId
|
uploadId := resp.Result().(*UploadCreate).UploadId
|
||||||
@ -249,7 +81,7 @@ func (c *UploadCommand) Execute(args []string) error {
|
|||||||
|
|
||||||
resp, err := cli.
|
resp, err := cli.
|
||||||
R().
|
R().
|
||||||
SetError(&UploadError{}).
|
SetError(&ResponseError{}).
|
||||||
SetResult(&UploadPartResult{}).
|
SetResult(&UploadPartResult{}).
|
||||||
SetQueryParam("part", fmt.Sprint(parts)).
|
SetQueryParam("part", fmt.Sprint(parts)).
|
||||||
SetQueryParam("sha256", hex.EncodeToString(partsha256.Sum(nil))).
|
SetQueryParam("sha256", hex.EncodeToString(partsha256.Sum(nil))).
|
||||||
@ -261,8 +93,8 @@ func (c *UploadCommand) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := resp.Error().(*UploadError); ok {
|
if resp.IsError() {
|
||||||
return err
|
return resp.Error().(*ResponseError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,9 +106,9 @@ func (c *UploadCommand) Execute(args []string) error {
|
|||||||
|
|
||||||
resp, err = cli.
|
resp, err = cli.
|
||||||
R().
|
R().
|
||||||
SetError(&UploadError{}).
|
SetError(&ResponseError{}).
|
||||||
SetPathParam("id", uploadId).
|
SetPathParam("id", uploadId).
|
||||||
SetBody(&UploadCompleteRequest{
|
SetBody(&photosapi.UploadCompleteRequest{
|
||||||
Sha256: hex.EncodeToString(completesha256.Sum(nil)),
|
Sha256: hex.EncodeToString(completesha256.Sum(nil)),
|
||||||
Parts: uint(parts),
|
Parts: uint(parts),
|
||||||
Name: filepath.Base(c.File),
|
Name: filepath.Base(c.File),
|
||||||
@ -287,8 +119,8 @@ func (c *UploadCommand) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, ok := resp.Error().(*UploadError); ok {
|
if resp.IsError() {
|
||||||
return err
|
return resp.Error().(*ResponseError)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Response: %s\n", resp.Body())
|
fmt.Printf("Response: %s\n", resp.Body())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user