From 0165352a63cb2f78871c2e72d4f2fd4f111637c3 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 14 Apr 2026 11:29:56 +0300 Subject: fix(report): propagate Write errors; shorten query/upload paths (ask 44) - Return io.WriteString errors from WriteReports via writeReportString - Split ParseReportQuery into small URL parsing helpers - Extract serveUploadPut and uploadAuthorized from upload handler closure - Build report header with strings.Builder Made-with: Cursor --- internal/daemon/upload.go | 105 +++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 48 deletions(-) (limited to 'internal/daemon/upload.go') diff --git a/internal/daemon/upload.go b/internal/daemon/upload.go index be6c6d9..71bffd0 100644 --- a/internal/daemon/upload.go +++ b/internal/daemon/upload.go @@ -24,57 +24,66 @@ var uploadKinds = map[string]string{ func uploadHandler(statsDir string, store *authkeys.Store) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPut { - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - return - } - host, kind, ok := parseUploadPath(r.URL.Path) - if !ok { - http.Error(w, "bad path", http.StatusBadRequest) - return - } - ext, ok := uploadKinds[kind] - if !ok { - http.Error(w, "unknown file kind", http.StatusBadRequest) - return - } - ctx := r.Context() - nKeys, err := store.KeyCount(ctx) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if nKeys > 0 { - tok, ok := parseBearer(r.Header.Get("Authorization")) - if !ok || tok == "" { - w.Header().Set("WWW-Authenticate", `Bearer realm="upload"`) - http.Error(w, "unauthorized", http.StatusUnauthorized) - return - } - valid, err := store.Verify(ctx, host, tok) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if !valid { - http.Error(w, "forbidden", http.StatusForbidden) - return - } - } - rel := host + ext - target := filepath.Join(statsDir, rel) - if !fileUnderDir(statsDir, target) { - http.Error(w, "bad path", http.StatusBadRequest) - return - } - if err := writeUploadBody(target, r.Body); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - w.WriteHeader(http.StatusNoContent) + serveUploadPut(w, r, statsDir, store) }) } +func serveUploadPut(w http.ResponseWriter, r *http.Request, statsDir string, store *authkeys.Store) { + if r.Method != http.MethodPut { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + host, kind, ok := parseUploadPath(r.URL.Path) + if !ok { + http.Error(w, "bad path", http.StatusBadRequest) + return + } + ext, ok := uploadKinds[kind] + if !ok { + http.Error(w, "unknown file kind", http.StatusBadRequest) + return + } + ctx := r.Context() + nKeys, err := store.KeyCount(ctx) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if nKeys > 0 && !uploadAuthorized(ctx, w, store, host, r.Header.Get("Authorization")) { + return + } + rel := host + ext + target := filepath.Join(statsDir, rel) + if !fileUnderDir(statsDir, target) { + http.Error(w, "bad path", http.StatusBadRequest) + return + } + if err := writeUploadBody(target, r.Body); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + w.WriteHeader(http.StatusNoContent) +} + +func uploadAuthorized(ctx context.Context, w http.ResponseWriter, store *authkeys.Store, host, authz string) bool { + tok, ok := parseBearer(authz) + if !ok || tok == "" { + w.Header().Set("WWW-Authenticate", `Bearer realm="upload"`) + http.Error(w, "unauthorized", http.StatusUnauthorized) + return false + } + valid, err := store.Verify(ctx, host, tok) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return false + } + if !valid { + http.Error(w, "forbidden", http.StatusForbidden) + return false + } + return true +} + func parseUploadPath(path string) (host, kind string, ok bool) { const prefix = "/upload/" if !strings.HasPrefix(path, prefix) { -- cgit v1.2.3