Skip to content

Commit cfc1103

Browse files
committed
code refractor for multipart form data
1 parent 2df2b38 commit cfc1103

File tree

6 files changed

+52
-104
lines changed

6 files changed

+52
-104
lines changed

HttpUtility.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
/* Begin PBXBuildFile section */
1010
86277C2024CB399B0078EB37 /* LazyImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86277C1F24CB399B0078EB37 /* LazyImageView.swift */; };
1111
86521B5625C6FD7200E05422 /* HURequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86521B5525C6FD7100E05422 /* HURequest.swift */; };
12-
86521B5C25C7023D00E05422 /* HUMultiPartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86521B5B25C7023D00E05422 /* HUMultiPartFormData.swift */; };
1312
8656BC582483E3C60023549D /* EncodableExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8656BC572483E3C60023549D /* EncodableExtension.swift */; };
1413
8656BC5B2483E43D0023549D /* EncodableExtensionUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8656BC5A2483E43D0023549D /* EncodableExtensionUnitTest.swift */; };
1514
8656BC5E2484313F0023549D /* HttpUtilityIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8656BC5D2484313F0023549D /* HttpUtilityIntegrationTests.swift */; };
@@ -35,7 +34,6 @@
3534
/* Begin PBXFileReference section */
3635
86277C1F24CB399B0078EB37 /* LazyImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyImageView.swift; sourceTree = "<group>"; };
3736
86521B5525C6FD7100E05422 /* HURequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HURequest.swift; sourceTree = "<group>"; };
38-
86521B5B25C7023D00E05422 /* HUMultiPartFormData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUMultiPartFormData.swift; sourceTree = "<group>"; };
3937
8656BC572483E3C60023549D /* EncodableExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableExtension.swift; sourceTree = "<group>"; };
4038
8656BC5A2483E43D0023549D /* EncodableExtensionUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableExtensionUnitTest.swift; sourceTree = "<group>"; };
4139
8656BC5D2484313F0023549D /* HttpUtilityIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpUtilityIntegrationTests.swift; sourceTree = "<group>"; };
@@ -132,7 +130,6 @@
132130
86719E9924720BD1002A2AB0 /* HttpUtility.h */,
133131
86719E9A24720BD1002A2AB0 /* Info.plist */,
134132
86719EB024720E40002A2AB0 /* HttpUtility.swift */,
135-
86521B5B25C7023D00E05422 /* HUMultiPartFormData.swift */,
136133
);
137134
path = HttpUtility;
138135
sourceTree = "<group>";
@@ -262,7 +259,6 @@
262259
86277C2024CB399B0078EB37 /* LazyImageView.swift in Sources */,
263260
86719EB124720E40002A2AB0 /* HttpUtility.swift in Sources */,
264261
8656BC582483E3C60023549D /* EncodableExtension.swift in Sources */,
265-
86521B5C25C7023D00E05422 /* HUMultiPartFormData.swift in Sources */,
266262
86521B5625C6FD7200E05422 /* HURequest.swift in Sources */,
267263
86CAEFEA25BBBEDE006A7791 /* HUHttpMethods.swift in Sources */,
268264
);

HttpUtility/Extensions/EncodableExtension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extension Encodable
3939
return nil
4040
}
4141

42-
private func convertToDictionary() -> [String: Any?]?
42+
func convertToDictionary() -> [String: Any?]?
4343
{
4444
do {
4545
let encoder = try JSONEncoder().encode(self)

HttpUtility/HUMultiPartFormData.swift

Lines changed: 0 additions & 43 deletions
This file was deleted.

HttpUtility/HURequest.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Foundation
1010

1111
public struct HURequest {
1212

13-
let url: URL
14-
let method: HUHttpMethods
13+
let url : URL
14+
let method : HUHttpMethods
15+
let request : Encodable
1516
}

HttpUtility/HttpUtility.swift

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@ public struct HttpUtility
3939
}
4040

4141
// MARK: - Multipart
42-
43-
public func requestWithMultiPart<T:Decodable>(request: HURequest, resultType: T.Type, postBody: HUMultiPartFormData, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void) {
44-
45-
postMultiPartFormData(requestUrl: request.url, multiPartFormData: postBody, resultType: resultType.self) { completionHandler($0) }
42+
public func requestWithMultiPartFormData<T:Decodable>(huRequest: HURequest, responseType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void) {
43+
postMultiPartFormData(huRequest: huRequest) { completionHandler($0) }
4644
}
4745

4846
// MARK: - Private functions
@@ -100,23 +98,41 @@ public struct HttpUtility
10098
}
10199
}
102100

