diff --git a/internal/agent/fsstream.go b/internal/agent/fsstream.go index d3f9919..19675fb 100644 --- a/internal/agent/fsstream.go +++ b/internal/agent/fsstream.go @@ -5,11 +5,13 @@ import ( "encoding/json" "fmt" "io" + "log" "net/http" "os" "path/filepath" "strconv" "syscall" + "time" "github.com/x-grk/longpolling-remote-access/internal/proto" ) @@ -62,6 +64,7 @@ func (a *Agent) doFSUpload(ctx context.Context, env proto.TaskEnvelope) proto.Ta } n, err := io.Copy(tmp, io.LimitReader(resp.Body, proto.FSFileCap+1)) if err != nil { + log.Printf("fs receive %s: broke after %d of %d bytes: %v", args.Path, n, args.Size, err) return proto.TaskResult{Error: "загрузка прервана: " + err.Error()} } if n > proto.FSFileCap { @@ -123,13 +126,16 @@ func (a *Agent) doFSGet(ctx context.Context, env proto.TaskEnvelope) proto.TaskR req.ContentLength = info.Size() req.Header.Set("X-Size", strconv.FormatInt(info.Size(), 10)) a.authHeaders(req) + start := time.Now() resp, err := a.stream.Do(req) if err != nil { + log.Printf("fs send %s (%d bytes): failed after %s: %v", args.Path, info.Size(), time.Since(start).Round(time.Millisecond), err) return proto.TaskResult{Error: err.Error()} } io.Copy(io.Discard, resp.Body) resp.Body.Close() if resp.StatusCode != http.StatusNoContent { + log.Printf("fs send %s (%d bytes): server answered %d after %s", args.Path, info.Size(), resp.StatusCode, time.Since(start).Round(time.Millisecond)) return proto.TaskResult{Error: "браузер не дочитал файл"} } data, _ := json.Marshal(map[string]any{"path": args.Path, "size": info.Size()}) diff --git a/internal/server/fsstream.go b/internal/server/fsstream.go index 0ef0a96..fd752ea 100644 --- a/internal/server/fsstream.go +++ b/internal/server/fsstream.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "io" + "log" "net/http" "path" "strconv" @@ -154,7 +155,10 @@ func (s *Server) handleFSUpload(w http.ResponseWriter, r *http.Request) { copied := make(chan struct{}) go func() { defer close(copied) - _, err := io.Copy(st.w, body) + n, err := io.Copy(st.w, body) + if err != nil && !errors.Is(err, io.ErrClosedPipe) { + log.Printf("fs upload %s to %s: browser stream broke after %d of %d bytes: %v", p, agentID, n, r.ContentLength, err) + } st.w.CloseWithError(err) // nil: the reader sees the end of the file }() @@ -246,9 +250,10 @@ func (s *Server) handleFSDownload(w http.ResponseWriter, r *http.Request) { if st.size >= 0 { w.Header().Set("Content-Length", strconv.FormatInt(st.size, 10)) } - if _, err := io.Copy(w, st.r); err != nil { + if n, err := io.Copy(w, st.r); err != nil { // Cut the response off, so the browser does not take a part of // the file for all of it. + log.Printf("fs download %s from %s: cut off after %d of %d bytes: %v", p, agentID, n, st.size, err) st.r.CloseWithError(err) panic(http.ErrAbortHandler) } @@ -310,9 +315,10 @@ func (s *Server) handleAgentFSStreamGet(w http.ResponseWriter, r *http.Request) if st.size >= 0 { w.Header().Set("Content-Length", strconv.FormatInt(st.size, 10)) } - if _, err := io.Copy(w, st.r); err != nil { + if n, err := io.Copy(w, st.r); err != nil { // The browser broke off: cut the response, so the agent does not // take a part of the file for all of it. + log.Printf("fs upload to %s: cut off after %d of %d bytes: %v", a.ID, n, st.size, err) panic(http.ErrAbortHandler) } } @@ -338,9 +344,10 @@ func (s *Server) handleAgentFSStreamPost(w http.ResponseWriter, r *http.Request) http.Error(w, "gone", http.StatusGone) return } - _, err = io.Copy(st.w, http.MaxBytesReader(w, r.Body, proto.FSFileCap)) + n, err := io.Copy(st.w, http.MaxBytesReader(w, r.Body, proto.FSFileCap)) st.w.CloseWithError(err) if err != nil { + log.Printf("fs download from %s: agent stream broke after %d of %d bytes: %v", a.ID, n, size, err) http.Error(w, "gone", http.StatusGone) return }