1
0
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:
Laura
2025-06-20 16:10:38 +02:00
parent 28fad96c76
commit 602e327d03
8 changed files with 143 additions and 98 deletions

35
client/progress.go Normal file
View 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()
}

View File

@ -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)