Skip to content

Commit dc43940

Browse files
authored
Merge pull request #7 from codecat15/multipart-form-data-format
creating a singleton out of the httputility
2 parents 6cd693f + 4416ef1 commit dc43940

File tree

7 files changed

+95
-82
lines changed

7 files changed

+95
-82
lines changed

HttpUtility.xcodeproj/project.pbxproj

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
86719EA024720BD1002A2AB0 /* HttpUtility.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86719E9624720BD1002A2AB0 /* HttpUtility.framework */; };
1616
86719EA724720BD1002A2AB0 /* HttpUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 86719E9924720BD1002A2AB0 /* HttpUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
1717
86719EB124720E40002A2AB0 /* HttpUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86719EB024720E40002A2AB0 /* HttpUtility.swift */; };
18+
86CAEFE625BBBE98006A7791 /* HUNetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86CAEFE525BBBE98006A7791 /* HUNetworkError.swift */; };
19+
86CAEFEA25BBBEDE006A7791 /* HUHttpMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86CAEFE925BBBEDE006A7791 /* HUHttpMethods.swift */; };
1820
86E9B56424883E9100B78521 /* Requests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86E9B56324883E9100B78521 /* Requests.swift */; };
1921
/* End PBXBuildFile section */
2022

@@ -40,6 +42,8 @@
4042
86719E9F24720BD1002A2AB0 /* HttpUtilityTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HttpUtilityTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4143
86719EA624720BD1002A2AB0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4244
86719EB024720E40002A2AB0 /* HttpUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpUtility.swift; sourceTree = "<group>"; };
45+
86CAEFE525BBBE98006A7791 /* HUNetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUNetworkError.swift; sourceTree = "<group>"; };
46+
86CAEFE925BBBEDE006A7791 /* HUHttpMethods.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUHttpMethods.swift; sourceTree = "<group>"; };
4347
86E9B56324883E9100B78521 /* Requests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Requests.swift; sourceTree = "<group>"; };
4448
/* End PBXFileReference section */
4549

