Let --data read the body: @<path> from a file, @- from stdin - #4
Merged
Merged
Conversation
mattpodwysocki
force-pushed
the
data-from-file
branch
from
September 14, 2026 17:39
9a8399d to
ba70257
Compare
zmofei
approved these changes
Sep 14, 2026
zmofei
left a comment
Member
There was a problem hiding this comment.
LGTM — verified diff, timeout budget threading, edge-case tests, and CI (all green).
`--data` could only carry a body typed on the command line, so sending a
style from a file meant `--data "$(cat style.json)"`. That works on macOS and
Linux and nowhere else this CLI ships to: there is no `cmd.exe` equivalent of
`$(cat …)`, the body lands in the process table where `ps` shows it, and it
breaks at a size that fails in the shell *before* `mapbox` runs — so no
remedy string can explain it.
`@<path>` and `@-` are curl's spelling. Only the first character decides, so
`--data '{"contact":"a@b.example"}'` is still the body it looks like; a body
whose first character is a literal `@` cannot be passed this way, which costs
nothing because all five operations that take `--data` send JSON and `@` is
not valid JSON.
Resolved before the dry-run branch, so `--dry-run` validates the file too.
**The timeout had to move with it.** `Payload::Bounded`'s reasoning was "a
`--data` body was typed on a command line, and every operating system caps
how much one of those can hold" — true until this change, and
`BodySource::Json` looks identical whether it was typed or read from a 200 MB
file. A read body now gets the 900-second transfer budget, so `payload_of`
takes the provenance rather than inferring it from a body that no longer
carries the distinction.
Three smaller decisions, each with a test: read as text, because a JSON body
has to be UTF-8 and a lossy conversion would be rejected for reasons naming
nothing the caller did; sent byte for byte, because trimming a supplied body
would be the CLI editing what it was asked to send; and an empty source names
itself, because `cat missing.json | mapbox …` otherwise fails as "EOF while
parsing a value", which describes the parser rather than the pipe.
Documented one interaction rather than changing it: of the five operations
only `sprites delete-batch` is a DELETE, and a confirmation needs stdin to be
a terminal — which a pipe is not. So `@-` sends it unasked, exactly as
`< file` always did. `@<path>` keeps the prompt.
Verified live against the API through both forms, not only under `--dry-run`.
Ported from mapbox/mapbox-cli-private#136, which cannot merge there now that
`oss/` is a submodule (mapbox/mapbox-cli-private#132).
mattpodwysocki
force-pushed
the
data-from-file
branch
from
September 14, 2026 17:54
ba70257 to
0c369b9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ported from mapbox-cli-private#136, which can no longer merge there now that
oss/is a submodule (#132). CI was green there; re-verified here.--datacan now read the request body instead of carrying it:Why
--data "$(cat style.json)"works on macOS and Linux and nowhere else this CLI ships to. There is nocmd.exeequivalent of$(cat …)on a platform with its own installer and CI leg; the body lands in the process table wherepsshows it to other users; and it breaks at a size that fails in the shell, beforemapboxruns, so no remedy string could ever be seen.Exactly five operations take
--data, so the blast radius is knowable:geocoder batch-geocode,styles create,styles update,styles draft update,sprites delete-batch.The part that would have been silently wrong
Payload::Bounded's doc comment read:Correct until this change, and exactly what
@<path>breaks:BodySource::Jsonlooks identical whether it was typed or read from a 200 MB file, and the second would have been handed a 60-second budget instead of the 900 seconds--filegets. Nothing would have failed in CI — a large body would just have timed out with an error blaming the network.payload_ofnow takes the provenance rather than inferring it from a body that no longer carries the distinction.Three decisions, each with a test
cat missing.json | mapbox …fails asEOF while parsing a value, which describes the parser rather than the pipe whose own error scrolled past.One interaction documented rather than changed
Of the five, only
sprites delete-batchis aDELETE, and a confirmation needs stdin to be a terminal — which a pipe is not, soconfirm::decidereturnsProceed. Piping a body therefore sends it unasked, exactly as< filealways did.@<path>leaves stdin alone and keeps the prompt.This was the one thing I'd flagged as needing a decision — whether
@-must imply--yesor error. It doesn't: the thing that makes@-possible is the same thing that already suppresses the prompt.The
@ambiguityOnly the first character decides, so
--data '{"contact":"a@b.example"}'is still the body it looks like. A body whose first character is a literal@can't be passed this way — curl has the same limitation — and it costs nothing because all five operations send JSON and@is not valid JSON.--data-rawis the escape hatch if a text body that could start with one is ever wired up; noted in the comment rather than built for a case that doesn't exist.Verified
548 tests, fmt and clippy clean. Before the port, against the live API:
batch-geocode --data @queries.jsonand the same piped through@-both returned Helsinki and Tampere. Under--dry-run: the 242 KB style from the issue at 241,946 bytes, a missing file, a bare@, a directory, an empty pipe, and a non-UTF-8 file each reporting the actual mistake.