103-
private func postMultiPartFormData<T:Decodable>(requestUrl: URL, multiPartFormData: HUMultiPartFormData, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
101+
private func postMultiPartFormData<T:Decodable>(huRequest: HURequest, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
104102
{
105-
var urlRequest = self.createUrlRequest(requestUrl: requestUrl)
103+
let boundary = "-----------------------------\(UUID().uuidString)"
104+
let lineBreak = "\r\n"
105+
var urlRequest = self.createUrlRequest(requestUrl: huRequest.url)
106106
urlRequest.httpMethod = HUHttpMethods.post.rawValue
107+
urlRequest.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
107108

108-
let body = multiPartFormData.getMultiPartBody()
109-
let boundary = multiPartFormData.getBoundary()
109+
var postBody = Data()
110110

111-
urlRequest.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
112-
urlRequest.addValue("\(body.count)", forHTTPHeaderField: "Content-Length")
113-
urlRequest.httpBody = body
114-
115-
performOperation(requestUrl: urlRequest, responseType: T.self) { (result) in
116-
completionHandler(result)
111+
let requestDictionary = huRequest.request.convertToDictionary()
112+
if(requestDictionary != nil)
113+
{
114+
requestDictionary?.forEach({ (key, value) in
115+
if(value != nil) {
116+
let strValue = value.map { String(describing: $0) }
117+
if(strValue != nil && strValue?.count != 0) {
118+
postBody.append("--\(boundary + lineBreak)" .data(using: .utf8)!)
119+
postBody.append("Content-Disposition: form-data; name=\"\(key)\" \(lineBreak + lineBreak)" .data(using: .utf8)!)
120+
postBody.append("\(strValue! + lineBreak)".data(using: .utf8)!)
121+
}
122+
}
123+
})
124+
125+
postBody.append("--\(boundary)--\(lineBreak)" .data(using: .utf8)!)
126+
127+
urlRequest.addValue("\(postBody.count)", forHTTPHeaderField: "Content-Length")
128+
urlRequest.httpBody = postBody
129+
130+
performOperation(requestUrl: urlRequest, responseType: T.self) { (result) in
131+
completionHandler(result)
132+
}
117133
}
118134
}
119-
135+
120136
// MARK: - PUT Api
121137
private func putData<T:Decodable>(requestUrl: URL, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
122138
{
@@ -145,6 +161,7 @@ public struct HttpUtility
145161
URLSession.shared.dataTask(with: requestUrl) { (data, httpUrlResponse, error) in
146162

147163
let statusCode = (httpUrlResponse as? HTTPURLResponse)?.statusCode
164+
debugPrint(String(data: data!, encoding: .utf8)!)
148165
if(error == nil && data != nil && data?.count != 0) {
149166
let response = self.decodeJsonResponse(data: data!, responseType: responseType)
150167
if(response != nil) {

HttpUtilityTests/IntegrationTests/HttpUtilityIntegrationTests.swift

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
import XCTest
1010
@testable import HttpUtility
1111

12+
13+
struct MyStruct : Encodable
14+
{
15+
let name, lastName: String
16+
}
17+
1218
class HttpUtilityIntegrationTests: XCTestCase {
1319

1420
private typealias Employees = [EmployeeResponse]
@@ -156,31 +162,24 @@ class HttpUtilityIntegrationTests: XCTestCase {
156162
// ARRANGE
157163
let expectation = XCTestExpectation(description: "Multipart form data test")
158164
let requestUrl = URL(string: "https://api-dev-scus-demo.azurewebsites.net/TestMultiPart")
159-
let name = "Code"
160-
let lastName = "Cat"
161165

162-
// todo: this code can be improved
163-
let multiPartFormData = HUMultiPartFormData()
164-
multiPartFormData.appendInitalBoundary() // what if the developer forgets to add this line?
165-
multiPartFormData.appendBodyPart(parameterName: "Name", WithParameterData: name)
166-
multiPartFormData.appendLineBreakForNextParameter() // I don't like this
167-
multiPartFormData.appendBodyPart(parameterName: "LastName", WithParameterData: lastName)
168-
multiPartFormData.appendClosingBoundary() // why does the dev has to specify all this???
166+
// request parameter structure that inherits from Encodable
167+
let myStruct = MyStruct(name: "Bruce", lastName: "Wayne")
169168

170-
let request = HURequest(url: requestUrl!, method: .post)
169+
// HURequest object containing information about the type of API call with request object
170+
let huRequest = HURequest(url: requestUrl!, method: .post, request: myStruct)
171171

172172
// ACT
173-
_utility.requestWithMultiPart(request: request, resultType: TestMultiPartResponse.self, postBody: multiPartFormData) { (response) in
174-
// ASSERT
173+
_utility.requestWithMultiPartFormData(huRequest: huRequest, responseType: TestMultiPartResponse.self) { (response) in
175174
switch response
176175
{
177176
case .success(let serviceResponse):
178177

179178
// ASSERT
180179
XCTAssertNotNil(serviceResponse)
181180
XCTAssertNotNil(serviceResponse?.data)
182-
XCTAssertEqual(name, serviceResponse?.data.name)
183-
XCTAssertEqual(lastName, serviceResponse?.data.lastName)
181+
XCTAssertEqual(myStruct.name, serviceResponse?.data.name)
182+
XCTAssertEqual(myStruct.lastName, serviceResponse?.data.lastName)
184183

185184
case .failure(let error):
186185
XCTAssertNil(error.reason)
@@ -196,35 +195,13 @@ class HttpUtilityIntegrationTests: XCTestCase {
196195
// ARRANGE
197196
let expectation = XCTestExpectation(description: "Multipart form data test")
198197
let requestUrl = URL(string: "https://api-dev-scus-demo.azurewebsites.net/api/Employee/MultiPartCodeChallenge")
199-
let multiPartFormData = HUMultiPartFormData()
200-
201-
multiPartFormData.appendInitalBoundary()
202-
203-
multiPartFormData.appendBodyPart(parameterName: "Name", WithParameterData: "Codecat")
204-
multiPartFormData.appendLineBreakForNextParameter()
205-
206-
multiPartFormData.appendBodyPart(parameterName: "LastName", WithParameterData: "HellWorld")
207-
multiPartFormData.appendLineBreakForNextParameter()
208-
209-
multiPartFormData.appendBodyPart(parameterName: "DateofJoining", WithParameterData: "12-12-2012")
210-
multiPartFormData.appendLineBreakForNextParameter()
211-
212-
multiPartFormData.appendBodyPart(parameterName: "DateofBirth", WithParameterData: "12-12-1992")
213-
multiPartFormData.appendLineBreakForNextParameter()
214-
215-
multiPartFormData.appendBodyPart(parameterName: "Gender", WithParameterData: "HumanBeing")
216-
multiPartFormData.appendLineBreakForNextParameter()
217-
218-
multiPartFormData.appendBodyPart(parameterName: "DepartmentName", WithParameterData: "Technology")
219-
multiPartFormData.appendLineBreakForNextParameter()
220198

221-
multiPartFormData.appendBodyPart(parameterName: "ManagerName", WithParameterData: "MyManagerName")
222-
multiPartFormData.appendClosingBoundary()
199+
let multiPartFormRequest = MultiPartFormRequest(name: "Bruce", lastName: "Wayne", gender: "Male", departmentName: "Tech", managerName: "James Gordan", dateOfJoining: "01-09-2020", dateOfBirth: "07-07-1988")
223200

224-
let request = HURequest(url: requestUrl!, method: .post)
201+
let request = HURequest(url: requestUrl!, method: .post, request: multiPartFormRequest)
225202

226203
// ACT
227-
_utility.requestWithMultiPart(request: request, resultType: MultiPartResponse.self, postBody: multiPartFormData) { (response) in
204+
_utility.requestWithMultiPartFormData(huRequest: request, responseType: MultiPartResponse.self) { (response) in
228205
// ASSERT
229206
switch response
230207
{

0 commit comments

Comments
 (0)