@@ -117,6 +121,8 @@
117121
86719E9824720BD1002A2AB0 /* HttpUtility */ = {
118122
isa = PBXGroup;
119123
children = (
124+
86CAEFE525BBBE98006A7791 /* HUNetworkError.swift */,
125+
86CAEFE925BBBEDE006A7791 /* HUHttpMethods.swift */,
120126
8656BC562483E3B20023549D /* Extensions */,
121127
86719E9924720BD1002A2AB0 /* HttpUtility.h */,
122128
86719E9A24720BD1002A2AB0 /* Info.plist */,
@@ -193,7 +199,7 @@
193199
isa = PBXProject;
194200
attributes = {
195201
LastSwiftUpdateCheck = 1140;
196-
LastUpgradeCheck = 1140;
202+
LastUpgradeCheck = 1220;
197203
ORGANIZATIONNAME = CodeCat15;
198204
TargetAttributes = {
199205
86719E9524720BD1002A2AB0 = {
@@ -246,9 +252,11 @@
246252
isa = PBXSourcesBuildPhase;
247253
buildActionMask = 2147483647;
248254
files = (
255+
86CAEFE625BBBE98006A7791 /* HUNetworkError.swift in Sources */,
249256
86277C2024CB399B0078EB37 /* LazyImageView.swift in Sources */,
250257
86719EB124720E40002A2AB0 /* HttpUtility.swift in Sources */,
251258
8656BC582483E3C60023549D /* EncodableExtension.swift in Sources */,
259+
86CAEFEA25BBBEDE006A7791 /* HUHttpMethods.swift in Sources */,
252260
);
253261
runOnlyForDeploymentPostprocessing = 0;
254262
};
@@ -300,6 +308,7 @@
300308
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
301309
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
302310
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
311+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
303312
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
304313
CLANG_WARN_STRICT_PROTOTYPES = YES;
305314
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -325,7 +334,7 @@
325334
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
326335
GCC_WARN_UNUSED_FUNCTION = YES;
327336
GCC_WARN_UNUSED_VARIABLE = YES;
328-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
337+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
329338
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
330339
MTL_FAST_MATH = YES;
331340
ONLY_ACTIVE_ARCH = YES;
@@ -363,6 +372,7 @@
363372
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
364373
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
365374
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
375+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
366376
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
367377
CLANG_WARN_STRICT_PROTOTYPES = YES;
368378
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -382,7 +392,7 @@
382392
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
383393
GCC_WARN_UNUSED_FUNCTION = YES;
384394
GCC_WARN_UNUSED_VARIABLE = YES;
385-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
395+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
386396
MTL_ENABLE_DEBUG_INFO = NO;
387397
MTL_FAST_MATH = YES;
388398
SDKROOT = iphoneos;

HttpUtility.xcodeproj/xcshareddata/xcschemes/HttpUtility.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1150"
3+
LastUpgradeVersion = "1220"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

HttpUtility/Extensions/EncodableExtension.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,10 @@ extension Encodable
2020
if(requestDictionary != nil)
2121
{
2222
var queryItems: [URLQueryItem] = []
23-
2423
requestDictionary?.forEach({ (key, value) in
25-
26-
if(value != nil)
27-
{
24+
if(value != nil){
2825
let strValue = value.map { String(describing: $0) }
29-
if(strValue != nil && strValue?.count != 0)
30-
{
26+
if(strValue != nil && strValue?.count != 0){
3127
queryItems.append(URLQueryItem(name: key, value: strValue))
3228
}
3329
}
@@ -48,6 +44,7 @@ extension Encodable
4844
do {
4945
let encoder = try JSONEncoder().encode(self)
5046
let result = (try? JSONSerialization.jsonObject(with: encoder, options: .allowFragments)).flatMap{$0 as? [String: Any?]}
47+
5148
return result
5249

5350
} catch let error {

HttpUtility/HUHttpMethods.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// HUHttpMethods.swift
3+
// HttpUtility
4+
//
5+
// Created by CodeCat15 on 1/22/21.
6+
// Copyright © 2021 CodeCat15. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public enum HUHttpMethods : String
12+
{
13+
case get = "GET"
14+
case post = "POST"
15+
case put = "PUT"
16+
case delete = "DELETE"
17+
}

HttpUtility/HUNetworkError.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// HUNetworkError.swift
3+
// HttpUtility
4+
//
5+
// Created by CodeCat15 on 1/22/21.
6+
// Copyright © 2021 CodeCat15. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public struct HUNetworkError : Error
12+
{
13+
let reason: String?
14+
let httpStatusCode: Int?
15+
}

HttpUtility/HttpUtility.swift

Lines changed: 45 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,13 @@
88

99
import Foundation
1010

11-
public struct HUNetworkError : Error
12-
{
13-
let reason: String?
14-
let httpStatusCode: Int?
15-
}
16-
17-
public enum HUHttpMethods : String
18-
{
19-
case get = "GET"
20-
case post = "POST"
21-
case put = "PUT"
22-
case delete = "DELETE"
23-
}
24-
25-
2611
public struct HttpUtility
2712
{
28-
private var _token: String? = nil
29-
private var _customJsonDecoder: JSONDecoder? = nil
30-
31-
public init(token: String?){
32-
_token = token
33-
}
34-
35-
public init(token: String?, decoder: JSONDecoder?){
36-
_token = token
37-
_customJsonDecoder = decoder
38-
}
13+
static let shared = HttpUtility()
14+
public var authenticationToken : String? = nil
15+
public var customJsonDecoder : JSONDecoder? = nil
3916

40-
public init(WithJsonDecoder decoder: JSONDecoder){
41-
_customJsonDecoder = decoder
42-
}
43-
44-
public init(){}
17+
private init(){}
4518

4619
public func request<T:Decodable>(requestUrl: URL, method: HUHttpMethods, requestBody: Data? = nil, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
4720
{
@@ -68,9 +41,8 @@ public struct HttpUtility
6841
// MARK: - Private functions
6942
private func createJsonDecoder() -> JSONDecoder
7043
{
71-
let decoder = _customJsonDecoder != nil ? _customJsonDecoder! : JSONDecoder()
72-
if(_customJsonDecoder == nil)
73-
{
44+
let decoder = customJsonDecoder != nil ? customJsonDecoder! : JSONDecoder()
45+
if(customJsonDecoder == nil) {
7446
decoder.dateDecodingStrategy = .iso8601
7547
}
7648
return decoder
@@ -79,54 +51,29 @@ public struct HttpUtility
7951
private func createUrlRequest(requestUrl: URL) -> URLRequest
8052
{
8153
var urlRequest = URLRequest(url: requestUrl)
82-
if(_token != nil)
83-
{
84-
urlRequest.addValue(_token!, forHTTPHeaderField: "authorization")
54+
if(authenticationToken != nil) {
55+
urlRequest.setValue(authenticationToken!, forHTTPHeaderField: "authorization")
8556
}
8657

8758
return urlRequest
8859
}
8960

9061
private func decodeJsonResponse<T: Decodable>(data: Data, responseType: T.Type) -> T?
9162
{
92-
let decoder = self.createJsonDecoder()
63+
let decoder = createJsonDecoder()
9364
do{
9465
return try decoder.decode(responseType, from: data)
9566
}catch let error{
96-
debugPrint("deocding error =>\(error)")
67+
debugPrint("deocding error =>\(error.localizedDescription)")
9768
}
9869
return nil
9970
}
10071

101-
private func performOperation<T: Decodable>(requestUrl: URLRequest, responseType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>) -> Void)
102-
{
103-
URLSession.shared.dataTask(with: requestUrl) { (data, httpUrlResponse, error) in
104-
105-
let statusCode = (httpUrlResponse as? HTTPURLResponse)?.statusCode
106-
if(error == nil && data != nil && data?.count != 0)
107-
{
108-
let response = self.decodeJsonResponse(data: data!, responseType: responseType)
109-
110-
if(response != nil){
111-
completionHandler(.success(response))
112-
}else{
113-
completionHandler(.failure(HUNetworkError(reason: "decoding error", httpStatusCode: statusCode)))
114-
}
115-
}
116-
else
117-
{
118-
let networkError = HUNetworkError(reason: error.debugDescription,httpStatusCode: statusCode)
119-
completionHandler(.failure(networkError))
120-
}
121-
122-
}.resume()
123-
}
124-
12572
// MARK: - GET Api
12673
private func getData<T:Decodable>(requestUrl: URL, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
12774
{
128-
var urlRequest = createUrlRequest(requestUrl: requestUrl)
129-
urlRequest.httpMethod = "get"
75+
var urlRequest = self.createUrlRequest(requestUrl: requestUrl)
76+
urlRequest.httpMethod = HUHttpMethods.get.rawValue
13077

13178
performOperation(requestUrl: urlRequest, responseType: T.self) { (result) in
13279
completionHandler(result)
@@ -136,8 +83,8 @@ public struct HttpUtility
13683
// MARK: - POST Api
13784
private func postData<T:Decodable>(requestUrl: URL, requestBody: Data, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
13885
{
139-
var urlRequest = createUrlRequest(requestUrl: requestUrl)
140-
urlRequest.httpMethod = "post"
86+
var urlRequest = self.createUrlRequest(requestUrl: requestUrl)
87+
urlRequest.httpMethod = HUHttpMethods.post.rawValue
14188
urlRequest.httpBody = requestBody
14289
urlRequest.addValue("application/json", forHTTPHeaderField: "content-type")
14390

@@ -149,8 +96,8 @@ public struct HttpUtility
14996
// MARK: - PUT Api
15097
private func putData<T:Decodable>(requestUrl: URL, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
15198
{
152-
var urlRequest = createUrlRequest(requestUrl: requestUrl)
153-
urlRequest.httpMethod = "put"
99+
var urlRequest = self.createUrlRequest(requestUrl: requestUrl)
100+
urlRequest.httpMethod = HUHttpMethods.put.rawValue
154101

155102
performOperation(requestUrl: urlRequest, responseType: T.self) { (result) in
156103
completionHandler(result)
@@ -160,11 +107,38 @@ public struct HttpUtility
160107
// MARK: - DELETE Api
161108
private func deleteData<T:Decodable>(requestUrl: URL, resultType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>)-> Void)
162109
{
163-
var urlRequest = createUrlRequest(requestUrl: requestUrl)
164-
urlRequest.httpMethod = "delete"
110+
var urlRequest = self.createUrlRequest(requestUrl: requestUrl)
111+
urlRequest.httpMethod = HUHttpMethods.delete.rawValue
165112

166113
performOperation(requestUrl: urlRequest, responseType: T.self) { (result) in
167114
completionHandler(result)
168115
}
169116
}
117+
118+
// MARK: - Perform data task
119+
private func performOperation<T: Decodable>(requestUrl: URLRequest, responseType: T.Type, completionHandler:@escaping(Result<T?, HUNetworkError>) -> Void)
120+
{
121+
URLSession.shared.dataTask(with: requestUrl) { (data, httpUrlResponse, error) in
122+
123+
let statusCode = (httpUrlResponse as? HTTPURLResponse)?.statusCode
124+
if(error == nil && data != nil && data?.count != 0)
125+
{
126+
let response = self.decodeJsonResponse(data: data!, responseType: responseType)
127+
128+
if(response != nil){
129+
completionHandler(.success(response))
130+
}else {
131+
132+
let responseJsonString = String(data: data!, encoding: .utf8)
133+
completionHandler(.failure(HUNetworkError(reason: "response decoding error = \(String(describing: responseJsonString))", httpStatusCode: statusCode)))
134+
}
135+
}
136+
else
137+
{
138+
let networkError = HUNetworkError(reason: error.debugDescription,httpStatusCode: statusCode)
139+
completionHandler(.failure(networkError))
140+
}
141+
142+
}.resume()
143+
}
170144
}

HttpUtilityTests/IntegrationTests/HttpUtilityIntegrationTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import XCTest
1212
class HttpUtilityIntegrationTests: XCTestCase {
1313

1414
private typealias Employees = [EmployeeResponse]
15-
private let _utility = HttpUtility()
15+
private let _utility = HttpUtility.shared
1616

1717
func test_getApiData_With_Valid_Request_Returns_Success()
1818
{

0 commit comments

Comments
 (0)