Skip to content

Commit fed3893

Browse files
stainless-app[bot]yjp20
authored andcommitted
feat(cli): binary request bodies
1 parent d8b885b commit fed3893

File tree

10 files changed

+155
-1
lines changed

10 files changed

+155
-1
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package binaryparam
2+
3+
import (
4+
"io"
5+
"os"
6+
)
7+
8+
const stdinGlyph = "-"
9+
10+
// FileOrStdin opens the file at the given path for reading. If the path is "-", stdin is returned instead.
11+
//
12+
// It's the caller's responsibility to close the returned ReadCloser (usually with `defer`).
13+
//
14+
// Returns a boolean indicating whether stdin is being used. If true, no other components of the calling
15+
// program should attempt to read from stdin for anything else.
16+
func FileOrStdin(stdin io.ReadCloser, path string) (io.ReadCloser, bool, error) {
17+
// When the special glyph "-" is used, read from stdin. Although probably less necessary, also support
18+
// special Unix files that refer to stdin.
19+
switch path {
20+
case stdinGlyph, "/dev/fd/0", "/dev/stdin":
21+
return stdin, true, nil
22+
}
23+
24+
readCloser, err := os.Open(path)
25+
if err != nil {
26+
return nil, false, err
27+
}
28+
29+
return readCloser, false, err
30+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package binaryparam
2+
3+
import (
4+
"io"
5+
"os"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestFileOrStdin(t *testing.T) {
12+
t.Parallel()
13+
14+
const expectedContents = "test file contents"
15+
16+
t.Run("WithFile", func(t *testing.T) {
17+
tempFile := t.TempDir() + "/test_file.txt"
18+
require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600))
19+
20+
readCloser, stdinInUse, err := FileOrStdin(os.Stdin, tempFile)
21+
require.NoError(t, err)
22+
t.Cleanup(func() { require.NoError(t, readCloser.Close()) })
23+
24+
actualContents, err := io.ReadAll(readCloser)
25+
require.NoError(t, err)
26+
require.Equal(t, expectedContents, string(actualContents))
27+
28+
require.False(t, stdinInUse)
29+
})
30+
31+
t.Run("WithStdinGlyph", func(t *testing.T) {
32+
tempFile := t.TempDir() + "/test_file.txt"
33+
require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600))
34+
35+
stubStdin, err := os.Open(tempFile)
36+
require.NoError(t, err)
37+
38+
readCloser, stdinInUse, err := FileOrStdin(stubStdin, "-")
39+
require.NoError(t, err)
40+
41+
actualContents, err := io.ReadAll(readCloser)
42+
require.NoError(t, err)
43+
require.Equal(t, expectedContents, string(actualContents))
44+
45+
require.True(t, stdinInUse)
46+
})
47+
48+
t.Run("WithDevFD0File", func(t *testing.T) {
49+
tempFile := t.TempDir() + "/dev_fd_0"
50+
require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600))
51+
52+
stubStdin, err := os.Open(tempFile)
53+
require.NoError(t, err)
54+
55+
readCloser, stdinInUse, err := FileOrStdin(stubStdin, "/dev/fd/0")
56+
require.NoError(t, err)
57+
58+
actualContents, err := io.ReadAll(readCloser)
59+
require.NoError(t, err)
60+
require.Equal(t, expectedContents, string(actualContents))
61+
62+
require.True(t, stdinInUse)
63+
})
64+
65+
t.Run("WithDevStdinFile", func(t *testing.T) {
66+
tempFile := t.TempDir() + "/dev_stdin"
67+
require.NoError(t, os.WriteFile(tempFile, []byte(expectedContents), 0600))
68+
69+
stubStdin, err := os.Open(tempFile)
70+
require.NoError(t, err)
71+
72+
readCloser, stdinInUse, err := FileOrStdin(stubStdin, "/dev/stdin")
73+
require.NoError(t, err)
74+
75+
actualContents, err := io.ReadAll(readCloser)
76+
require.NoError(t, err)
77+
require.Equal(t, expectedContents, string(actualContents))
78+
79+
require.True(t, stdinInUse)
80+
})
81+
}

