88
99import Foundation
1010
11- struct HttpMethodType {
12- static let GET = " GET "
13- static let POST = " POST "
11+ struct HttpMethod : Equatable , Hashable {
12+ static let get = " GET "
13+ static let post = " POST "
14+ static let put = " PUT "
15+ static let delete = " DELETE "
1416}
1517
1618struct HttpHeaderFields
@@ -24,150 +26,156 @@ struct NetworkError : Error
2426 let httpStatusCode : Int ?
2527}
2628
29+ enum HttpMethods
30+ {
31+ case get
32+ case post
33+ case put
34+ case delete
35+ }
36+
2737struct HttpUtility
2838{
2939 private var _token : String ? = nil
30- private var _dateFormatter : DateFormatter ? = nil
40+ private var _customerJSONDecoder : JSONDecoder ? = nil
3141
3242 init ( token: String ? ) {
3343 _token = token
3444 }
35-
36- init ( dateFormatter: DateFormatter ) {
37- _dateFormatter = dateFormatter
38- }
39-
40- init ( token: String , dateFormatter: DateFormatter )
41- {
45+
46+ init ( token: String ? , decoder: JSONDecoder ? ) {
4247 _token = token
43- _dateFormatter = dateFormatter
48+ _customerJSONDecoder = decoder
49+ }
50+
51+ init ( WithJsonDecoder decoder: JSONDecoder ) {
52+ _customerJSONDecoder = decoder
4453 }
4554
4655 init ( ) { }
47-
48- func getData < T: Decodable > ( requestUrl: URL , resultType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
56+
57+ func request < T: Decodable > ( requestUrl: URL , method : HttpMethods , requestBody : Data ? = nil , resultType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
4958 {
50-
51- var urlRequest = createUrlRequest ( requestUrl: requestUrl)
52- urlRequest. httpMethod = HttpMethodType . GET
53-
54- URLSession . shared. dataTask ( with: requestUrl) { ( responseData, httpUrlResponse, error) in
55-
56- //todo: this code can be added into a common function
57- let statusCode = ( httpUrlResponse as? HTTPURLResponse ) ? . statusCode
58- if ( error == nil && responseData != nil && responseData? . count != 0 )
59- {
60- let decoder = self . createJsonDecoder ( )
61- do
62- {
63- let result = try decoder. decode ( T . self, from: responseData!)
64- completionHandler ( . success( result) )
65- }
66- catch let error
67- {
68- debugPrint ( error)
69- completionHandler ( . failure( NetworkError ( reason: error. localizedDescription, httpStatusCode: statusCode) ) )
70- }
71- }
72- else
73- {
74- let error = NetworkError ( reason: error. debugDescription, httpStatusCode: statusCode)
75- completionHandler ( . failure( error) )
76- }
77-
78- } . resume ( )
59+ switch method
60+ {
61+ case . get:
62+ getData ( requestUrl: requestUrl, resultType: T . self) { completionHandler ( $0) }
63+ break
64+
65+ case . post:
66+ postData ( requestUrl: requestUrl, requestBody: requestBody!, resultType: T . self) { completionHandler ( $0) }
67+ break
68+
69+ case . put:
70+ putData ( requestUrl: requestUrl, resultType: T . self) { completionHandler ( $0) }
71+ break
72+
73+ case . delete:
74+ deleteData ( requestUrl: requestUrl, resultType: T . self) { completionHandler ( $0) }
75+ break
76+ }
7977 }
80-
81- // MARK: - Post Api
82- func postData < T : Decodable > ( requestUrl : URL , requestBody : Data , resultType : T . Type , completionHandler : @escaping ( Result < T ? , NetworkError > ) -> Void )
78+
79+ // MARK: - Private functions
80+ private func createJsonDecoder ( ) -> JSONDecoder
8381 {
84- var urlRequest = createUrlRequest ( requestUrl: requestUrl)
85- urlRequest. httpMethod = HttpMethodType . POST
86- urlRequest. httpBody = requestBody
87- urlRequest. addValue ( " application/json " , forHTTPHeaderField: HttpHeaderFields . contentType)
88-
89- URLSession . shared. dataTask ( with: urlRequest) { ( data, httpUrlResponse, error) in
90- let statusCode = ( httpUrlResponse as? HTTPURLResponse ) ? . statusCode
91- if ( error == nil && data != nil && data? . count != 0 )
92- {
93- do {
94-
95- let decoder = self . createJsonDecoder ( )
96- let response = try decoder. decode ( T . self, from: data!)
97- completionHandler ( . success( response) )
98- }
99- catch let decodingError
100- {
101- debugPrint ( decodingError)
102- let networkError = NetworkError ( reason: decodingError. localizedDescription, httpStatusCode: statusCode)
103- completionHandler ( . failure( networkError) )
104- }
105- }
106- else
107- {
108- let error = NetworkError ( reason: error. debugDescription, httpStatusCode: statusCode)
109- completionHandler ( . failure( error) )
110- }
111-
112- } . resume ( )
82+ let decoder = _customerJSONDecoder != nil ? _customerJSONDecoder! : JSONDecoder ( )
83+ if ( _customerJSONDecoder == nil )
84+ {
85+ decoder. dateDecodingStrategy = . iso8601
86+ }
87+ return decoder
11388 }
11489
115- func postMultipartFormData < T : Decodable > ( requestUrl: URL , multiPartRequestBody : Data , resultType : T . Type , completionHandler : @escaping ( Result < T ? , NetworkError > ) -> Void )
90+ private func createUrlRequest ( requestUrl: URL ) -> URLRequest
11691 {
11792 var urlRequest = URLRequest ( url: requestUrl)
93+ if ( _token != nil )
94+ {
95+ urlRequest. addValue ( _token!, forHTTPHeaderField: " authorization " )
96+ }
11897
119- urlRequest. httpMethod = HttpMethodType . POST
120-
121- let boundary = " --------------------------------- \( UUID ( ) . uuidString) "
122- urlRequest. addValue ( " multipart/form-data; boundary= \( boundary) " , forHTTPHeaderField: " content-type " )
123- urlRequest. addValue ( " \( multiPartRequestBody. count) " , forHTTPHeaderField: " content-length " )
124- urlRequest. httpBody = multiPartRequestBody
125-
126- debugPrint ( " multipart form data => \( String ( describing: String ( data: multiPartRequestBody, encoding: . utf8) ) ) " )
127-
128- URLSession . shared. dataTask ( with: urlRequest) { ( data, httpUrlResponse, error) in
98+ return urlRequest
99+ }
100+
101+ private func decodeJsonResponse< T: Decodable > ( data: Data , responseType: T . Type ) -> T ?
102+ {
103+ let decoder = self . createJsonDecoder ( )
104+ do {
105+ return try decoder. decode ( T . self, from: data)
106+ } catch let error{
107+ debugPrint ( " deocding error => \( error) " )
108+ }
109+ return nil
110+ }
111+
112+ private func performOperation< T: Decodable > ( requestUrl: URLRequest , responseType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
113+ {
114+ URLSession . shared. dataTask ( with: requestUrl) { ( data, httpUrlResponse, error) in
115+
129116 let statusCode = ( httpUrlResponse as? HTTPURLResponse ) ? . statusCode
130117 if ( error == nil && data != nil && data? . count != 0 )
131118 {
132- do {
133- let decoder = self . createJsonDecoder ( )
134- let response = try decoder . decode ( T . self , from : data! )
119+ let response = self . decodeJsonResponse ( data : data! , responseType : T . self )
120+
121+ if ( response != nil ) {
135122 completionHandler ( . success( response) )
136- }
137- catch let decodingError
138- {
139- debugPrint ( decodingError)
140- let networkError = NetworkError ( reason: decodingError. localizedDescription, httpStatusCode: statusCode)
141- completionHandler ( . failure( networkError) )
123+ } else {
124+ completionHandler ( . failure( NetworkError ( reason: " decoding error " , httpStatusCode: statusCode) ) )
142125 }
143126 }
144127 else
145128 {
146- debugPrint ( error. debugDescription)
147- let networkError = NetworkError ( reason: error. debugDescription, httpStatusCode: statusCode)
129+ let networkError = NetworkError ( reason: error. debugDescription, httpStatusCode: statusCode)
148130 completionHandler ( . failure( networkError) )
149131 }
150-
132+
151133 } . resume ( )
152-
153134 }
154-
155- // MARK: - Private functions
156- private func createJsonDecoder ( ) -> JSONDecoder
135+
136+ // MARK: - GET Api
137+ private func getData < T : Decodable > ( requestUrl : URL , resultType : T . Type , completionHandler : @escaping ( Result < T ? , NetworkError > ) -> Void )
157138 {
158- let decoder = JSONDecoder ( )
159- decoder. dateDecodingStrategy = _dateFormatter != nil ? . formatted( _dateFormatter!) : . iso8601
160- return decoder
139+ var urlRequest = createUrlRequest ( requestUrl: requestUrl)
140+ urlRequest. httpMethod = HttpMethod . get
141+
142+ performOperation ( requestUrl: urlRequest, responseType: T . self) { ( result) in
143+ completionHandler ( result)
144+ }
161145 }
162-
163- private func createUrlRequest( requestUrl: URL ) -> URLRequest
146+
147+ // MARK: - POST Api
148+ private func postData< T: Decodable > ( requestUrl: URL , requestBody: Data , resultType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
164149 {
165- var urlRequest = URLRequest ( url: requestUrl)
166- if ( _token != nil )
167- {
168- urlRequest. addValue ( _token!, forHTTPHeaderField: " authorization " )
150+ var urlRequest = createUrlRequest ( requestUrl: requestUrl)
151+ urlRequest. httpMethod = HttpMethod . post
152+ urlRequest. httpBody = requestBody
153+ urlRequest. addValue ( " application/json " , forHTTPHeaderField: HttpHeaderFields . contentType)
154+
155+ performOperation ( requestUrl: urlRequest, responseType: T . self) { ( result) in
156+ completionHandler ( result)
157+ }
158+ }
159+
160+ // MARK: - PUT Api
161+ private func putData< T: Decodable > ( requestUrl: URL , resultType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
162+ {
163+ var urlRequest = createUrlRequest ( requestUrl: requestUrl)
164+ urlRequest. httpMethod = HttpMethod . put
165+
166+ performOperation ( requestUrl: urlRequest, responseType: T . self) { ( result) in
167+ completionHandler ( result)
168+ }
169+ }
170+
171+ // MARK: - DELETE Api
172+ private func deleteData< T: Decodable > ( requestUrl: URL , resultType: T . Type , completionHandler: @escaping ( Result < T ? , NetworkError > ) -> Void )
173+ {
174+ var urlRequest = createUrlRequest ( requestUrl: requestUrl)
175+ urlRequest. httpMethod = HttpMethod . delete
176+
177+ performOperation ( requestUrl: urlRequest, responseType: T . self) { ( result) in
178+ completionHandler ( result)
169179 }
170-
171- return urlRequest
172180 }
173181}
0 commit comments