feat(cli): 支持安全下载单个远端文件 / safely download one remote file - #485
feat(cli): 支持安全下载单个远端文件 / safely download one remote file#485Jinghao-coding wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c0d05d18a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if err != nil { | ||
| return 0, &NetworkError{Cause: err} | ||
| } | ||
| if !resp.IsSuccessState() { |
There was a problem hiding this comment.
Require a full-file HTTP response before publishing
Reject successful statuses other than the endpoint's expected 200 OK. IsSuccessState() also accepts responses such as 206 Partial Content and 204 No Content; if a proxy or storage server returns a valid shorter 206 response, io.Copy reaches EOF without error and the command atomically publishes the incomplete file while reporting success.
Useful? React with 👍 / 👎.
| defer func() { | ||
| if temporaryOpen { | ||
| _ = temporary.Close() | ||
| } | ||
| _ = os.Remove(temporaryPath) |
There was a problem hiding this comment.
Handle interrupts so partial temporary files are removed
Make command interruption cancel the request and unwind this cleanup path. The inspected entrypoint calls rootCmd.Execute() without a signal-aware context (cli/main.go:13, cli/cmd/root.go:71), so pressing Ctrl-C during a large download invokes Go's default SIGINT termination and skips all deferred functions, leaving the potentially large .crater-* temporary file behind indefinitely.
Useful? React with 👍 / 👎.
2c0d05d to
292b395
Compare
292b395 to
5faadb6
Compare
中文
说明
新增
crater file download <remote-file> [local-path],用于把user、public或当前account下的单个远端文件安全下载到本机。实现内容
GET /api/ss/download/*path。io.Copy真正流式写入,不把完整文件载入内存。#和%,并在请求前拒绝越界路径。Sync、Close再发布。os.Link原子 no-clobber 发布,消除检查与发布之间的竞态覆盖。--overwrite才使用同目录os.Rename原子替换;下载完成前旧文件保持不变。--json只输出远端路径、本地路径、字节数和覆盖开关,不输出二进制内容。make pre-commit-check在当前 main 上可复现通过。验证
go test ./cmd ./internal/api -count=1go test -race ./cmd ./internal/api -count=1make snapshot-update,已人工检查新增/变化 goldenmake pre-commit-checkmake buildgo vet ./cmd ./internal/api./crater file download --helpusage_error和退出码 2测试覆盖流式首块互锁、NUL/0xff 二进制完整性、逐段路径编码、JSON/纯文本错误、错误响应体读取失败、默认无覆盖成功、并发晚到冲突、显式覆盖、部分失败保留旧文件、临时文件清理及 JSON 纯元数据。
真实 storage service 未在本机 8088 入口提供,因此未把真实服务联调冒充为通过;HTTP 传输契约由真实
httptest.Server和流式互锁测试覆盖。测试截图
Closes #478
English
Summary
Adds
crater file download <remote-file> [local-path]to safely copy one remote file fromuser,public, or the currentaccountstorage space to the local machine.Changes
GET /api/ss/download/*path.io.Copy, never buffering the complete file.os.Linkno-clobber publication by default, removing the check-to-publish overwrite race.os.Renamereplacement only with explicit--overwrite; the old file remains intact until the download completes.make pre-commit-checkis reproducible on current main.Validation
go test ./cmd ./internal/api -count=1go test -race ./cmd ./internal/api -count=1make snapshot-update, followed by manual golden reviewmake pre-commit-checkmake buildgo vet ./cmd ./internal/api./crater file download --helpexecutionusage_errorand exit code 2Coverage includes a first-chunk streaming handshake, NUL/0xff binary integrity, segment encoding, JSON/plain-text failures, broken error-body reads, default no-clobber success, late concurrent conflicts, explicit overwrite, partial-failure preservation, temp cleanup, and metadata-only JSON stdout.
The real storage service is not exposed through local port 8088, so this PR does not claim a live storage integration result. HTTP transport behavior is exercised through a real
httptest.Serverand streaming handshake.Test screenshot