pkg/cmd/build.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error {
264264
apiquery.NestedQueryFormatBrackets,
265265
apiquery.ArrayQueryFormatComma,
266266
ApplicationJSON,
267+
false,
267268
)
268269
if err != nil {
269270
return err
@@ -374,11 +375,13 @@ func handleBuildsRetrieve(ctx context.Context, cmd *cli.Command) error {
374375
if len(unusedArgs) > 0 {
375376
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
376377
}
378+
377379
options, err := flagOptions(
378380
cmd,
379381
apiquery.NestedQueryFormatBrackets,
380382
apiquery.ArrayQueryFormatComma,
381383
EmptyBody,
384+
false,
382385
)
383386
if err != nil {
384387
return err
@@ -404,13 +407,15 @@ func handleBuildsList(ctx context.Context, cmd *cli.Command) error {
404407
if len(unusedArgs) > 0 {
405408
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
406409
}
410+
407411
params := stainless.BuildListParams{}
408412

409413
options, err := flagOptions(
410414
cmd,
411415
apiquery.NestedQueryFormatBrackets,
412416
apiquery.ArrayQueryFormatComma,
413417
EmptyBody,
418+
false,
414419
)
415420
if err != nil {
416421
return err
@@ -449,13 +454,15 @@ func handleBuildsCompare(ctx context.Context, cmd *cli.Command) error {
449454
if len(unusedArgs) > 0 {
450455
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
451456
}
457+
452458
params := stainless.BuildCompareParams{}
453459

454460
options, err := flagOptions(
455461
cmd,
456462
apiquery.NestedQueryFormatBrackets,
457463
apiquery.ArrayQueryFormatComma,
458464
ApplicationJSON,
465+
false,
459466
)
460467
if err != nil {
461468
return err

pkg/cmd/builddiagnostic.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,15 @@ func handleBuildsDiagnosticsList(ctx context.Context, cmd *cli.Command) error {
6161
if len(unusedArgs) > 0 {
6262
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
6363
}
64+
6465
params := stainless.BuildDiagnosticListParams{}
6566

6667
options, err := flagOptions(
6768
cmd,
6869
apiquery.NestedQueryFormatBrackets,
6970
apiquery.ArrayQueryFormatComma,
7071
EmptyBody,
72+
false,
7173
)
7274
if err != nil {
7375
return err

pkg/cmd/buildtargetoutput.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ func handleBuildsTargetOutputsRetrieve(ctx context.Context, cmd *cli.Command) er
6666
if len(unusedArgs) > 0 {
6767
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
6868
}
69+
6970
params := stainless.BuildTargetOutputGetParams{}
7071
options, err := flagOptions(
7172
cmd,
7273
apiquery.NestedQueryFormatBrackets,
7374
apiquery.ArrayQueryFormatComma,
7475
EmptyBody,
76+
false,
7577
)
7678
if err != nil {
7779
return err

pkg/cmd/flagoptions.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ func flagOptions(
3131
nestedFormat apiquery.NestedQueryFormat,
3232
arrayFormat apiquery.ArrayQueryFormat,
3333
bodyType BodyContentType,
34+
35+
// This parameter is true if stdin is already in use to pass a binary parameter by using the special value
36+
// "-". In this case, we won't attempt to read it as a JSON/YAML blob for options setting.
37+
stdinInUse bool,
3438
) ([]option.RequestOption, error) {
3539
var options []option.RequestOption
3640
if cmd.Bool("debug") {
@@ -40,7 +44,7 @@ func flagOptions(
4044
flagContents := requestflag.ExtractRequestContents(cmd)
4145

4246
var bodyData any
43-
if isInputPiped() {
47+
if isInputPiped() && !stdinInUse {
4448
var err error
4549
pipeData, err := io.ReadAll(os.Stdin)
4650
if err != nil {

pkg/cmd/org.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ func handleOrgsRetrieve(ctx context.Context, cmd *cli.Command) error {
4747
if len(unusedArgs) > 0 {
4848
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
4949
}
50+
5051
options, err := flagOptions(
5152
cmd,
5253
apiquery.NestedQueryFormatBrackets,
5354
apiquery.ArrayQueryFormatComma,
5455
EmptyBody,
56+
false,
5557
)
5658
if err != nil {
5759
return err
@@ -77,11 +79,13 @@ func handleOrgsList(ctx context.Context, cmd *cli.Command) error {
7779
if len(unusedArgs) > 0 {
7880
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
7981
}
82+
8083
options, err := flagOptions(
8184
cmd,
8285
apiquery.NestedQueryFormatBrackets,
8386
apiquery.ArrayQueryFormatComma,
8487
EmptyBody,
88+
false,
8589
)
8690
if err != nil {
8791
return err

pkg/cmd/project.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ func handleProjectsCreate(ctx context.Context, cmd *cli.Command) error {
106106
if len(unusedArgs) > 0 {
107107
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
108108
}
109+
109110
params := stainless.ProjectNewParams{}
110111

111112
options, err := flagOptions(
112113
cmd,
113114
apiquery.NestedQueryFormatBrackets,
114115
apiquery.ArrayQueryFormatComma,
115116
ApplicationJSON,
117+
false,
116118
)
117119
if err != nil {
118120
return err
@@ -138,13 +140,15 @@ func handleProjectsRetrieve(ctx context.Context, cmd *cli.Command) error {
138140
if len(unusedArgs) > 0 {
139141
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
140142
}
143+
141144
params := stainless.ProjectGetParams{}
142145

143146
options, err := flagOptions(
144147
cmd,
145148
apiquery.NestedQueryFormatBrackets,
146149
apiquery.ArrayQueryFormatComma,
147150
EmptyBody,
151+
false,
148152
)
149153
if err != nil {
150154
return err
@@ -170,13 +174,15 @@ func handleProjectsUpdate(ctx context.Context, cmd *cli.Command) error {
170174
if len(unusedArgs) > 0 {
171175
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
172176
}
177+
173178
params := stainless.ProjectUpdateParams{}
174179

175180
options, err := flagOptions(
176181
cmd,
177182
apiquery.NestedQueryFormatBrackets,
178183
apiquery.ArrayQueryFormatComma,
179184
ApplicationJSON,
185+
false,
180186
)
181187
if err != nil {
182188
return err
@@ -202,13 +208,15 @@ func handleProjectsList(ctx context.Context, cmd *cli.Command) error {
202208
if len(unusedArgs) > 0 {
203209
return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs)
204210
}
211+
205212
params := stainless.ProjectListParams{}
206213

207214
options, err := flagOptions(
208215
cmd,
209216
apiquery.NestedQueryFormatBrackets,
210217
apiquery.ArrayQueryFormatComma,
211218
EmptyBody,
219+
false,
212220
)
213221
if err != nil {
214222
return err

0 commit comments

Comments
 (0)