Skip to content

Commit ee84d28

Browse files
committed
Fix(cf curl): Prevent errors when handling binary API responses
1 parent 75c5776 commit ee84d28

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed

command/v7/curl_command.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package v7
22

33
import (
4+
"bytes"
45
"net/http/httputil"
56
"os"
67

@@ -39,9 +40,9 @@ func (cmd CurlCommand) Execute(args []string) error {
3940
}
4041

4142
var bytesToWrite []byte
42-
43-
if cmd.IncludeResponseHeaders {
44-
headerBytes, _ := httputil.DumpResponse(httpResponse, false)
43+
var headerBytes []byte
44+
if cmd.IncludeResponseHeaders && httpResponse != nil {
45+
headerBytes, _ = httputil.DumpResponse(httpResponse, false)
4546
bytesToWrite = append(bytesToWrite, headerBytes...)
4647
}
4748

@@ -54,9 +55,24 @@ func (cmd CurlCommand) Execute(args []string) error {
5455
}
5556

5657
cmd.UI.DisplayOK()
58+
return nil
59+
}
60+
61+
// Check if the response contains binary data
62+
if IsBinary(responseBodyBytes) {
63+
// For binary data, write response headers with string conversion
64+
// and the response body without string conversion
65+
if cmd.IncludeResponseHeaders {
66+
cmd.UI.DisplayTextLiteral(string(headerBytes))
67+
}
68+
cmd.UI.GetOut().Write(responseBodyBytes)
5769
} else {
5870
cmd.UI.DisplayText(string(bytesToWrite))
5971
}
6072

6173
return nil
6274
}
75+
76+
func IsBinary(data []byte) bool {
77+
return bytes.ContainsRune(data, 0x00) // Check for null byte
78+
}

command/v7/curl_command_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,95 @@ var _ = Describe("curl Command", func() {
149149
})
150150
})
151151

152+
When("the response contains binary data", func() {
153+
var binaryData []byte
154+
155+
BeforeEach(func() {
156+
// Create binary data with null bytes (like a droplet file)
157+
binaryData = []byte{0x50, 0x4B, 0x03, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00}
158+
fakeActor.MakeCurlRequestReturns(binaryData, &http.Response{
159+
Header: http.Header{
160+
"Content-Type": []string{"application/octet-stream"},
161+
},
162+
}, nil)
163+
})
164+
165+
It("writes binary data directly to stdout without string conversion", func() {
166+
Expect(executeErr).NotTo(HaveOccurred())
167+
Expect(testUI.Out).To(Say(string(binaryData)))
168+
})
169+
170+
When("include-response-headers flag is set", func() {
171+
BeforeEach(func() {
172+
cmd.IncludeResponseHeaders = true
173+
})
174+
175+
It("writes headers as text and binary data separately", func() {
176+
Expect(executeErr).NotTo(HaveOccurred())
177+
178+
// Check that headers are written as text (using DisplayTextLiteral)
179+
Expect(testUI.Out).To(Say("Content-Type: application/octet-stream"))
180+
181+
// Check that binary data is preserved
182+
Expect(testUI.Out).To(Say(string(binaryData)))
183+
})
184+
})
185+
186+
When("output file is specified", func() {
187+
BeforeEach(func() {
188+
outputFile, err := os.CreateTemp("", "binary-output")
189+
Expect(err).NotTo(HaveOccurred())
190+
cmd.OutputFile = flag.Path(outputFile.Name())
191+
})
192+
193+
AfterEach(func() {
194+
os.RemoveAll(string(cmd.OutputFile))
195+
})
196+
197+
It("writes binary data to the file correctly", func() {
198+
Expect(executeErr).NotTo(HaveOccurred())
199+
200+
fileContents, err := os.ReadFile(string(cmd.OutputFile))
201+
Expect(err).ToNot(HaveOccurred())
202+
Expect(fileContents).To(Equal(binaryData))
203+
})
204+
})
205+
})
206+
207+
When("the response is empty", func() {
208+
BeforeEach(func() {
209+
fakeActor.MakeCurlRequestReturns([]byte{}, &http.Response{
210+
Header: http.Header{},
211+
}, nil)
212+
})
213+
214+
It("handles empty response correctly", func() {
215+
Expect(executeErr).NotTo(HaveOccurred())
216+
Expect(testUI.Out).To(Say(""))
217+
})
218+
})
219+
220+
// Test the IsBinary function directly
221+
Describe("IsBinary function", func() {
222+
It("returns true for data containing null bytes", func() {
223+
data := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64}
224+
Expect(v7.IsBinary(data)).To(BeTrue())
225+
})
226+
227+
It("returns false for data without null bytes", func() {
228+
data := []byte("Hello World")
229+
Expect(v7.IsBinary(data)).To(BeFalse())
230+
})
231+
232+
It("returns true for data that is all null bytes", func() {
233+
data := []byte{0x00, 0x00, 0x00, 0x00}
234+
Expect(v7.IsBinary(data)).To(BeTrue())
235+
})
236+
237+
It("returns false for empty data", func() {
238+
data := []byte{}
239+
Expect(v7.IsBinary(data)).To(BeFalse())
240+
})
241+
})
242+
152243
})

0 commit comments

Comments
 (0)