-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathObjectManager.swift
More file actions
executable file
·143 lines (98 loc) · 4.55 KB
/
Copy pathObjectManager.swift
File metadata and controls
executable file
·143 lines (98 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//
// ObjectManager.swift
// Requestum
//
// Created by Alex Kovalov on 3/20/18.
// Copyright © 2018 Requestum. All rights reserved.
//
import Foundation
import Alamofire
import AlamofireNetworkActivityIndicator
import ObjectMapper
import HTTPStatusCodes
typealias JSON = [String: Any]
typealias JSONArray = [[String: Any]]
class ObjectManager {
var isUpdateToken: Bool = false
public let manager: Alamofire.SessionManager
public static var adapter: ((URLRequest) -> URLRequest)?
private let lock = NSLock()
private var requestsToRetry: [RequestRetryCompletion] = []
public init(manager: Alamofire.SessionManager = Alamofire.SessionManager.default) {
self.manager = manager
self.manager.adapter = self
self.manager.retrier = self
}
func headers() -> HTTPHeaders {
var headers: HTTPHeaders = [:]
headers["Content-Type"] = "application/json"
headers["Cookie"] = ""
return headers
}
func request(_ method: HTTPMethod,
serverAPI: ServerAPI,
parameters: Parameters? = nil,
urlParameters: [String: String]? = nil,
encoding: ParameterEncoding = JSONEncoding.default) -> DataRequest {
let dataRequest = manager.request(serverAPI.fullURL, method: method, parameters: parameters, encoding: encoding, headers: headers())
return dataRequest.validate { urlRequest, urlResponse, data -> Request.ValidationResult in
return self.validate(urlRequest: urlRequest, httpUrlResponce: urlResponse, data: data)
}
}
}
// MARK: - RequestRetrier, RequestAdapter
extension ObjectManager: RequestRetrier, RequestAdapter {
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse,
response.statusCode == HTTPStatusCode.unauthorized.rawValue || response.statusCode == HTTPStatusCode.forbidden.rawValue {
requestsToRetry.append(completion)
guard !isUpdateToken else {
return
}
isUpdateToken = true
UserManager.shared.refreshToken { [weak self] error in
self?.isUpdateToken = false
guard error == nil else {
self?.requestsToRetry.forEach { $0(false, 0.0) }
self?.requestsToRetry.removeAll()
App.logout()
return
}
guard let strongSelf = self else {
return
}
strongSelf.lock.lock(); defer { strongSelf.lock.unlock() }
strongSelf.requestsToRetry.forEach { $0(true, 0.0) }
strongSelf.requestsToRetry.removeAll()
}
} else {
completion(false, 0.0)
}
}
public func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
if let token = Token.token, let type = token.tokenType, let str = token.accessToken {
var urlRequest = urlRequest
urlRequest.setValue(type + " " + str, forHTTPHeaderField: "Authorization")
return urlRequest
} else if let token = Token.token, let type = token.tokenType, let str = token.accessToken {
var urlRequest = urlRequest
urlRequest.setValue(type + " " + str, forHTTPHeaderField: "Authorization")
return urlRequest
}
return urlRequest
}
}
// MARK: - Validation
extension ObjectManager {
func validate(urlRequest: URLRequest?, httpUrlResponce: HTTPURLResponse, data: Data?) -> Request.ValidationResult {
if httpUrlResponce.statusCode == HTTPStatusCode.unauthorized.rawValue {
return Request.ValidationResult.failure(NSError.refreshTokenError())
} else if Array(200..<300).contains(httpUrlResponce.statusCode) {
return Request.ValidationResult.success
} else {
let reason: AFError.ResponseValidationFailureReason = .unacceptableStatusCode(code: httpUrlResponce.statusCode)
return .failure(AFError.responseValidationFailed(reason: reason))
}
}
}