Skip to content

Commit cf14135

Browse files
authored
fix(Multipart): Create InputStream only when the body is filled (#23)
1 parent a5a5e07 commit cf14135

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

Sources/SimpleHTTP/MultipartForm/MultipartFormData.swift

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,30 @@ enum Boundary {
4848

4949
struct BodyPart {
5050
let headers: [Header]
51-
let stream: InputStream
5251
let length: Int
52+
let stream: () throws -> InputStream
53+
5354
var hasInitialBoundary = false
5455
var hasFinalBoundary = false
5556

56-
init(headers: [Header], stream: InputStream, length: Int) {
57+
private init(headers: [Header], stream: @escaping () throws -> InputStream, length: Int) {
5758
self.headers = headers
58-
self.stream = stream
5959
self.length = length
60+
self.stream = stream
61+
}
62+
63+
init(headers: [Header], url: URL, length: Int) {
64+
let stream: () throws -> InputStream = {
65+
guard let stream = InputStream(url: url) else {
66+
throw MultipartFormData.Error.inputStreamCreationFailed(url)
67+
}
68+
return stream
69+
}
70+
self.init(headers: headers, stream: stream, length: length)
71+
}
72+
73+
init(headers: [Header], data: Data) {
74+
self.init(headers: headers, stream: { InputStream(data: data) }, length: data.count)
6075
}
6176
}
6277

@@ -126,12 +141,7 @@ public struct MultipartFormData {
126141
}
127142

128143
let length = fileSize.intValue
129-
130-
guard let stream = InputStream(url: url) else {
131-
throw MultipartFormData.Error.inputStreamCreationFailed(url)
132-
}
133-
134-
bodyParts.append(BodyPart(headers: headers, stream: stream, length: length))
144+
bodyParts.append(BodyPart(headers: headers, url: url, length: length))
135145
}
136146

137147
/// Creates a body part from the data and add it to the instance.
@@ -150,10 +160,8 @@ public struct MultipartFormData {
150160
/// - mimeType: MIME type associated to the data in the `Content-Type` HTTPHeader.
151161
public mutating func add(data: Data, name: String, fileName: String? = nil, mimeType: String? = nil) {
152162
let headers = defineBodyPartHeader(name: name, fileName: fileName, mimeType: mimeType)
153-
let stream = InputStream(data: data)
154-
let length = data.count
155163

156-
bodyParts.append(BodyPart(headers: headers, stream: stream, length: length))
164+
bodyParts.append(BodyPart(headers: headers, data: data))
157165
}
158166

159167
private func defineBodyPartHeader(name: String, fileName: String?, mimeType: String?) -> [Header] {

Sources/SimpleHTTP/MultipartForm/MultipartFormDataEncoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct MultipartFormDataEncoder {
4646
}
4747

4848
encoded.append(try encodeBodyPart(headers: bodyPart.headers))
49-
encoded.append(try encodeBodyPart(stream: bodyPart.stream, length: bodyPart.length))
49+
encoded.append(try encodeBodyPart(stream: bodyPart.stream(), length: bodyPart.length))
5050

5151
if bodyPart.hasFinalBoundary {
5252
encoded.append(Boundary.data(for: .final, boundary: boundary))

Tests/SimpleHTTPTests/MultipartForm/MultipartFormDataEncoderTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,18 @@ class MultipartFormDataEncoderTests: XCTestCase {
158158
XCTAssertEqual(encodedData, expectedData)
159159
}
160160

161+
func test_encode_encoreMultiPartFormDataTwice_notThrow() throws {
162+
let boundary = "boundary"
163+
var multipart = MultipartFormData(boundary: boundary)
164+
165+
let data = "I'm pjechris, Nice to meet you"
166+
let name1 = "data"
167+
multipart.add(data: Data(data.utf8), name: name1)
168+
169+
var encoder = MultipartFormDataEncoder(body: multipart)
170+
_ = try encoder.encode()
171+
172+
XCTAssertNoThrow(_ = try encoder.encode())
173+
}
174+
161175
}

0 commit comments

Comments
 (0)