mirror of
https://github.com/coalaura/up.git
synced 2025-07-18 21:53:23 +00:00
msgpack and streaming
This commit is contained in:
35
client/progress.go
Normal file
35
client/progress.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/coalaura/progress"
|
||||
)
|
||||
|
||||
type ProgressReader struct {
|
||||
io.Reader
|
||||
bar *progress.Bar
|
||||
}
|
||||
|
||||
func NewProgressReader(label string, total int64, reader io.Reader) *ProgressReader {
|
||||
bar := progress.NewProgressBarWithTheme(label, total, progress.ThemeDots)
|
||||
|
||||
bar.Start()
|
||||
|
||||
return &ProgressReader{
|
||||
Reader: reader,
|
||||
bar: bar,
|
||||
}
|
||||
}
|
||||
|
||||
func (pr *ProgressReader) Read(p []byte) (int, error) {
|
||||
n, err := pr.Reader.Read(p)
|
||||
|
||||
pr.bar.IncrementBy(int64(n))
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (pr *ProgressReader) Close() {
|
||||
pr.bar.Stop()
|
||||
}
|
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -14,18 +13,19 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coalaura/up/internal"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func RequestChallenge(target, public string) (*internal.AuthChallenge, error) {
|
||||
request, err := json.Marshal(internal.AuthRequest{
|
||||
request, err := msgpack.Marshal(internal.AuthRequest{
|
||||
Public: public,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
response, err := http.Post(fmt.Sprintf("%s/request", target), "application/json", bytes.NewReader(request))
|
||||
response, err := http.Post(fmt.Sprintf("%s/request", target), "application/msgpack", bytes.NewReader(request))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %v", err)
|
||||
}
|
||||
@ -38,7 +38,7 @@ func RequestChallenge(target, public string) (*internal.AuthChallenge, error) {
|
||||
|
||||
var challenge internal.AuthChallenge
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&challenge); err != nil {
|
||||
if err := msgpack.NewDecoder(response.Body).Decode(&challenge); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ func CompleteChallenge(target, public string, private ssh.Signer, challenge *int
|
||||
return nil, fmt.Errorf("failed to sign challenge: %v", err)
|
||||
}
|
||||
|
||||
request, err := json.Marshal(internal.AuthResponse{
|
||||
request, err := msgpack.Marshal(internal.AuthResponse{
|
||||
Token: challenge.Token,
|
||||
Public: public,
|
||||
Format: signature.Format,
|
||||
@ -66,7 +66,7 @@ func CompleteChallenge(target, public string, private ssh.Signer, challenge *int
|
||||
return nil, fmt.Errorf("failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
response, err := http.Post(fmt.Sprintf("%s/complete", target), "application/json", bytes.NewReader(request))
|
||||
response, err := http.Post(fmt.Sprintf("%s/complete", target), "application/msgpack", bytes.NewReader(request))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %v", err)
|
||||
}
|
||||
@ -79,7 +79,7 @@ func CompleteChallenge(target, public string, private ssh.Signer, challenge *int
|
||||
|
||||
var result internal.AuthResponse
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
|
||||
if err := msgpack.NewDecoder(response.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
@ -87,22 +87,38 @@ func CompleteChallenge(target, public string, private ssh.Signer, challenge *int
|
||||
}
|
||||
|
||||
func SendFile(target, token string, file *os.File) error {
|
||||
var buf bytes.Buffer
|
||||
|
||||
writer := multipart.NewWriter(&buf)
|
||||
|
||||
part, err := writer.CreateFormFile("file", filepath.Base(file.Name()))
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create form file: %v", err)
|
||||
return fmt.Errorf("failed to stat file: %v", err)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(part, file); err != nil {
|
||||
return fmt.Errorf("failed to copy file: %v", err)
|
||||
}
|
||||
pReader, pWriter := io.Pipe()
|
||||
|
||||
writer.Close()
|
||||
writer := multipart.NewWriter(pWriter)
|
||||
|
||||
request, err := http.NewRequest("POST", fmt.Sprintf("%s/receive", target), &buf)
|
||||
go func() {
|
||||
defer pWriter.Close()
|
||||
|
||||
part, err := writer.CreateFormFile("file", filepath.Base(file.Name()))
|
||||
if err != nil {
|
||||
pWriter.CloseWithError(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := io.Copy(part, file); err != nil {
|
||||
pWriter.CloseWithError(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
writer.Close()
|
||||
}()
|
||||
|
||||
reader := NewProgressReader("Uploading", stat.Size(), pReader)
|
||||
defer reader.Close()
|
||||
|
||||
request, err := http.NewRequest("POST", fmt.Sprintf("%s/receive", target), reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create request: %v", err)
|
||||
}
|
||||
@ -116,6 +132,7 @@ func SendFile(target, token string, file *os.File) error {
|
||||
}
|
||||
|
||||
response.Body.Close()
|
||||
reader.Close()
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return errors.New(response.Status)
|
||||
|
Reference in New Issue
Block a user