-
Notifications
You must be signed in to change notification settings - Fork 0
Download logic #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e8706f5
bc9d397
847e73f
5d0b57b
4fe093d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||
| package api | ||||||
|
|
||||||
| import ( | ||||||
| "encoding/json" | ||||||
| "fmt" | ||||||
| "net/http" | ||||||
| "time" | ||||||
|
|
||||||
| "github.com/go-chi/chi/v5" | ||||||
| ) | ||||||
|
|
||||||
| // handleGetDropMetadata returns info about the file (name, size, salt) | ||||||
| // The CLI needs this *before* it starts downloading to set up decryption. | ||||||
| func (s *Server) handleGetDropMetadata() http.HandlerFunc { | ||||||
| return func(w http.ResponseWriter, r *http.Request) { | ||||||
| dropID := chi.URLParam(r, "id") | ||||||
|
|
||||||
| var resp GetDropMetadataResponse | ||||||
| var expiresAt time.Time | ||||||
|
|
||||||
| // 1. Fetch metadata from Postgres | ||||||
| query := ` | ||||||
| SELECT file_name, file_size, encryption_salt, expires_at | ||||||
| FROM drops WHERE id = $1` | ||||||
|
|
||||||
| err := s.DB.QueryRow(query, dropID).Scan( | ||||||
| &resp.FileName, &resp.FileSize, &resp.EncryptionSalt, &expiresAt, | ||||||
| ) | ||||||
|
|
||||||
| if err != nil { | ||||||
| http.Error(w, "Drop not found", http.StatusNotFound) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| // 2. Check Expiry | ||||||
| if time.Now().After(expiresAt) { | ||||||
| http.Error(w, "Drop has expired", http.StatusGone) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| // 3. Get chunk count (to know how many pieces to expect) | ||||||
| err = s.DB.QueryRow("SELECT COUNT(*) FROM chunks WHERE drop_id = $1", dropID).Scan(&resp.ChunkCount) | ||||||
| if err != nil { | ||||||
| http.Error(w, "Database error", http.StatusInternalServerError) | ||||||
| return | ||||||
|
Comment on lines
+41
to
+45
|
||||||
| } | ||||||
|
|
||||||
| w.Header().Set("Content-Type", "application/json") | ||||||
| json.NewEncoder(w).Encode(resp) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // handleDownloadChunk retrieves a specific piece of binary data | ||||||
| func (s *Server) handleDownloadChunk() http.HandlerFunc { | ||||||
| return func(w http.ResponseWriter, r *http.Request) { | ||||||
| dropID := chi.URLParam(r, "id") | ||||||
| chunkIndex := chi.URLParam(r, "chunkIndex") // We'll add this param to router | ||||||
|
||||||
| chunkIndex := chi.URLParam(r, "chunkIndex") // We'll add this param to router | |
| chunkIndex := chi.URLParam(r, "chunkIndex") // chunkIndex is provided as a URL parameter |
Copilot
AI
Feb 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Download endpoint builds the S3 key directly from the URL chunkIndex without validating it or checking the drop/chunk state in Postgres (expiry, deletion, max/current downloads, chunk existence). Add validation (e.g. numeric index) and enforce drop expiry/download limits before serving data.
Copilot
AI
Feb 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This maps any DownloadChunk error to 404, which can hide genuine storage/permission/outage errors. Consider returning 404 only for missing objects and 500 for other errors (and/or log the underlying error).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QueryRow(...).Scan(...)errors are all mapped to 404. This will incorrectly return "Drop not found" on transient DB errors. Handlesql.ErrNoRowsas 404, but return 500 (and ideally log) for other errors.