Implement resumable download queue (T-301)
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package downloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TaskPaths are fixed local names derived only from RequestID.
|
||||
type TaskPaths struct {
|
||||
Root string
|
||||
TasksDir string
|
||||
FilesDir string
|
||||
Metadata string
|
||||
Backup string
|
||||
Part string
|
||||
Completed string
|
||||
}
|
||||
|
||||
// DeriveTaskPaths derives all local paths without accepting remote filenames
|
||||
// or Content-Disposition values.
|
||||
func DeriveTaskPaths(downloadsRoot, requestID string) (TaskPaths, error) {
|
||||
if downloadsRoot == "" {
|
||||
return TaskPaths{}, fmt.Errorf("%w: empty downloads root", ErrInvalidTask)
|
||||
}
|
||||
if !ValidRequestID(requestID) {
|
||||
return TaskPaths{}, fmt.Errorf("%w: invalid request_id", ErrInvalidTask)
|
||||
}
|
||||
absoluteRoot, err := filepath.Abs(downloadsRoot)
|
||||
if err != nil {
|
||||
return TaskPaths{}, fmt.Errorf("%w: resolve downloads root", ErrInvalidTask)
|
||||
}
|
||||
tasksDir := filepath.Join(absoluteRoot, "tasks")
|
||||
filesDir := filepath.Join(absoluteRoot, "files")
|
||||
paths := TaskPaths{
|
||||
Root: absoluteRoot,
|
||||
TasksDir: tasksDir,
|
||||
FilesDir: filesDir,
|
||||
Metadata: filepath.Join(tasksDir, requestID+".json"),
|
||||
Backup: filepath.Join(tasksDir, requestID+".json.backup"),
|
||||
Part: filepath.Join(filesDir, requestID+".part"),
|
||||
Completed: filepath.Join(filesDir, requestID+".download"),
|
||||
}
|
||||
for _, candidate := range []string{
|
||||
paths.TasksDir,
|
||||
paths.FilesDir,
|
||||
paths.Metadata,
|
||||
paths.Backup,
|
||||
paths.Part,
|
||||
paths.Completed,
|
||||
} {
|
||||
relative, relativeErr := filepath.Rel(absoluteRoot, candidate)
|
||||
if relativeErr != nil ||
|
||||
relative == ".." ||
|
||||
strings.HasPrefix(relative, ".."+string(filepath.Separator)) {
|
||||
return TaskPaths{}, fmt.Errorf("%w: derived path escapes root", ErrInvalidTask)
|
||||
}
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
Reference in New Issue
Block a user