fj api: read request body from stdin (--input -) or file (--input @path) #136

Closed
opened 2026-06-11 00:57:41 +00:00 by stephen · 0 comments
Owner

Task

Let fj api read its request body from stdin or a file, matching gh api:

  • --input - reads the body from stdin until EOF.
  • --input @path reads the body from a file.
  • Optionally extend -F key=@path (gh-style) so a single field is sourced from a file (@- for stdin, @file for a file), per gh's convention.

Keep the existing inline-string behavior for any value that is not - / @....

Source: rasterstate/fj#126.

Priority

p1. Streaming a generated payload into the escape hatch (jq -n '...' | fj api -X POST .../statuses/$SHA --input -) is the single most common gh api write idiom, and fj has no equivalent. The api command is the documented fallback for everything fj does not natively model, so a fallback that cannot accept generated/large/metacharacter-bearing payloads is a hard wall for CI, which is why this rates p1.

Reason

--input is parsed only as a literal JSON string (src/cli/api.rs:137): serde_json::from_str(input) with no -/@file handling here or in split_kv (:259), and the -f/-F field parsers (:143-167) treat every value as literal, so -f body=@payload.json sends the literal text @payload.json. The field doc comment even says values are taken verbatim (:40). So any payload generated by another tool, exceeding a comfortable command-line length, or containing shell metacharacters cannot be sent.

Acceptance

  • fj api -X POST <path> --input - reads the request body from stdin.
  • fj api -X POST <path> --input @file.json reads the body from a file.
  • (Optional) -F key=@path sources a single field from a file; @- from stdin.
  • Any value that is not -/@... keeps today's literal-string behavior.
  • Invalid JSON from stdin/file errors with the same --input must be valid JSON context.
  • Wiremock coverage in src/client/integration_tests.rs for stdin and file body sources.
  • cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all pass.

Dependencies

None. Sibling to rasterstate/fj#124 (-F/--body-file for issue/pr/release/milestone prose bodies); this issue is the raw HTTP request body on the api passthrough. Unblocks the fj api workaround called out in rasterstate/fj#127.

Size

S

## Task Let `fj api` read its request body from stdin or a file, matching `gh api`: - `--input -` reads the body from stdin until EOF. - `--input @path` reads the body from a file. - Optionally extend `-F key=@path` (gh-style) so a single field is sourced from a file (`@-` for stdin, `@file` for a file), per gh's convention. Keep the existing inline-string behavior for any value that is not `-` / `@...`. Source: rasterstate/fj#126. ## Priority p1. Streaming a generated payload into the escape hatch (`jq -n '...' | fj api -X POST .../statuses/$SHA --input -`) is the single most common `gh api` write idiom, and `fj` has no equivalent. The `api` command is the documented fallback for everything fj does not natively model, so a fallback that cannot accept generated/large/metacharacter-bearing payloads is a hard wall for CI, which is why this rates p1. ## Reason `--input` is parsed only as a literal JSON string (`src/cli/api.rs:137`): `serde_json::from_str(input)` with no `-`/`@file` handling here or in `split_kv` (`:259`), and the `-f`/`-F` field parsers (`:143-167`) treat every value as literal, so `-f body=@payload.json` sends the literal text `@payload.json`. The field doc comment even says values are taken verbatim (`:40`). So any payload generated by another tool, exceeding a comfortable command-line length, or containing shell metacharacters cannot be sent. ## Acceptance - [ ] `fj api -X POST <path> --input -` reads the request body from stdin. - [ ] `fj api -X POST <path> --input @file.json` reads the body from a file. - [ ] (Optional) `-F key=@path` sources a single field from a file; `@-` from stdin. - [ ] Any value that is not `-`/`@...` keeps today's literal-string behavior. - [ ] Invalid JSON from stdin/file errors with the same `--input must be valid JSON` context. - [ ] Wiremock coverage in `src/client/integration_tests.rs` for stdin and file body sources. - [ ] `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test --all` pass. ## Dependencies None. Sibling to rasterstate/fj#124 (`-F/--body-file` for issue/pr/release/milestone prose bodies); this issue is the raw HTTP request body on the `api` passthrough. Unblocks the `fj api` workaround called out in rasterstate/fj#127. ## Size S
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rasterstate/fj#136
No description provided.