服务商获取权限失败的话retry,更换了首页的背景图
This commit is contained in:
Binary file not shown.
@@ -3569,22 +3569,6 @@
|
|||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "13D4EEB2-43B5-4060-973F-6B3853959DB1"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "37"
|
|
||||||
endingLineNumber = "37"
|
|
||||||
landmarkName = "init()"
|
|
||||||
landmarkType = "7">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
@@ -4845,22 +4829,6 @@
|
|||||||
</Locations>
|
</Locations>
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "DD1381E7-616D-4126-9D53-127EE8F3C58D"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "45"
|
|
||||||
endingLineNumber = "45"
|
|
||||||
landmarkName = "init()"
|
|
||||||
landmarkType = "7">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
@@ -4873,23 +4841,7 @@
|
|||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "35"
|
startingLineNumber = "35"
|
||||||
endingLineNumber = "35"
|
endingLineNumber = "35"
|
||||||
landmarkName = "post(urlString:parameters:encoding:headers:responseType:)"
|
landmarkName = "post(urlString:parameters:encoding:headers:responseType:completionHandler:)"
|
||||||
landmarkType = "7">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "A9FCC6E5-032F-4920-BD1A-EE1CA080F8C3"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "118"
|
|
||||||
endingLineNumber = "118"
|
|
||||||
landmarkName = "init()"
|
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
@@ -4903,8 +4855,8 @@
|
|||||||
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "36"
|
startingLineNumber = "33"
|
||||||
endingLineNumber = "36"
|
endingLineNumber = "33"
|
||||||
landmarkName = "init()"
|
landmarkName = "init()"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
<Locations>
|
<Locations>
|
||||||
@@ -4941,5 +4893,101 @@
|
|||||||
</Locations>
|
</Locations>
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "CDB1B968-1B96-47AF-8588-145C7DCA8DDA"
|
||||||
|
shouldBeEnabled = "No"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "46"
|
||||||
|
endingLineNumber = "46"
|
||||||
|
landmarkName = "init()"
|
||||||
|
landmarkType = "7">
|
||||||
|
<Locations>
|
||||||
|
<Location
|
||||||
|
uuid = "CDB1B968-1B96-47AF-8588-145C7DCA8DDA - 57f4233fc3fbba6c"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "OrderScheduling.UserPermission.init() -> OrderScheduling.UserPermission"
|
||||||
|
moduleName = "OrderScheduling"
|
||||||
|
usesParentBreakpointCondition = "Yes"
|
||||||
|
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "47"
|
||||||
|
endingLineNumber = "47"
|
||||||
|
offsetFromSymbolStart = "1476">
|
||||||
|
</Location>
|
||||||
|
<Location
|
||||||
|
uuid = "CDB1B968-1B96-47AF-8588-145C7DCA8DDA - f350e9cccc58bb60"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "closure #5 (Swift.Optional<OrderScheduling.ResponseModel<Swift.Array<Swift.String>>>) -> () in OrderScheduling.UserPermission.init() -> OrderScheduling.UserPermission"
|
||||||
|
moduleName = "OrderScheduling"
|
||||||
|
usesParentBreakpointCondition = "Yes"
|
||||||
|
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "47"
|
||||||
|
endingLineNumber = "47"
|
||||||
|
offsetFromSymbolStart = "44">
|
||||||
|
</Location>
|
||||||
|
</Locations>
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "B9BCBB10-2C21-4C80-952B-A48BD5461765"
|
||||||
|
shouldBeEnabled = "No"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "115"
|
||||||
|
endingLineNumber = "115"
|
||||||
|
landmarkName = "init()"
|
||||||
|
landmarkType = "7">
|
||||||
|
<Locations>
|
||||||
|
<Location
|
||||||
|
uuid = "B9BCBB10-2C21-4C80-952B-A48BD5461765 - f350e9cccc5880e2"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "closure #5 (Swift.Optional<OrderScheduling.ResponseModel<Swift.Array<Swift.String>>>) -> () in OrderScheduling.UserPermission.init() -> OrderScheduling.UserPermission"
|
||||||
|
moduleName = "OrderScheduling"
|
||||||
|
usesParentBreakpointCondition = "Yes"
|
||||||
|
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "113"
|
||||||
|
endingLineNumber = "113"
|
||||||
|
offsetFromSymbolStart = "5256">
|
||||||
|
</Location>
|
||||||
|
<Location
|
||||||
|
uuid = "B9BCBB10-2C21-4C80-952B-A48BD5461765 - 866a31bf155da6"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "closure #8 (Swift.String) -> Swift.Bool in closure #5 (Swift.Optional<OrderScheduling.ResponseModel<Swift.Array<Swift.String>>>) -> () in OrderScheduling.UserPermission.init() -> OrderScheduling.UserPermission"
|
||||||
|
moduleName = "OrderScheduling"
|
||||||
|
usesParentBreakpointCondition = "Yes"
|
||||||
|
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Global/User/UserPermission.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "113"
|
||||||
|
endingLineNumber = "113"
|
||||||
|
offsetFromSymbolStart = "92">
|
||||||
|
</Location>
|
||||||
|
</Locations>
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
</Breakpoints>
|
</Breakpoints>
|
||||||
</Bucket>
|
</Bucket>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 221 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 379 KiB After Width: | Height: | Size: 373 KiB |
@@ -25,103 +25,94 @@ open class UserPermission {
|
|||||||
public var canSupplierRemarkBtn : Bool = false
|
public var canSupplierRemarkBtn : Bool = false
|
||||||
public var canSupplierAuditEditCostBtn : Bool = false
|
public var canSupplierAuditEditCostBtn : Bool = false
|
||||||
public var canSupplierAuditUploadPhotoBtn : Bool = false
|
public var canSupplierAuditUploadPhotoBtn : Bool = false
|
||||||
lazy private var alert = CommonAlertView()
|
|
||||||
|
private let maxRetryCount = 120
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
Observable.combineLatest(relay, USER.refreshTokenSub)
|
Observable.combineLatest(relay, USER.refreshTokenSub)
|
||||||
.observe(on: MainScheduler.instance)
|
|
||||||
.do(onNext: { (_,_) in
|
|
||||||
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_showHUD()
|
|
||||||
})
|
|
||||||
.flatMapLatest { (_,_) in
|
.flatMapLatest { (_,_) in
|
||||||
return RQ.userOperationPermissions()
|
return RQ.userOperationPermissions()
|
||||||
}
|
}
|
||||||
.observe(on: MainScheduler.instance)
|
.retry(when: { (rxError: Observable<Error>) -> Observable<Int> in
|
||||||
.do(onNext: { _ in
|
return rxError.enumerated().flatMap({[weak self] (index,error) -> Observable<Int> in
|
||||||
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_hideHUD()
|
guard index < (self?.maxRetryCount ?? 0) else {
|
||||||
|
return Observable.error(error)
|
||||||
|
}
|
||||||
|
return Observable.timer(RxTimeInterval.seconds(5), scheduler: MainScheduler.instance)
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.observe(on: MainScheduler.instance)
|
.observe(on: MainScheduler.instance)
|
||||||
.subscribe(onNext: {[weak self] response in
|
.subscribe(onNext: {[weak self] response in
|
||||||
if response?.success == true {
|
if response?.success == true {
|
||||||
self?.canRejectDispatchHandle = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.rejectDispatchHandle.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.rejectDispatchHandle.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canRejectDispatchHandle = true
|
self?.canRejectDispatchHandle = true
|
||||||
|
}else{
|
||||||
|
self?.canRejectDispatchHandle = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canAcceptDispatchHandle = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.acceptDispatchHandle.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.acceptDispatchHandle.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canAcceptDispatchHandle = true
|
self?.canAcceptDispatchHandle = true
|
||||||
|
}else{
|
||||||
|
self?.canAcceptDispatchHandle = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canWaitdispatchBtn = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.waitdispatchBtn.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.waitdispatchBtn.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canWaitdispatchBtn = true
|
self?.canWaitdispatchBtn = true
|
||||||
|
}else{
|
||||||
|
self?.canWaitdispatchBtn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canWaitModifyDispatchBtn = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.waitModifyDispatchBtn.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.waitModifyDispatchBtn.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canWaitModifyDispatchBtn = true
|
self?.canWaitModifyDispatchBtn = true
|
||||||
|
}else{
|
||||||
|
self?.canWaitModifyDispatchBtn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canDealWith = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.dealWith.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.dealWith.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canDealWith = true
|
self?.canDealWith = true
|
||||||
|
}else{
|
||||||
|
self?.canDealWith = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canSupplierRemarkBtn = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.supplierRemarkBtn.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.supplierRemarkBtn.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canSupplierRemarkBtn = true
|
self?.canSupplierRemarkBtn = true
|
||||||
|
}else{
|
||||||
|
self?.canSupplierRemarkBtn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canSupplierAuditEditCostBtn = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.supplierAuditEditCostBtn.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.supplierAuditEditCostBtn.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canSupplierAuditEditCostBtn = true
|
self?.canSupplierAuditEditCostBtn = true
|
||||||
|
}else{
|
||||||
|
self?.canSupplierAuditEditCostBtn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.canSupplierAuditUploadPhotoBtn = false
|
|
||||||
if response?.data?.contains(where: { value in
|
if response?.data?.contains(where: { value in
|
||||||
value == UserOperationPermissionsDataModel.DataEnum.supplierAuditUploadPhotoBtn.rawValue
|
value == UserOperationPermissionsDataModel.DataEnum.supplierAuditUploadPhotoBtn.rawValue
|
||||||
}) == true {
|
}) == true {
|
||||||
self?.canSupplierAuditUploadPhotoBtn = true
|
self?.canSupplierAuditUploadPhotoBtn = true
|
||||||
|
}else{
|
||||||
|
self?.canSupplierAuditUploadPhotoBtn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.userPermissionRelay.accept(response?.data)
|
self?.userPermissionRelay.accept(response?.data)
|
||||||
}else{
|
|
||||||
if let alert = self?.alert {
|
|
||||||
alert.contentLabel.text = notObtainUserPermissions
|
|
||||||
ENTRY.showUserPermissionsEntry(view: alert,name: notObtainUserPermissionsEntry)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
},onError: { error in
|
||||||
.disposed(by: disposeBag)
|
|
||||||
|
|
||||||
alert.sureButton.rx.tap
|
|
||||||
.observe(on: MainScheduler.instance)
|
|
||||||
.subscribe(onNext: {[weak self] _ in
|
|
||||||
ENTRY.dismiss(name: notObtainUserPermissionsEntry) {[weak self] in
|
|
||||||
self?.relay.accept(nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.disposed(by: disposeBag)
|
|
||||||
|
|
||||||
alert.cancelButton.rx.tap
|
|
||||||
.observe(on: MainScheduler.instance)
|
|
||||||
.subscribe(onNext: { _ in
|
|
||||||
exit(0)
|
|
||||||
})
|
})
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ public let RQ = RequestList.default
|
|||||||
open class RequestList {
|
open class RequestList {
|
||||||
public static let `default` = RequestList()
|
public static let `default` = RequestList()
|
||||||
|
|
||||||
|
struct DDError : Error {
|
||||||
|
}
|
||||||
|
|
||||||
func tokenHeader() -> HTTPHeader {
|
func tokenHeader() -> HTTPHeader {
|
||||||
let httpHeader = HTTPHeader.init(name: "Authorization", value: USER.token ?? "")
|
let httpHeader = HTTPHeader.init(name: "Authorization", value: USER.token ?? "")
|
||||||
return httpHeader
|
return httpHeader
|
||||||
@@ -109,7 +112,13 @@ open class RequestList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func userOperationPermissions() -> Single<ResponseModel<[String]>?> {
|
func userOperationPermissions() -> Single<ResponseModel<[String]>?> {
|
||||||
return DDAF.post(urlString: HOST+API.userOperationPermissions,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<[String]>.self)
|
return DDAF.post(urlString: HOST+API.userOperationPermissions,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<[String]>.self) { single, response in
|
||||||
|
if response.value?.success == true {
|
||||||
|
single(.success(response.value))
|
||||||
|
}else{
|
||||||
|
single(.failure(DDError()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func vehicleLogout<P:Encodable>(parameters:P) -> Single<ResponseModel<String>?> {
|
func vehicleLogout<P:Encodable>(parameters:P) -> Single<ResponseModel<String>?> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Alamofire (5.7.1)
|
- Alamofire (5.8.1)
|
||||||
- AMapFoundation-NO-IDFA (1.8.2)
|
- AMapFoundation-NO-IDFA (1.8.2)
|
||||||
- AMapLocation-NO-IDFA (2.9.0):
|
- AMapLocation-NO-IDFA (2.9.0):
|
||||||
- AMapFoundation-NO-IDFA (>= 1.7.0)
|
- AMapFoundation-NO-IDFA (>= 1.7.0)
|
||||||
@@ -270,7 +270,7 @@ PODS:
|
|||||||
- DDLogKit_Private
|
- DDLogKit_Private
|
||||||
- DDMAMapKit_Private/DDMAUtil (0.1.5):
|
- DDMAMapKit_Private/DDMAUtil (0.1.5):
|
||||||
- DDMAMapKit_Private/DDMAMap
|
- DDMAMapKit_Private/DDMAMap
|
||||||
- DDNetworkingOfAlamofireKit_Private (0.1.8):
|
- DDNetworkingOfAlamofireKit_Private (0.2.1):
|
||||||
- Alamofire
|
- Alamofire
|
||||||
- DDLogKit_Private
|
- DDLogKit_Private
|
||||||
- RxSwift
|
- RxSwift
|
||||||
@@ -412,7 +412,7 @@ SPEC REPOS:
|
|||||||
- ZLPhotoBrowser
|
- ZLPhotoBrowser
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: 0123a34370cb170936ae79a8df46cc62b2edeb88
|
Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7
|
||||||
AMapFoundation-NO-IDFA: 6ce0ef596d4eb8d934ff498e56747b6de1247b05
|
AMapFoundation-NO-IDFA: 6ce0ef596d4eb8d934ff498e56747b6de1247b05
|
||||||
AMapLocation-NO-IDFA: 6839d1543b3138ae594ddd36ab72741dc87df66f
|
AMapLocation-NO-IDFA: 6839d1543b3138ae594ddd36ab72741dc87df66f
|
||||||
AMapNavi-NO-IDFA: 70c724400376bfadcb8ec08b9761f526096cfdb6
|
AMapNavi-NO-IDFA: 70c724400376bfadcb8ec08b9761f526096cfdb6
|
||||||
@@ -430,7 +430,7 @@ SPEC CHECKSUMS:
|
|||||||
DDFontKit_Private: 7b8f4ebf0f60622874036202734d8460dc7b3806
|
DDFontKit_Private: 7b8f4ebf0f60622874036202734d8460dc7b3806
|
||||||
DDLogKit_Private: 1ed442cc7be004bd05f27bfda9b525e113df54e0
|
DDLogKit_Private: 1ed442cc7be004bd05f27bfda9b525e113df54e0
|
||||||
DDMAMapKit_Private: b378d69f693d6998d136155cd5c81be2e4545fae
|
DDMAMapKit_Private: b378d69f693d6998d136155cd5c81be2e4545fae
|
||||||
DDNetworkingOfAlamofireKit_Private: d65c96f99bc59311d374e7b7a7e8a9e042d9b5ea
|
DDNetworkingOfAlamofireKit_Private: 652eb70a7d8bac81d77d036fabeb52f807120f6d
|
||||||
DDPersistenceKit_Private: c150822543ffa6ece3900178629812f64902ed90
|
DDPersistenceKit_Private: c150822543ffa6ece3900178629812f64902ed90
|
||||||
DDProgressHUDKit_Private: 1e219062ddeb7801a4bb13b367efa1f3fbf17f1e
|
DDProgressHUDKit_Private: 1e219062ddeb7801a4bb13b367efa1f3fbf17f1e
|
||||||
DDTimerSwiftKit_Private: cce3fe58b1b581fe4cddb3fb84fcde31b4e83541
|
DDTimerSwiftKit_Private: cce3fe58b1b581fe4cddb3fb84fcde31b4e83541
|
||||||
|
|||||||
57
Pods/Alamofire/README.md
generated
57
Pods/Alamofire/README.md
generated
@@ -1,11 +1,10 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://img.shields.io/badge/Swift-5.5_5.6_5.7_5.8-Orange?style=flat-square)
|
[](https://img.shields.io/badge/Swift-5.6_5.7_5.8_5.9-Orange?style=flat-square)
|
||||||
[](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_Linux_Windows-Green?style=flat-square)
|
[](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_vision_OS_Linux_Windows_Android-Green?style=flat-square)
|
||||||
[](https://img.shields.io/cocoapods/v/Alamofire.svg)
|
[](https://img.shields.io/cocoapods/v/Alamofire.svg)
|
||||||
[](https://github.com/Carthage/Carthage)
|
[](https://github.com/Carthage/Carthage)
|
||||||
[](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)
|
[](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)
|
||||||
[](https://twitter.com/AlamofireSF)
|
|
||||||
[](https://forums.swift.org/c/related-projects/alamofire/37)
|
[](https://forums.swift.org/c/related-projects/alamofire/37)
|
||||||
|
|
||||||
Alamofire is an HTTP networking library written in Swift.
|
Alamofire is an HTTP networking library written in Swift.
|
||||||
@@ -52,6 +51,33 @@ Alamofire is an HTTP networking library written in Swift.
|
|||||||
- [x] Comprehensive Unit and Integration Test Coverage
|
- [x] Comprehensive Unit and Integration Test Coverage
|
||||||
- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
|
- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
|
||||||
|
|
||||||
|
## Write Requests Fast!
|
||||||
|
|
||||||
|
Alamofire's compact syntax and extensive feature set allow requests with powerful features like automatic retry to be written in just a few lines of code.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
// Automatic String to URL conversion, Swift concurrency support, and automatic retry.
|
||||||
|
let response = await AF.request("https://httpbin.org/get", interceptor: .retryPolicy)
|
||||||
|
// Automatic HTTP Basic Auth.
|
||||||
|
.authenticate(username: "user", password: "pass")
|
||||||
|
// Caching customization.
|
||||||
|
.cacheResponse(using: .cache)
|
||||||
|
// Redirect customization.
|
||||||
|
.redirect(using: .follow)
|
||||||
|
// Validate response code and Content-Type.
|
||||||
|
.validate()
|
||||||
|
// Produce a cURL command for the request.
|
||||||
|
.cURLDescription { description in
|
||||||
|
print(description)
|
||||||
|
}
|
||||||
|
// Automatic Decodable support with background parsing.
|
||||||
|
.serializingDecodable(DecodableType.self)
|
||||||
|
// Await the full response with metrics and a parsed body.
|
||||||
|
.response
|
||||||
|
// Detailed response description for easy debugging.
|
||||||
|
debugPrint(response)
|
||||||
|
```
|
||||||
|
|
||||||
## Component Libraries
|
## Component Libraries
|
||||||
|
|
||||||
In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
|
In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
|
||||||
@@ -61,21 +87,23 @@ In order to keep Alamofire focused specifically on core networking implementatio
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
| Platform | Minimum Swift Version | Installation | Status |
|
| Platform | Minimum Swift Version | Installation | Status |
|
||||||
| --- | --- | --- | --- |
|
| ---------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
||||||
| iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ | 5.5 | [CocoaPods](#cocoapods), [Carthage](#carthage), [Swift Package Manager](#swift-package-manager), [Manual](#manually) | Fully Tested |
|
| iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ | 5.6 | [CocoaPods](#cocoapods), [Carthage](#carthage), [Swift Package Manager](#swift-package-manager), [Manual](#manually) | Fully Tested |
|
||||||
| Linux | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
|
| Linux | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
|
||||||
| Windows | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
|
| Windows | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
|
||||||
|
| Android | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
|
||||||
|
|
||||||
#### Known Issues on Linux and Windows
|
#### Known Issues on Linux and Windows
|
||||||
|
|
||||||
Alamofire builds on Linux and Windows but there are missing features and many issues in the underlying `swift-corelibs-foundation` that prevent full functionality and may cause crashes. These include:
|
Alamofire builds on Linux, Windows, and Android but there are missing features and many issues in the underlying `swift-corelibs-foundation` that prevent full functionality and may cause crashes. These include:
|
||||||
|
|
||||||
- `ServerTrustManager` and associated certificate functionality is unavailable, so there is no certificate pinning and no client certificate support.
|
- `ServerTrustManager` and associated certificate functionality is unavailable, so there is no certificate pinning and no client certificate support.
|
||||||
- Various methods of HTTP authentication may crash, including HTTP Basic and HTTP Digest. Crashes may occur if responses contain server challenges.
|
- Various methods of HTTP authentication may crash, including HTTP Basic and HTTP Digest. Crashes may occur if responses contain server challenges.
|
||||||
- Cache control through `CachedResponseHandler` and associated APIs is unavailable, as the underlying delegate methods aren't called.
|
- Cache control through `CachedResponseHandler` and associated APIs is unavailable, as the underlying delegate methods aren't called.
|
||||||
- `URLSessionTaskMetrics` are never gathered.
|
- `URLSessionTaskMetrics` are never gathered.
|
||||||
|
|
||||||
Due to these issues, Alamofire is unsupported on Linux and Windows. Please report any crashes to the [Swift bug reporter](https://bugs.swift.org).
|
Due to these issues, Alamofire is unsupported on Linux, Windows, and Android. Please report any crashes to the [Swift bug reporter](https://bugs.swift.org).
|
||||||
|
|
||||||
## Migration Guides
|
## Migration Guides
|
||||||
|
|
||||||
@@ -85,6 +113,7 @@ Due to these issues, Alamofire is unsupported on Linux and Windows. Please repor
|
|||||||
- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
|
- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
|
||||||
|
|
||||||
## Communication
|
## Communication
|
||||||
|
|
||||||
- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
|
- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
|
||||||
- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
|
- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
|
||||||
- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
|
- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
|
||||||
@@ -118,7 +147,7 @@ Once you have your Swift package set up, adding Alamofire as a dependency is as
|
|||||||
|
|
||||||
```swift
|
```swift
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.6.4"))
|
.package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.8.1"))
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -142,7 +171,7 @@ If you prefer not to use any of the aforementioned dependency managers, you can
|
|||||||
|
|
||||||
- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
|
- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
|
||||||
|
|
||||||
> It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
|
> It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
|
||||||
|
|
||||||
- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
|
- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
|
||||||
- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
|
- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
|
||||||
@@ -150,11 +179,11 @@ If you prefer not to use any of the aforementioned dependency managers, you can
|
|||||||
- Click on the `+` button under the "Embedded Binaries" section.
|
- Click on the `+` button under the "Embedded Binaries" section.
|
||||||
- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
|
- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
|
||||||
|
|
||||||
> It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
|
> It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
|
||||||
|
|
||||||
- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
|
- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
|
||||||
|
|
||||||
> You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS`, or `Alamofire watchOS`.
|
> You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS`, or `Alamofire watchOS`.
|
||||||
|
|
||||||
- And that's it!
|
- And that's it!
|
||||||
|
|
||||||
|
|||||||
20
Pods/Alamofire/Source/AFError.swift
generated
20
Pods/Alamofire/Source/AFError.swift
generated
@@ -24,6 +24,10 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
#if canImport(Security)
|
||||||
|
import Security
|
||||||
|
#endif
|
||||||
|
|
||||||
/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
|
/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
|
||||||
/// their own associated reasons.
|
/// their own associated reasons.
|
||||||
public enum AFError: Error {
|
public enum AFError: Error {
|
||||||
@@ -129,7 +133,7 @@ public enum AFError: Error {
|
|||||||
case invalidEmptyResponse(type: String)
|
case invalidEmptyResponse(type: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// Underlying reason a server trust evaluation error occurred.
|
/// Underlying reason a server trust evaluation error occurred.
|
||||||
public enum ServerTrustFailureReason {
|
public enum ServerTrustFailureReason {
|
||||||
/// The output of a server trust evaluation.
|
/// The output of a server trust evaluation.
|
||||||
@@ -211,7 +215,7 @@ public enum AFError: Error {
|
|||||||
case responseValidationFailed(reason: ResponseValidationFailureReason)
|
case responseValidationFailed(reason: ResponseValidationFailureReason)
|
||||||
/// Response serialization failed.
|
/// Response serialization failed.
|
||||||
case responseSerializationFailed(reason: ResponseSerializationFailureReason)
|
case responseSerializationFailed(reason: ResponseSerializationFailureReason)
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// `ServerTrustEvaluating` instance threw an error during trust evaluation.
|
/// `ServerTrustEvaluating` instance threw an error during trust evaluation.
|
||||||
case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
|
case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
|
||||||
#endif
|
#endif
|
||||||
@@ -314,7 +318,7 @@ extension AFError {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
|
/// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
|
||||||
/// contain the associated value.
|
/// contain the associated value.
|
||||||
public var isServerTrustEvaluationError: Bool {
|
public var isServerTrustEvaluationError: Bool {
|
||||||
@@ -393,7 +397,7 @@ extension AFError {
|
|||||||
return reason.underlyingError
|
return reason.underlyingError
|
||||||
case let .responseSerializationFailed(reason):
|
case let .responseSerializationFailed(reason):
|
||||||
return reason.underlyingError
|
return reason.underlyingError
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
case let .serverTrustEvaluationFailed(reason):
|
case let .serverTrustEvaluationFailed(reason):
|
||||||
return reason.underlyingError
|
return reason.underlyingError
|
||||||
#endif
|
#endif
|
||||||
@@ -451,7 +455,7 @@ extension AFError {
|
|||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// The download resume data of any underlying network error. Only produced by `DownloadRequest`s.
|
/// The download resume data of any underlying network error. Only produced by `DownloadRequest`s.
|
||||||
public var downloadResumeData: Data? {
|
public var downloadResumeData: Data? {
|
||||||
(underlyingError as? URLError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data
|
(underlyingError as? URLError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data
|
||||||
@@ -610,7 +614,7 @@ extension AFError.ResponseSerializationFailureReason {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
extension AFError.ServerTrustFailureReason {
|
extension AFError.ServerTrustFailureReason {
|
||||||
var output: AFError.ServerTrustFailureReason.Output? {
|
var output: AFError.ServerTrustFailureReason.Output? {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -688,7 +692,7 @@ extension AFError: LocalizedError {
|
|||||||
"""
|
"""
|
||||||
case let .sessionInvalidated(error):
|
case let .sessionInvalidated(error):
|
||||||
return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
|
return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
case let .serverTrustEvaluationFailed(reason):
|
case let .serverTrustEvaluationFailed(reason):
|
||||||
return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
|
return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
|
||||||
#endif
|
#endif
|
||||||
@@ -822,7 +826,7 @@ extension AFError.ResponseValidationFailureReason {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
extension AFError.ServerTrustFailureReason {
|
extension AFError.ServerTrustFailureReason {
|
||||||
var localizedDescription: String {
|
var localizedDescription: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
|||||||
2
Pods/Alamofire/Source/Alamofire.swift
generated
2
Pods/Alamofire/Source/Alamofire.swift
generated
@@ -37,4 +37,4 @@ import Foundation
|
|||||||
public let AF = Session.default
|
public let AF = Session.default
|
||||||
|
|
||||||
/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
|
/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
|
||||||
let version = "5.7.1"
|
let version = "5.8.0"
|
||||||
|
|||||||
@@ -217,15 +217,14 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
|
|||||||
|
|
||||||
/// The `Credential` used to authenticate requests.
|
/// The `Credential` used to authenticate requests.
|
||||||
public var credential: Credential? {
|
public var credential: Credential? {
|
||||||
get { $mutableState.credential }
|
get { mutableState.credential }
|
||||||
set { $mutableState.credential = newValue }
|
set { mutableState.credential = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
let authenticator: AuthenticatorType
|
let authenticator: AuthenticatorType
|
||||||
let queue = DispatchQueue(label: "org.alamofire.authentication.inspector")
|
let queue = DispatchQueue(label: "org.alamofire.authentication.inspector")
|
||||||
|
|
||||||
@Protected
|
private let mutableState: Protected<MutableState>
|
||||||
private var mutableState: MutableState
|
|
||||||
|
|
||||||
// MARK: Initialization
|
// MARK: Initialization
|
||||||
|
|
||||||
@@ -242,13 +241,13 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
|
|||||||
credential: Credential? = nil,
|
credential: Credential? = nil,
|
||||||
refreshWindow: RefreshWindow? = RefreshWindow()) {
|
refreshWindow: RefreshWindow? = RefreshWindow()) {
|
||||||
self.authenticator = authenticator
|
self.authenticator = authenticator
|
||||||
mutableState = MutableState(credential: credential, refreshWindow: refreshWindow)
|
mutableState = Protected(MutableState(credential: credential, refreshWindow: refreshWindow))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Adapt
|
// MARK: Adapt
|
||||||
|
|
||||||
public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||||
let adaptResult: AdaptResult = $mutableState.write { mutableState in
|
let adaptResult: AdaptResult = mutableState.write { mutableState in
|
||||||
// Queue the adapt operation if a refresh is already in place.
|
// Queue the adapt operation if a refresh is already in place.
|
||||||
guard !mutableState.isRefreshing else {
|
guard !mutableState.isRefreshing else {
|
||||||
let operation = AdaptOperation(urlRequest: urlRequest, session: session, completion: completion)
|
let operation = AdaptOperation(urlRequest: urlRequest, session: session, completion: completion)
|
||||||
@@ -316,7 +315,7 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
mutableState.requestsToRetry.append(completion)
|
mutableState.requestsToRetry.append(completion)
|
||||||
|
|
||||||
guard !mutableState.isRefreshing else { return }
|
guard !mutableState.isRefreshing else { return }
|
||||||
@@ -340,7 +339,7 @@ public class AuthenticationInterceptor<AuthenticatorType>: RequestInterceptor wh
|
|||||||
// Dispatch to queue to hop out of the lock in case authenticator.refresh is implemented synchronously.
|
// Dispatch to queue to hop out of the lock in case authenticator.refresh is implemented synchronously.
|
||||||
queue.async {
|
queue.async {
|
||||||
self.authenticator.refresh(credential, for: session) { result in
|
self.authenticator.refresh(credential, for: session) { result in
|
||||||
self.$mutableState.write { mutableState in
|
self.mutableState.write { mutableState in
|
||||||
switch result {
|
switch result {
|
||||||
case let .success(credential):
|
case let .success(credential):
|
||||||
self.handleRefreshSuccess(credential, insideLock: &mutableState)
|
self.handleRefreshSuccess(credential, insideLock: &mutableState)
|
||||||
|
|||||||
35
Pods/Alamofire/Source/Combine.swift
generated
35
Pods/Alamofire/Source/Combine.swift
generated
@@ -22,7 +22,7 @@
|
|||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux))
|
#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux) || os(Android))
|
||||||
|
|
||||||
import Combine
|
import Combine
|
||||||
import Dispatch
|
import Dispatch
|
||||||
@@ -91,23 +91,22 @@ public struct DataResponsePublisher<Value>: Publisher {
|
|||||||
where Downstream.Input == Output {
|
where Downstream.Input == Output {
|
||||||
typealias Failure = Downstream.Failure
|
typealias Failure = Downstream.Failure
|
||||||
|
|
||||||
@Protected
|
private let downstream: Protected<Downstream?>
|
||||||
private var downstream: Downstream?
|
|
||||||
private let request: DataRequest
|
private let request: DataRequest
|
||||||
private let responseHandler: Handler
|
private let responseHandler: Handler
|
||||||
|
|
||||||
init(request: DataRequest, responseHandler: @escaping Handler, downstream: Downstream) {
|
init(request: DataRequest, responseHandler: @escaping Handler, downstream: Downstream) {
|
||||||
self.request = request
|
self.request = request
|
||||||
self.responseHandler = responseHandler
|
self.responseHandler = responseHandler
|
||||||
self.downstream = downstream
|
self.downstream = Protected(downstream)
|
||||||
}
|
}
|
||||||
|
|
||||||
func request(_ demand: Subscribers.Demand) {
|
func request(_ demand: Subscribers.Demand) {
|
||||||
assert(demand > 0)
|
assert(demand > 0)
|
||||||
|
|
||||||
guard let downstream = downstream else { return }
|
guard let downstream = downstream.read({ $0 }) else { return }
|
||||||
|
|
||||||
self.downstream = nil
|
self.downstream.write(nil)
|
||||||
responseHandler { response in
|
responseHandler { response in
|
||||||
_ = downstream.receive(response)
|
_ = downstream.receive(response)
|
||||||
downstream.receive(completion: .finished)
|
downstream.receive(completion: .finished)
|
||||||
@@ -116,7 +115,7 @@ public struct DataResponsePublisher<Value>: Publisher {
|
|||||||
|
|
||||||
func cancel() {
|
func cancel() {
|
||||||
request.cancel()
|
request.cancel()
|
||||||
downstream = nil
|
downstream.write(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,23 +311,22 @@ public struct DataStreamPublisher<Value>: Publisher {
|
|||||||
where Downstream.Input == Output {
|
where Downstream.Input == Output {
|
||||||
typealias Failure = Downstream.Failure
|
typealias Failure = Downstream.Failure
|
||||||
|
|
||||||
@Protected
|
private let downstream: Protected<Downstream?>
|
||||||
private var downstream: Downstream?
|
|
||||||
private let request: DataStreamRequest
|
private let request: DataStreamRequest
|
||||||
private let streamHandler: Handler
|
private let streamHandler: Handler
|
||||||
|
|
||||||
init(request: DataStreamRequest, streamHandler: @escaping Handler, downstream: Downstream) {
|
init(request: DataStreamRequest, streamHandler: @escaping Handler, downstream: Downstream) {
|
||||||
self.request = request
|
self.request = request
|
||||||
self.streamHandler = streamHandler
|
self.streamHandler = streamHandler
|
||||||
self.downstream = downstream
|
self.downstream = Protected(downstream)
|
||||||
}
|
}
|
||||||
|
|
||||||
func request(_ demand: Subscribers.Demand) {
|
func request(_ demand: Subscribers.Demand) {
|
||||||
assert(demand > 0)
|
assert(demand > 0)
|
||||||
|
|
||||||
guard let downstream = downstream else { return }
|
guard let downstream = downstream.read({ $0 }) else { return }
|
||||||
|
|
||||||
self.downstream = nil
|
self.downstream.write(nil)
|
||||||
streamHandler { stream in
|
streamHandler { stream in
|
||||||
_ = downstream.receive(stream)
|
_ = downstream.receive(stream)
|
||||||
if case .complete = stream.event {
|
if case .complete = stream.event {
|
||||||
@@ -339,7 +337,7 @@ public struct DataStreamPublisher<Value>: Publisher {
|
|||||||
|
|
||||||
func cancel() {
|
func cancel() {
|
||||||
request.cancel()
|
request.cancel()
|
||||||
downstream = nil
|
downstream.write(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,23 +460,22 @@ public struct DownloadResponsePublisher<Value>: Publisher {
|
|||||||
where Downstream.Input == Output {
|
where Downstream.Input == Output {
|
||||||
typealias Failure = Downstream.Failure
|
typealias Failure = Downstream.Failure
|
||||||
|
|
||||||
@Protected
|
private let downstream: Protected<Downstream?>
|
||||||
private var downstream: Downstream?
|
|
||||||
private let request: DownloadRequest
|
private let request: DownloadRequest
|
||||||
private let responseHandler: Handler
|
private let responseHandler: Handler
|
||||||
|
|
||||||
init(request: DownloadRequest, responseHandler: @escaping Handler, downstream: Downstream) {
|
init(request: DownloadRequest, responseHandler: @escaping Handler, downstream: Downstream) {
|
||||||
self.request = request
|
self.request = request
|
||||||
self.responseHandler = responseHandler
|
self.responseHandler = responseHandler
|
||||||
self.downstream = downstream
|
self.downstream = Protected(downstream)
|
||||||
}
|
}
|
||||||
|
|
||||||
func request(_ demand: Subscribers.Demand) {
|
func request(_ demand: Subscribers.Demand) {
|
||||||
assert(demand > 0)
|
assert(demand > 0)
|
||||||
|
|
||||||
guard let downstream = downstream else { return }
|
guard let downstream = downstream.read({ $0 }) else { return }
|
||||||
|
|
||||||
self.downstream = nil
|
self.downstream.write(nil)
|
||||||
responseHandler { response in
|
responseHandler { response in
|
||||||
_ = downstream.receive(response)
|
_ = downstream.receive(response)
|
||||||
downstream.receive(completion: .finished)
|
downstream.receive(completion: .finished)
|
||||||
@@ -487,7 +484,7 @@ public struct DownloadResponsePublisher<Value>: Publisher {
|
|||||||
|
|
||||||
func cancel() {
|
func cancel() {
|
||||||
request.cancel()
|
request.cancel()
|
||||||
downstream = nil
|
downstream.write(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
220
Pods/Alamofire/Source/Concurrency.swift
generated
220
Pods/Alamofire/Source/Concurrency.swift
generated
@@ -37,7 +37,7 @@ extension Request {
|
|||||||
/// - Returns: The `StreamOf<Progress>`.
|
/// - Returns: The `StreamOf<Progress>`.
|
||||||
public func uploadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
|
public func uploadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
|
||||||
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
uploadProgress(queue: .singleEventQueue) { progress in
|
uploadProgress(queue: underlyingQueue) { progress in
|
||||||
continuation.yield(progress)
|
continuation.yield(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ extension Request {
|
|||||||
/// - Returns: The `StreamOf<Progress>`.
|
/// - Returns: The `StreamOf<Progress>`.
|
||||||
public func downloadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
|
public func downloadProgress(bufferingPolicy: StreamOf<Progress>.BufferingPolicy = .unbounded) -> StreamOf<Progress> {
|
||||||
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
downloadProgress(queue: .singleEventQueue) { progress in
|
downloadProgress(queue: underlyingQueue) { progress in
|
||||||
continuation.yield(progress)
|
continuation.yield(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ extension Request {
|
|||||||
/// - Returns: The `StreamOf<URLRequest>`.
|
/// - Returns: The `StreamOf<URLRequest>`.
|
||||||
public func urlRequests(bufferingPolicy: StreamOf<URLRequest>.BufferingPolicy = .unbounded) -> StreamOf<URLRequest> {
|
public func urlRequests(bufferingPolicy: StreamOf<URLRequest>.BufferingPolicy = .unbounded) -> StreamOf<URLRequest> {
|
||||||
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
onURLRequestCreation(on: .singleEventQueue) { request in
|
onURLRequestCreation(on: underlyingQueue) { request in
|
||||||
continuation.yield(request)
|
continuation.yield(request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ extension Request {
|
|||||||
/// - Returns: The `StreamOf<URLSessionTask>`.
|
/// - Returns: The `StreamOf<URLSessionTask>`.
|
||||||
public func urlSessionTasks(bufferingPolicy: StreamOf<URLSessionTask>.BufferingPolicy = .unbounded) -> StreamOf<URLSessionTask> {
|
public func urlSessionTasks(bufferingPolicy: StreamOf<URLSessionTask>.BufferingPolicy = .unbounded) -> StreamOf<URLSessionTask> {
|
||||||
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
onURLSessionTaskCreation(on: .singleEventQueue) { task in
|
onURLSessionTaskCreation(on: underlyingQueue) { task in
|
||||||
continuation.yield(task)
|
continuation.yield(task)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,15 +89,15 @@ extension Request {
|
|||||||
/// - Returns: The `StreamOf<String>`.
|
/// - Returns: The `StreamOf<String>`.
|
||||||
public func cURLDescriptions(bufferingPolicy: StreamOf<String>.BufferingPolicy = .unbounded) -> StreamOf<String> {
|
public func cURLDescriptions(bufferingPolicy: StreamOf<String>.BufferingPolicy = .unbounded) -> StreamOf<String> {
|
||||||
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
cURLDescription(on: .singleEventQueue) { description in
|
cURLDescription(on: underlyingQueue) { description in
|
||||||
continuation.yield(description)
|
continuation.yield(description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func stream<T>(of type: T.Type = T.self,
|
fileprivate func stream<T>(of type: T.Type = T.self,
|
||||||
bufferingPolicy: StreamOf<T>.BufferingPolicy = .unbounded,
|
bufferingPolicy: StreamOf<T>.BufferingPolicy = .unbounded,
|
||||||
yielder: @escaping (StreamOf<T>.Continuation) -> Void) -> StreamOf<T> {
|
yielder: @escaping (StreamOf<T>.Continuation) -> Void) -> StreamOf<T> {
|
||||||
StreamOf<T>(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
StreamOf<T>(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
yielder(continuation)
|
yielder(continuation)
|
||||||
// Must come after serializers run in order to catch retry progress.
|
// Must come after serializers run in order to catch retry progress.
|
||||||
@@ -168,18 +168,83 @@ public struct DataTask<Value> {
|
|||||||
|
|
||||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||||
extension DataRequest {
|
extension DataRequest {
|
||||||
|
/// Creates a `StreamOf<HTTPURLResponse>` for the instance's responses.
|
||||||
|
///
|
||||||
|
/// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
|
||||||
|
///
|
||||||
|
/// - Returns: The `StreamOf<HTTPURLResponse>`.
|
||||||
|
public func httpResponses(bufferingPolicy: StreamOf<HTTPURLResponse>.BufferingPolicy = .unbounded) -> StreamOf<HTTPURLResponse> {
|
||||||
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
|
onHTTPResponse(on: underlyingQueue) { response in
|
||||||
|
continuation.yield(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if swift(>=5.7)
|
||||||
|
/// Sets an async closure returning a `Request.ResponseDisposition`, called whenever the `DataRequest` produces an
|
||||||
|
/// `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Note: Most requests will only produce a single response for each outgoing attempt (initial + retries).
|
||||||
|
/// However, some types of response may trigger multiple `HTTPURLResponse`s, such as multipart streams,
|
||||||
|
/// where responses after the first will contain the part headers.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - handler: Async closure executed when a new `HTTPURLResponse` is received and returning a
|
||||||
|
/// `ResponseDisposition` value. This value determines whether to continue the request or cancel it as
|
||||||
|
/// if `cancel()` had been called on the instance. Note, this closure is called on an arbitrary thread,
|
||||||
|
/// so any synchronous calls in it will execute in that context.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@_disfavoredOverload
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(
|
||||||
|
perform handler: @escaping @Sendable (_ response: HTTPURLResponse) async -> ResponseDisposition
|
||||||
|
) -> Self {
|
||||||
|
onHTTPResponse(on: underlyingQueue) { response, completionHandler in
|
||||||
|
Task {
|
||||||
|
let disposition = await handler(response)
|
||||||
|
completionHandler(disposition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets an async closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Note: Most requests will only produce a single response for each outgoing attempt (initial + retries).
|
||||||
|
/// However, some types of response may trigger multiple `HTTPURLResponse`s, such as multipart streams,
|
||||||
|
/// where responses after the first will contain the part headers.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - handler: Async closure executed when a new `HTTPURLResponse` is received. Note, this closure is called on an
|
||||||
|
/// arbitrary thread, so any synchronous calls in it will execute in that context.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(perform handler: @escaping @Sendable (_ response: HTTPURLResponse) async -> Void) -> Self {
|
||||||
|
onHTTPResponse { response in
|
||||||
|
await handler(response)
|
||||||
|
return .allow
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Creates a `DataTask` to `await` a `Data` value.
|
/// Creates a `DataTask` to `await` a `Data` value.
|
||||||
///
|
///
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
|
||||||
/// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
|
/// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
|
||||||
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DataTask`.
|
/// - Returns: The `DataTask`.
|
||||||
public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
|
||||||
emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
|
||||||
emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataTask<Data> {
|
emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DataTask<Data> {
|
||||||
@@ -195,7 +260,7 @@ extension DataRequest {
|
|||||||
/// - type: `Decodable` type to decode from response data.
|
/// - type: `Decodable` type to decode from response data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
||||||
/// `PassthroughPreprocessor()` by default.
|
/// `PassthroughPreprocessor()` by default.
|
||||||
/// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
|
/// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
|
||||||
@@ -204,7 +269,7 @@ extension DataRequest {
|
|||||||
///
|
///
|
||||||
/// - Returns: The `DataTask`.
|
/// - Returns: The `DataTask`.
|
||||||
public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
|
public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
|
||||||
decoder: DataDecoder = JSONDecoder(),
|
decoder: DataDecoder = JSONDecoder(),
|
||||||
emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
|
||||||
@@ -221,7 +286,7 @@ extension DataRequest {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
||||||
/// `PassthroughPreprocessor()` by default.
|
/// `PassthroughPreprocessor()` by default.
|
||||||
/// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
|
/// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
|
||||||
@@ -231,7 +296,7 @@ extension DataRequest {
|
|||||||
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DataTask`.
|
/// - Returns: The `DataTask`.
|
||||||
public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
|
||||||
encoding: String.Encoding? = nil,
|
encoding: String.Encoding? = nil,
|
||||||
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
|
||||||
@@ -249,16 +314,16 @@ extension DataRequest {
|
|||||||
/// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
|
/// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DataTask`.
|
/// - Returns: The `DataTask`.
|
||||||
public func serializingResponse<Serializer: ResponseSerializer>(using serializer: Serializer,
|
public func serializingResponse<Serializer: ResponseSerializer>(using serializer: Serializer,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true)
|
||||||
-> DataTask<Serializer.SerializedObject> {
|
-> DataTask<Serializer.SerializedObject> {
|
||||||
dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
|
dataTask(automaticallyCancelling: shouldAutomaticallyCancel) { [self] in
|
||||||
self.response(queue: .singleEventQueue,
|
response(queue: underlyingQueue,
|
||||||
responseSerializer: serializer,
|
responseSerializer: serializer,
|
||||||
completionHandler: $0)
|
completionHandler: $0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,16 +334,16 @@ extension DataRequest {
|
|||||||
/// response, and data.
|
/// response, and data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DataTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DataTask`.
|
/// - Returns: The `DataTask`.
|
||||||
public func serializingResponse<Serializer: DataResponseSerializerProtocol>(using serializer: Serializer,
|
public func serializingResponse<Serializer: DataResponseSerializerProtocol>(using serializer: Serializer,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true)
|
||||||
-> DataTask<Serializer.SerializedObject> {
|
-> DataTask<Serializer.SerializedObject> {
|
||||||
dataTask(automaticallyCancelling: shouldAutomaticallyCancel) {
|
dataTask(automaticallyCancelling: shouldAutomaticallyCancel) { [self] in
|
||||||
self.response(queue: .singleEventQueue,
|
response(queue: underlyingQueue,
|
||||||
responseSerializer: serializer,
|
responseSerializer: serializer,
|
||||||
completionHandler: $0)
|
completionHandler: $0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,13 +431,13 @@ extension DownloadRequest {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before completion.
|
||||||
/// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
|
/// - emptyResponseCodes: HTTP response codes for which empty responses are allowed. `[204, 205]` by default.
|
||||||
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
public func serializingData(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
|
||||||
emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = DataResponseSerializer.defaultEmptyResponseCodes,
|
||||||
emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<Data> {
|
emptyRequestMethods: Set<HTTPMethod> = DataResponseSerializer.defaultEmptyRequestMethods) -> DownloadTask<Data> {
|
||||||
@@ -390,7 +455,7 @@ extension DownloadRequest {
|
|||||||
/// - type: `Decodable` type to decode from response data.
|
/// - type: `Decodable` type to decode from response data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the serializer.
|
||||||
/// `PassthroughPreprocessor()` by default.
|
/// `PassthroughPreprocessor()` by default.
|
||||||
/// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
|
/// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
|
||||||
@@ -399,7 +464,7 @@ extension DownloadRequest {
|
|||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
|
public func serializingDecodable<Value: Decodable>(_ type: Value.Type = Value.self,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = DecodableResponseSerializer<Value>.defaultDataPreprocessor,
|
||||||
decoder: DataDecoder = JSONDecoder(),
|
decoder: DataDecoder = JSONDecoder(),
|
||||||
emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = DecodableResponseSerializer<Value>.defaultEmptyResponseCodes,
|
||||||
@@ -416,10 +481,10 @@ extension DownloadRequest {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingDownloadedFileURL(automaticallyCancelling shouldAutomaticallyCancel: Bool = false) -> DownloadTask<URL> {
|
public func serializingDownloadedFileURL(automaticallyCancelling shouldAutomaticallyCancel: Bool = true) -> DownloadTask<URL> {
|
||||||
serializingDownload(using: URLResponseSerializer(),
|
serializingDownload(using: URLResponseSerializer(),
|
||||||
automaticallyCancelling: shouldAutomaticallyCancel)
|
automaticallyCancelling: shouldAutomaticallyCancel)
|
||||||
}
|
}
|
||||||
@@ -429,7 +494,7 @@ extension DownloadRequest {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
|
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
|
||||||
/// serializer. `PassthroughPreprocessor()` by default.
|
/// serializer. `PassthroughPreprocessor()` by default.
|
||||||
/// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
|
/// - encoding: `String.Encoding` to use during serialization. Defaults to `nil`, in which case
|
||||||
@@ -439,7 +504,7 @@ extension DownloadRequest {
|
|||||||
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = false,
|
public func serializingString(automaticallyCancelling shouldAutomaticallyCancel: Bool = true,
|
||||||
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
|
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
|
||||||
encoding: String.Encoding? = nil,
|
encoding: String.Encoding? = nil,
|
||||||
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
|
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
|
||||||
@@ -457,16 +522,16 @@ extension DownloadRequest {
|
|||||||
/// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
|
/// - serializer: `ResponseSerializer` responsible for serializing the request, response, and data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingDownload<Serializer: ResponseSerializer>(using serializer: Serializer,
|
public func serializingDownload<Serializer: ResponseSerializer>(using serializer: Serializer,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true)
|
||||||
-> DownloadTask<Serializer.SerializedObject> {
|
-> DownloadTask<Serializer.SerializedObject> {
|
||||||
downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
|
downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) { [self] in
|
||||||
self.response(queue: .singleEventQueue,
|
response(queue: underlyingQueue,
|
||||||
responseSerializer: serializer,
|
responseSerializer: serializer,
|
||||||
completionHandler: $0)
|
completionHandler: $0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,16 +543,16 @@ extension DownloadRequest {
|
|||||||
/// response, and data.
|
/// response, and data.
|
||||||
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
/// - shouldAutomaticallyCancel: `Bool` determining whether or not the request should be cancelled when the
|
||||||
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
/// enclosing async context is cancelled. Only applies to `DownloadTask`'s async
|
||||||
/// properties. `false` by default.
|
/// properties. `true` by default.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DownloadTask`.
|
/// - Returns: The `DownloadTask`.
|
||||||
public func serializingDownload<Serializer: DownloadResponseSerializerProtocol>(using serializer: Serializer,
|
public func serializingDownload<Serializer: DownloadResponseSerializerProtocol>(using serializer: Serializer,
|
||||||
automaticallyCancelling shouldAutomaticallyCancel: Bool = false)
|
automaticallyCancelling shouldAutomaticallyCancel: Bool = true)
|
||||||
-> DownloadTask<Serializer.SerializedObject> {
|
-> DownloadTask<Serializer.SerializedObject> {
|
||||||
downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) {
|
downloadTask(automaticallyCancelling: shouldAutomaticallyCancel) { [self] in
|
||||||
self.response(queue: .singleEventQueue,
|
response(queue: underlyingQueue,
|
||||||
responseSerializer: serializer,
|
responseSerializer: serializer,
|
||||||
completionHandler: $0)
|
completionHandler: $0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,6 +690,69 @@ public struct DataStreamTask {
|
|||||||
|
|
||||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||||
extension DataStreamRequest {
|
extension DataStreamRequest {
|
||||||
|
/// Creates a `StreamOf<HTTPURLResponse>` for the instance's responses.
|
||||||
|
///
|
||||||
|
/// - Parameter bufferingPolicy: `BufferingPolicy` that determines the stream's buffering behavior.`.unbounded` by default.
|
||||||
|
///
|
||||||
|
/// - Returns: The `StreamOf<HTTPURLResponse>`.
|
||||||
|
public func httpResponses(bufferingPolicy: StreamOf<HTTPURLResponse>.BufferingPolicy = .unbounded) -> StreamOf<HTTPURLResponse> {
|
||||||
|
stream(bufferingPolicy: bufferingPolicy) { [unowned self] continuation in
|
||||||
|
onHTTPResponse(on: underlyingQueue) { response in
|
||||||
|
continuation.yield(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if swift(>=5.7)
|
||||||
|
/// Sets an async closure returning a `Request.ResponseDisposition`, called whenever the `DataStreamRequest`
|
||||||
|
/// produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Note: Most requests will only produce a single response for each outgoing attempt (initial + retries).
|
||||||
|
/// However, some types of response may trigger multiple `HTTPURLResponse`s, such as multipart streams,
|
||||||
|
/// where responses after the first will contain the part headers.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - handler: Async closure executed when a new `HTTPURLResponse` is received and returning a
|
||||||
|
/// `ResponseDisposition` value. This value determines whether to continue the request or cancel it as
|
||||||
|
/// if `cancel()` had been called on the instance. Note, this closure is called on an arbitrary thread,
|
||||||
|
/// so any synchronous calls in it will execute in that context.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@_disfavoredOverload
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(perform handler: @escaping @Sendable (HTTPURLResponse) async -> ResponseDisposition) -> Self {
|
||||||
|
onHTTPResponse(on: underlyingQueue) { response, completionHandler in
|
||||||
|
Task {
|
||||||
|
let disposition = await handler(response)
|
||||||
|
completionHandler(disposition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets an async closure called whenever the `DataStreamRequest` produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Note: Most requests will only produce a single response for each outgoing attempt (initial + retries).
|
||||||
|
/// However, some types of response may trigger multiple `HTTPURLResponse`s, such as multipart streams,
|
||||||
|
/// where responses after the first will contain the part headers.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - handler: Async closure executed when a new `HTTPURLResponse` is received. Note, this closure is called on an
|
||||||
|
/// arbitrary thread, so any synchronous calls in it will execute in that context.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(perform handler: @escaping @Sendable (HTTPURLResponse) async -> Void) -> Self {
|
||||||
|
onHTTPResponse { response in
|
||||||
|
await handler(response)
|
||||||
|
return .allow
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Creates a `DataStreamTask` used to `await` streams of serialized values.
|
/// Creates a `DataStreamTask` used to `await` streams of serialized values.
|
||||||
///
|
///
|
||||||
/// - Returns: The `DataStreamTask`.
|
/// - Returns: The `DataStreamTask`.
|
||||||
|
|||||||
15
Pods/Alamofire/Source/EventMonitor.swift
generated
15
Pods/Alamofire/Source/EventMonitor.swift
generated
@@ -69,6 +69,9 @@ public protocol EventMonitor {
|
|||||||
|
|
||||||
// MARK: URLSessionDataDelegate Events
|
// MARK: URLSessionDataDelegate Events
|
||||||
|
|
||||||
|
/// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:completionHandler:)` method.
|
||||||
|
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse)
|
||||||
|
|
||||||
/// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
|
/// Event called during `URLSessionDataDelegate`'s `urlSession(_:dataTask:didReceive:)` method.
|
||||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
|
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
|
||||||
|
|
||||||
@@ -244,6 +247,7 @@ extension EventMonitor {
|
|||||||
didFinishCollecting metrics: URLSessionTaskMetrics) {}
|
didFinishCollecting metrics: URLSessionTaskMetrics) {}
|
||||||
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
|
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {}
|
||||||
public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
|
public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
|
||||||
|
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse) {}
|
||||||
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
|
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
|
||||||
public func urlSession(_ session: URLSession,
|
public func urlSession(_ session: URLSession,
|
||||||
dataTask: URLSessionDataTask,
|
dataTask: URLSessionDataTask,
|
||||||
@@ -380,6 +384,10 @@ public final class CompositeEventMonitor: EventMonitor {
|
|||||||
performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
|
performEvent { $0.urlSession(session, taskIsWaitingForConnectivity: task) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse) {
|
||||||
|
performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: response) }
|
||||||
|
}
|
||||||
|
|
||||||
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||||
performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
|
performEvent { $0.urlSession(session, dataTask: dataTask, didReceive: data) }
|
||||||
}
|
}
|
||||||
@@ -593,6 +601,9 @@ open class ClosureEventMonitor: EventMonitor {
|
|||||||
/// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
|
/// Closure called on the `urlSession(_:taskIsWaitingForConnectivity:)` event.
|
||||||
open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
|
open var taskIsWaitingForConnectivity: ((URLSession, URLSessionTask) -> Void)?
|
||||||
|
|
||||||
|
/// Closure called on the `urlSession(_:dataTask:didReceive:completionHandler:)` event.
|
||||||
|
open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> Void)?
|
||||||
|
|
||||||
/// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
|
/// Closure that receives the `urlSession(_:dataTask:didReceive:)` event.
|
||||||
open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
|
open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
|
||||||
|
|
||||||
@@ -741,6 +752,10 @@ open class ClosureEventMonitor: EventMonitor {
|
|||||||
taskIsWaitingForConnectivity?(session, task)
|
taskIsWaitingForConnectivity?(session, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse) {
|
||||||
|
dataTaskDidReceiveResponse?(session, dataTask, response)
|
||||||
|
}
|
||||||
|
|
||||||
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||||
dataTaskDidReceiveData?(session, dataTask, data)
|
dataTaskDidReceiveData?(session, dataTask, data)
|
||||||
}
|
}
|
||||||
|
|||||||
8
Pods/Alamofire/Source/HTTPHeaders.swift
generated
8
Pods/Alamofire/Source/HTTPHeaders.swift
generated
@@ -34,16 +34,12 @@ public struct HTTPHeaders {
|
|||||||
/// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
|
/// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
|
||||||
/// name and value encountered.
|
/// name and value encountered.
|
||||||
public init(_ headers: [HTTPHeader]) {
|
public init(_ headers: [HTTPHeader]) {
|
||||||
self.init()
|
|
||||||
|
|
||||||
headers.forEach { update($0) }
|
headers.forEach { update($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
|
/// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
|
||||||
/// and value encountered.
|
/// and value encountered.
|
||||||
public init(_ dictionary: [String: String]) {
|
public init(_ dictionary: [String: String]) {
|
||||||
self.init()
|
|
||||||
|
|
||||||
dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
|
dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,8 +141,6 @@ public struct HTTPHeaders {
|
|||||||
|
|
||||||
extension HTTPHeaders: ExpressibleByDictionaryLiteral {
|
extension HTTPHeaders: ExpressibleByDictionaryLiteral {
|
||||||
public init(dictionaryLiteral elements: (String, String)...) {
|
public init(dictionaryLiteral elements: (String, String)...) {
|
||||||
self.init()
|
|
||||||
|
|
||||||
elements.forEach { update(name: $0.0, value: $0.1) }
|
elements.forEach { update(name: $0.0, value: $0.1) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,6 +399,8 @@ extension HTTPHeader {
|
|||||||
return "Linux"
|
return "Linux"
|
||||||
#elseif os(Windows)
|
#elseif os(Windows)
|
||||||
return "Windows"
|
return "Windows"
|
||||||
|
#elseif os(Android)
|
||||||
|
return "Android"
|
||||||
#else
|
#else
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
31
Pods/Alamofire/Source/MultipartFormData.swift
generated
31
Pods/Alamofire/Source/MultipartFormData.swift
generated
@@ -24,9 +24,9 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
#if canImport(MobileCoreServices)
|
||||||
import MobileCoreServices
|
import MobileCoreServices
|
||||||
#elseif os(macOS)
|
#elseif canImport(CoreServices)
|
||||||
import CoreServices
|
import CoreServices
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ open class MultipartFormData {
|
|||||||
// Check 2 - is file URL reachable?
|
// Check 2 - is file URL reachable?
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if !(os(Linux) || os(Windows) || os(Android))
|
||||||
do {
|
do {
|
||||||
let isReachable = try fileURL.checkPromisedItemIsReachable()
|
let isReachable = try fileURL.checkPromisedItemIsReachable()
|
||||||
guard isReachable else {
|
guard isReachable else {
|
||||||
@@ -455,9 +455,11 @@ open class MultipartFormData {
|
|||||||
inputStream.open()
|
inputStream.open()
|
||||||
defer { inputStream.close() }
|
defer { inputStream.close() }
|
||||||
|
|
||||||
while inputStream.hasBytesAvailable {
|
var bytesLeftToRead = bodyPart.bodyContentLength
|
||||||
var buffer = [UInt8](repeating: 0, count: streamBufferSize)
|
while inputStream.hasBytesAvailable && bytesLeftToRead > 0 {
|
||||||
let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
|
let bufferSize = min(streamBufferSize, Int(bytesLeftToRead))
|
||||||
|
var buffer = [UInt8](repeating: 0, count: bufferSize)
|
||||||
|
let bytesRead = inputStream.read(&buffer, maxLength: bufferSize)
|
||||||
|
|
||||||
if let streamError = inputStream.streamError {
|
if let streamError = inputStream.streamError {
|
||||||
throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
|
throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
|
||||||
@@ -469,6 +471,7 @@ open class MultipartFormData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try write(&buffer, to: outputStream)
|
try write(&buffer, to: outputStream)
|
||||||
|
bytesLeftToRead -= UInt64(bytesRead)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -549,6 +552,19 @@ extension MultipartFormData {
|
|||||||
// MARK: - Private - Mime Type
|
// MARK: - Private - Mime Type
|
||||||
|
|
||||||
private func mimeType(forPathExtension pathExtension: String) -> String {
|
private func mimeType(forPathExtension pathExtension: String) -> String {
|
||||||
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, visionOS 1, *) {
|
||||||
|
return UTType(filenameExtension: pathExtension)?.preferredMIMEType ?? "application/octet-stream"
|
||||||
|
} else {
|
||||||
|
if
|
||||||
|
let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
|
||||||
|
let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
|
||||||
|
return contentType as String
|
||||||
|
}
|
||||||
|
|
||||||
|
return "application/octet-stream"
|
||||||
|
}
|
||||||
|
#else
|
||||||
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, *) {
|
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, *) {
|
||||||
return UTType(filenameExtension: pathExtension)?.preferredMIMEType ?? "application/octet-stream"
|
return UTType(filenameExtension: pathExtension)?.preferredMIMEType ?? "application/octet-stream"
|
||||||
} else {
|
} else {
|
||||||
@@ -560,6 +576,7 @@ extension MultipartFormData {
|
|||||||
|
|
||||||
return "application/octet-stream"
|
return "application/octet-stream"
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +586,7 @@ extension MultipartFormData {
|
|||||||
// MARK: - Private - Mime Type
|
// MARK: - Private - Mime Type
|
||||||
|
|
||||||
private func mimeType(forPathExtension pathExtension: String) -> String {
|
private func mimeType(forPathExtension pathExtension: String) -> String {
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(CoreServices) || canImport(MobileCoreServices)
|
||||||
if
|
if
|
||||||
let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
|
let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
|
||||||
let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
|
let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() {
|
||||||
|
|||||||
14
Pods/Alamofire/Source/MultipartUpload.swift
generated
14
Pods/Alamofire/Source/MultipartUpload.swift
generated
@@ -28,8 +28,8 @@ import Foundation
|
|||||||
final class MultipartUpload {
|
final class MultipartUpload {
|
||||||
lazy var result = Result { try build() }
|
lazy var result = Result { try build() }
|
||||||
|
|
||||||
@Protected
|
private let multipartFormData: Protected<MultipartFormData>
|
||||||
private(set) var multipartFormData: MultipartFormData
|
|
||||||
let encodingMemoryThreshold: UInt64
|
let encodingMemoryThreshold: UInt64
|
||||||
let request: URLRequestConvertible
|
let request: URLRequestConvertible
|
||||||
let fileManager: FileManager
|
let fileManager: FileManager
|
||||||
@@ -40,13 +40,13 @@ final class MultipartUpload {
|
|||||||
self.encodingMemoryThreshold = encodingMemoryThreshold
|
self.encodingMemoryThreshold = encodingMemoryThreshold
|
||||||
self.request = request
|
self.request = request
|
||||||
fileManager = multipartFormData.fileManager
|
fileManager = multipartFormData.fileManager
|
||||||
self.multipartFormData = multipartFormData
|
self.multipartFormData = Protected(multipartFormData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func build() throws -> UploadRequest.Uploadable {
|
func build() throws -> UploadRequest.Uploadable {
|
||||||
let uploadable: UploadRequest.Uploadable
|
let uploadable: UploadRequest.Uploadable
|
||||||
if $multipartFormData.contentLength < encodingMemoryThreshold {
|
if multipartFormData.contentLength < encodingMemoryThreshold {
|
||||||
let data = try $multipartFormData.read { try $0.encode() }
|
let data = try multipartFormData.read { try $0.encode() }
|
||||||
|
|
||||||
uploadable = .data(data)
|
uploadable = .data(data)
|
||||||
} else {
|
} else {
|
||||||
@@ -58,7 +58,7 @@ final class MultipartUpload {
|
|||||||
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
|
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try $multipartFormData.read { try $0.writeEncodedData(to: fileURL) }
|
try multipartFormData.read { try $0.writeEncodedData(to: fileURL) }
|
||||||
} catch {
|
} catch {
|
||||||
// Cleanup after attempted write if it fails.
|
// Cleanup after attempted write if it fails.
|
||||||
try? fileManager.removeItem(at: fileURL)
|
try? fileManager.removeItem(at: fileURL)
|
||||||
@@ -76,7 +76,7 @@ extension MultipartUpload: UploadConvertible {
|
|||||||
func asURLRequest() throws -> URLRequest {
|
func asURLRequest() throws -> URLRequest {
|
||||||
var urlRequest = try request.asURLRequest()
|
var urlRequest = try request.asURLRequest()
|
||||||
|
|
||||||
$multipartFormData.read { multipartFormData in
|
multipartFormData.read { multipartFormData in
|
||||||
urlRequest.headers.add(.contentType(multipartFormData.contentType))
|
urlRequest.headers.add(.contentType(multipartFormData.contentType))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#if !(os(watchOS) || os(Linux) || os(Windows))
|
#if canImport(SystemConfiguration)
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import SystemConfiguration
|
import SystemConfiguration
|
||||||
@@ -113,8 +113,7 @@ open class NetworkReachabilityManager {
|
|||||||
private let reachability: SCNetworkReachability
|
private let reachability: SCNetworkReachability
|
||||||
|
|
||||||
/// Protected storage for mutable state.
|
/// Protected storage for mutable state.
|
||||||
@Protected
|
private let mutableState = Protected(MutableState())
|
||||||
private var mutableState = MutableState()
|
|
||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ open class NetworkReachabilityManager {
|
|||||||
onUpdatePerforming listener: @escaping Listener) -> Bool {
|
onUpdatePerforming listener: @escaping Listener) -> Bool {
|
||||||
stopListening()
|
stopListening()
|
||||||
|
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.listenerQueue = queue
|
state.listenerQueue = queue
|
||||||
state.listener = listener
|
state.listener = listener
|
||||||
}
|
}
|
||||||
@@ -194,7 +193,8 @@ open class NetworkReachabilityManager {
|
|||||||
let description = weakManager.manager?.flags?.readableDescription ?? "nil"
|
let description = weakManager.manager?.flags?.readableDescription ?? "nil"
|
||||||
|
|
||||||
return Unmanaged.passRetained(description as CFString)
|
return Unmanaged.passRetained(description as CFString)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
let callback: SCNetworkReachabilityCallBack = { _, flags, info in
|
let callback: SCNetworkReachabilityCallBack = { _, flags, info in
|
||||||
guard let info = info else { return }
|
guard let info = info else { return }
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ open class NetworkReachabilityManager {
|
|||||||
open func stopListening() {
|
open func stopListening() {
|
||||||
SCNetworkReachabilitySetCallback(reachability, nil, nil)
|
SCNetworkReachabilitySetCallback(reachability, nil, nil)
|
||||||
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
|
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.listener = nil
|
state.listener = nil
|
||||||
state.listenerQueue = nil
|
state.listenerQueue = nil
|
||||||
state.previousStatus = nil
|
state.previousStatus = nil
|
||||||
@@ -236,7 +236,7 @@ open class NetworkReachabilityManager {
|
|||||||
func notifyListener(_ flags: SCNetworkReachabilityFlags) {
|
func notifyListener(_ flags: SCNetworkReachabilityFlags) {
|
||||||
let newStatus = NetworkReachabilityStatus(flags)
|
let newStatus = NetworkReachabilityStatus(flags)
|
||||||
|
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
guard state.previousStatus != newStatus else { return }
|
guard state.previousStatus != newStatus else { return }
|
||||||
|
|
||||||
state.previousStatus = newStatus
|
state.previousStatus = newStatus
|
||||||
@@ -266,7 +266,7 @@ extension SCNetworkReachabilityFlags {
|
|||||||
var canConnectWithoutUserInteraction: Bool { canConnectAutomatically && !contains(.interventionRequired) }
|
var canConnectWithoutUserInteraction: Bool { canConnectAutomatically && !contains(.interventionRequired) }
|
||||||
var isActuallyReachable: Bool { isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
|
var isActuallyReachable: Bool { isReachable && (!isConnectionRequired || canConnectWithoutUserInteraction) }
|
||||||
var isCellular: Bool {
|
var isCellular: Bool {
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))
|
||||||
return contains(.isWWAN)
|
return contains(.isWWAN)
|
||||||
#else
|
#else
|
||||||
return false
|
return false
|
||||||
|
|||||||
67
Pods/Alamofire/Source/Protected.swift
generated
67
Pods/Alamofire/Source/Protected.swift
generated
@@ -49,13 +49,7 @@ extension Lock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(Linux) || os(Windows)
|
#if canImport(Darwin)
|
||||||
|
|
||||||
extension NSLock: Lock {}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
|
||||||
/// An `os_unfair_lock` wrapper.
|
/// An `os_unfair_lock` wrapper.
|
||||||
final class UnfairLock: Lock {
|
final class UnfairLock: Lock {
|
||||||
private let unfairLock: os_unfair_lock_t
|
private let unfairLock: os_unfair_lock_t
|
||||||
@@ -78,41 +72,35 @@ final class UnfairLock: Lock {
|
|||||||
os_unfair_lock_unlock(unfairLock)
|
os_unfair_lock_unlock(unfairLock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elseif canImport(Foundation)
|
||||||
|
extension NSLock: Lock {}
|
||||||
|
#else
|
||||||
|
#error("This platform needs a Lock-conforming type without Foundation.")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// A thread-safe wrapper around a value.
|
/// A thread-safe wrapper around a value.
|
||||||
@propertyWrapper
|
|
||||||
@dynamicMemberLookup
|
@dynamicMemberLookup
|
||||||
final class Protected<T> {
|
final class Protected<Value> {
|
||||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
#if canImport(Darwin)
|
||||||
private let lock = UnfairLock()
|
private let lock = UnfairLock()
|
||||||
#elseif os(Linux) || os(Windows)
|
#elseif canImport(Foundation)
|
||||||
private let lock = NSLock()
|
private let lock = NSLock()
|
||||||
|
#else
|
||||||
|
#error("This platform needs a Lock-conforming type without Foundation.")
|
||||||
#endif
|
#endif
|
||||||
private var value: T
|
private var value: Value
|
||||||
|
|
||||||
init(_ value: T) {
|
init(_ value: Value) {
|
||||||
self.value = value
|
self.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The contained value. Unsafe for anything more than direct read or write.
|
|
||||||
var wrappedValue: T {
|
|
||||||
get { lock.around { value } }
|
|
||||||
set { lock.around { value = newValue } }
|
|
||||||
}
|
|
||||||
|
|
||||||
var projectedValue: Protected<T> { self }
|
|
||||||
|
|
||||||
init(wrappedValue: T) {
|
|
||||||
value = wrappedValue
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Synchronously read or transform the contained value.
|
/// Synchronously read or transform the contained value.
|
||||||
///
|
///
|
||||||
/// - Parameter closure: The closure to execute.
|
/// - Parameter closure: The closure to execute.
|
||||||
///
|
///
|
||||||
/// - Returns: The return value of the closure passed.
|
/// - Returns: The return value of the closure passed.
|
||||||
func read<U>(_ closure: (T) throws -> U) rethrows -> U {
|
func read<U>(_ closure: (Value) throws -> U) rethrows -> U {
|
||||||
try lock.around { try closure(self.value) }
|
try lock.around { try closure(self.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,21 +110,28 @@ final class Protected<T> {
|
|||||||
///
|
///
|
||||||
/// - Returns: The modified value.
|
/// - Returns: The modified value.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func write<U>(_ closure: (inout T) throws -> U) rethrows -> U {
|
func write<U>(_ closure: (inout Value) throws -> U) rethrows -> U {
|
||||||
try lock.around { try closure(&self.value) }
|
try lock.around { try closure(&self.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
subscript<Property>(dynamicMember keyPath: WritableKeyPath<T, Property>) -> Property {
|
/// Synchronously update the protected value.
|
||||||
|
///
|
||||||
|
/// - Parameter value: The `Value`.
|
||||||
|
func write(_ value: Value) {
|
||||||
|
write { $0 = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
subscript<Property>(dynamicMember keyPath: WritableKeyPath<Value, Property>) -> Property {
|
||||||
get { lock.around { value[keyPath: keyPath] } }
|
get { lock.around { value[keyPath: keyPath] } }
|
||||||
set { lock.around { value[keyPath: keyPath] = newValue } }
|
set { lock.around { value[keyPath: keyPath] = newValue } }
|
||||||
}
|
}
|
||||||
|
|
||||||
subscript<Property>(dynamicMember keyPath: KeyPath<T, Property>) -> Property {
|
subscript<Property>(dynamicMember keyPath: KeyPath<Value, Property>) -> Property {
|
||||||
lock.around { value[keyPath: keyPath] }
|
lock.around { value[keyPath: keyPath] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Protected where T == Request.MutableState {
|
extension Protected where Value == Request.MutableState {
|
||||||
/// Attempts to transition to the passed `State`.
|
/// Attempts to transition to the passed `State`.
|
||||||
///
|
///
|
||||||
/// - Parameter state: The `State` to attempt transition to.
|
/// - Parameter state: The `State` to attempt transition to.
|
||||||
@@ -159,3 +154,15 @@ extension Protected where T == Request.MutableState {
|
|||||||
lock.around { perform(value.state) }
|
lock.around { perform(value.state) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Protected: Equatable where Value: Equatable {
|
||||||
|
static func ==(lhs: Protected<Value>, rhs: Protected<Value>) -> Bool {
|
||||||
|
lhs.read { left in rhs.read { right in left == right }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Protected: Hashable where Value: Hashable {
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
read { hasher.combine($0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
334
Pods/Alamofire/Source/Request.swift
generated
334
Pods/Alamofire/Source/Request.swift
generated
@@ -125,11 +125,10 @@ public class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Protected `MutableState` value that provides thread-safe access to state values.
|
/// Protected `MutableState` value that provides thread-safe access to state values.
|
||||||
@Protected
|
fileprivate let mutableState = Protected(MutableState())
|
||||||
fileprivate var mutableState = MutableState()
|
|
||||||
|
|
||||||
/// `State` of the `Request`.
|
/// `State` of the `Request`.
|
||||||
public var state: State { $mutableState.state }
|
public var state: State { mutableState.state }
|
||||||
/// Returns whether `state` is `.initialized`.
|
/// Returns whether `state` is `.initialized`.
|
||||||
public var isInitialized: Bool { state == .initialized }
|
public var isInitialized: Bool { state == .initialized }
|
||||||
/// Returns whether `state is `.resumed`.
|
/// Returns whether `state is `.resumed`.
|
||||||
@@ -152,50 +151,49 @@ public class Request {
|
|||||||
public let downloadProgress = Progress(totalUnitCount: 0)
|
public let downloadProgress = Progress(totalUnitCount: 0)
|
||||||
/// `ProgressHandler` called when `uploadProgress` is updated, on the provided `DispatchQueue`.
|
/// `ProgressHandler` called when `uploadProgress` is updated, on the provided `DispatchQueue`.
|
||||||
private var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
private var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
||||||
get { $mutableState.uploadProgressHandler }
|
get { mutableState.uploadProgressHandler }
|
||||||
set { $mutableState.uploadProgressHandler = newValue }
|
set { mutableState.uploadProgressHandler = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ProgressHandler` called when `downloadProgress` is updated, on the provided `DispatchQueue`.
|
/// `ProgressHandler` called when `downloadProgress` is updated, on the provided `DispatchQueue`.
|
||||||
fileprivate var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
fileprivate var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
||||||
get { $mutableState.downloadProgressHandler }
|
get { mutableState.downloadProgressHandler }
|
||||||
set { $mutableState.downloadProgressHandler = newValue }
|
set { mutableState.downloadProgressHandler = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Redirect Handling
|
// MARK: Redirect Handling
|
||||||
|
|
||||||
/// `RedirectHandler` set on the instance.
|
/// `RedirectHandler` set on the instance.
|
||||||
public private(set) var redirectHandler: RedirectHandler? {
|
public private(set) var redirectHandler: RedirectHandler? {
|
||||||
get { $mutableState.redirectHandler }
|
get { mutableState.redirectHandler }
|
||||||
set { $mutableState.redirectHandler = newValue }
|
set { mutableState.redirectHandler = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Cached Response Handling
|
// MARK: Cached Response Handling
|
||||||
|
|
||||||
/// `CachedResponseHandler` set on the instance.
|
/// `CachedResponseHandler` set on the instance.
|
||||||
public private(set) var cachedResponseHandler: CachedResponseHandler? {
|
public private(set) var cachedResponseHandler: CachedResponseHandler? {
|
||||||
get { $mutableState.cachedResponseHandler }
|
get { mutableState.cachedResponseHandler }
|
||||||
set { $mutableState.cachedResponseHandler = newValue }
|
set { mutableState.cachedResponseHandler = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: URLCredential
|
// MARK: URLCredential
|
||||||
|
|
||||||
/// `URLCredential` used for authentication challenges. Created by calling one of the `authenticate` methods.
|
/// `URLCredential` used for authentication challenges. Created by calling one of the `authenticate` methods.
|
||||||
public private(set) var credential: URLCredential? {
|
public private(set) var credential: URLCredential? {
|
||||||
get { $mutableState.credential }
|
get { mutableState.credential }
|
||||||
set { $mutableState.credential = newValue }
|
set { mutableState.credential = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Validators
|
// MARK: Validators
|
||||||
|
|
||||||
/// `Validator` callback closures that store the validation calls enqueued.
|
/// `Validator` callback closures that store the validation calls enqueued.
|
||||||
@Protected
|
fileprivate let validators = Protected<[() -> Void]>([])
|
||||||
fileprivate var validators: [() -> Void] = []
|
|
||||||
|
|
||||||
// MARK: URLRequests
|
// MARK: URLRequests
|
||||||
|
|
||||||
/// All `URLRequests` created on behalf of the `Request`, including original and adapted requests.
|
/// All `URLRequests` created on behalf of the `Request`, including original and adapted requests.
|
||||||
public var requests: [URLRequest] { $mutableState.requests }
|
public var requests: [URLRequest] { mutableState.requests }
|
||||||
/// First `URLRequest` created on behalf of the `Request`. May not be the first one actually executed.
|
/// First `URLRequest` created on behalf of the `Request`. May not be the first one actually executed.
|
||||||
public var firstRequest: URLRequest? { requests.first }
|
public var firstRequest: URLRequest? { requests.first }
|
||||||
/// Last `URLRequest` created on behalf of the `Request`.
|
/// Last `URLRequest` created on behalf of the `Request`.
|
||||||
@@ -205,7 +203,7 @@ public class Request {
|
|||||||
|
|
||||||
/// `URLRequest`s from all of the `URLSessionTask`s executed on behalf of the `Request`. May be different from
|
/// `URLRequest`s from all of the `URLSessionTask`s executed on behalf of the `Request`. May be different from
|
||||||
/// `requests` due to `URLSession` manipulation.
|
/// `requests` due to `URLSession` manipulation.
|
||||||
public var performedRequests: [URLRequest] { $mutableState.read { $0.tasks.compactMap(\.currentRequest) } }
|
public var performedRequests: [URLRequest] { mutableState.read { $0.tasks.compactMap(\.currentRequest) } }
|
||||||
|
|
||||||
// MARK: HTTPURLResponse
|
// MARK: HTTPURLResponse
|
||||||
|
|
||||||
@@ -216,7 +214,7 @@ public class Request {
|
|||||||
// MARK: Tasks
|
// MARK: Tasks
|
||||||
|
|
||||||
/// All `URLSessionTask`s created on behalf of the `Request`.
|
/// All `URLSessionTask`s created on behalf of the `Request`.
|
||||||
public var tasks: [URLSessionTask] { $mutableState.tasks }
|
public var tasks: [URLSessionTask] { mutableState.tasks }
|
||||||
/// First `URLSessionTask` created on behalf of the `Request`.
|
/// First `URLSessionTask` created on behalf of the `Request`.
|
||||||
public var firstTask: URLSessionTask? { tasks.first }
|
public var firstTask: URLSessionTask? { tasks.first }
|
||||||
/// Last `URLSessionTask` created on behalf of the `Request`.
|
/// Last `URLSessionTask` created on behalf of the `Request`.
|
||||||
@@ -227,7 +225,7 @@ public class Request {
|
|||||||
// MARK: Metrics
|
// MARK: Metrics
|
||||||
|
|
||||||
/// All `URLSessionTaskMetrics` gathered on behalf of the `Request`. Should correspond to the `tasks` created.
|
/// All `URLSessionTaskMetrics` gathered on behalf of the `Request`. Should correspond to the `tasks` created.
|
||||||
public var allMetrics: [URLSessionTaskMetrics] { $mutableState.metrics }
|
public var allMetrics: [URLSessionTaskMetrics] { mutableState.metrics }
|
||||||
/// First `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
/// First `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
||||||
public var firstMetrics: URLSessionTaskMetrics? { allMetrics.first }
|
public var firstMetrics: URLSessionTaskMetrics? { allMetrics.first }
|
||||||
/// Last `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
/// Last `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
||||||
@@ -238,14 +236,14 @@ public class Request {
|
|||||||
// MARK: Retry Count
|
// MARK: Retry Count
|
||||||
|
|
||||||
/// Number of times the `Request` has been retried.
|
/// Number of times the `Request` has been retried.
|
||||||
public var retryCount: Int { $mutableState.retryCount }
|
public var retryCount: Int { mutableState.retryCount }
|
||||||
|
|
||||||
// MARK: Error
|
// MARK: Error
|
||||||
|
|
||||||
/// `Error` returned from Alamofire internally, from the network request directly, or any validators executed.
|
/// `Error` returned from Alamofire internally, from the network request directly, or any validators executed.
|
||||||
public fileprivate(set) var error: AFError? {
|
public fileprivate(set) var error: AFError? {
|
||||||
get { $mutableState.error }
|
get { mutableState.error }
|
||||||
set { $mutableState.error = newValue }
|
set { mutableState.error = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default initializer for the `Request` superclass.
|
/// Default initializer for the `Request` superclass.
|
||||||
@@ -283,7 +281,7 @@ public class Request {
|
|||||||
func didCreateInitialURLRequest(_ request: URLRequest) {
|
func didCreateInitialURLRequest(_ request: URLRequest) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.write { $0.requests.append(request) }
|
mutableState.write { $0.requests.append(request) }
|
||||||
|
|
||||||
eventMonitor?.request(self, didCreateInitialURLRequest: request)
|
eventMonitor?.request(self, didCreateInitialURLRequest: request)
|
||||||
}
|
}
|
||||||
@@ -313,7 +311,7 @@ public class Request {
|
|||||||
func didAdaptInitialRequest(_ initialRequest: URLRequest, to adaptedRequest: URLRequest) {
|
func didAdaptInitialRequest(_ initialRequest: URLRequest, to adaptedRequest: URLRequest) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.write { $0.requests.append(adaptedRequest) }
|
mutableState.write { $0.requests.append(adaptedRequest) }
|
||||||
|
|
||||||
eventMonitor?.request(self, didAdaptInitialRequest: initialRequest, to: adaptedRequest)
|
eventMonitor?.request(self, didAdaptInitialRequest: initialRequest, to: adaptedRequest)
|
||||||
}
|
}
|
||||||
@@ -343,7 +341,7 @@ public class Request {
|
|||||||
func didCreateURLRequest(_ request: URLRequest) {
|
func didCreateURLRequest(_ request: URLRequest) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.read { state in
|
mutableState.read { state in
|
||||||
state.urlRequestHandler?.queue.async { state.urlRequestHandler?.handler(request) }
|
state.urlRequestHandler?.queue.async { state.urlRequestHandler?.handler(request) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +352,7 @@ public class Request {
|
|||||||
|
|
||||||
/// Asynchronously calls any stored `cURLHandler` and then removes it from `mutableState`.
|
/// Asynchronously calls any stored `cURLHandler` and then removes it from `mutableState`.
|
||||||
private func callCURLHandlerIfNecessary() {
|
private func callCURLHandlerIfNecessary() {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
guard let cURLHandler = mutableState.cURLHandler else { return }
|
guard let cURLHandler = mutableState.cURLHandler else { return }
|
||||||
|
|
||||||
cURLHandler.queue.async { cURLHandler.handler(self.cURLDescription()) }
|
cURLHandler.queue.async { cURLHandler.handler(self.cURLDescription()) }
|
||||||
@@ -369,7 +367,7 @@ public class Request {
|
|||||||
func didCreateTask(_ task: URLSessionTask) {
|
func didCreateTask(_ task: URLSessionTask) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.tasks.append(task)
|
state.tasks.append(task)
|
||||||
|
|
||||||
guard let urlSessionTaskHandler = state.urlSessionTaskHandler else { return }
|
guard let urlSessionTaskHandler = state.urlSessionTaskHandler else { return }
|
||||||
@@ -416,7 +414,9 @@ public class Request {
|
|||||||
func didCancel() {
|
func didCancel() {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
error = error ?? AFError.explicitlyCancelled
|
mutableState.write { mutableState in
|
||||||
|
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||||
|
}
|
||||||
|
|
||||||
eventMonitor?.requestDidCancel(self)
|
eventMonitor?.requestDidCancel(self)
|
||||||
}
|
}
|
||||||
@@ -436,7 +436,7 @@ public class Request {
|
|||||||
func didGatherMetrics(_ metrics: URLSessionTaskMetrics) {
|
func didGatherMetrics(_ metrics: URLSessionTaskMetrics) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.write { $0.metrics.append(metrics) }
|
mutableState.write { $0.metrics.append(metrics) }
|
||||||
|
|
||||||
eventMonitor?.request(self, didGatherMetrics: metrics)
|
eventMonitor?.request(self, didGatherMetrics: metrics)
|
||||||
}
|
}
|
||||||
@@ -468,6 +468,7 @@ public class Request {
|
|||||||
|
|
||||||
self.error = self.error ?? error
|
self.error = self.error ?? error
|
||||||
|
|
||||||
|
let validators = validators.read { $0 }
|
||||||
validators.forEach { $0() }
|
validators.forEach { $0() }
|
||||||
|
|
||||||
eventMonitor?.request(self, didCompleteTask: task, with: error)
|
eventMonitor?.request(self, didCompleteTask: task, with: error)
|
||||||
@@ -479,7 +480,7 @@ public class Request {
|
|||||||
func prepareForRetry() {
|
func prepareForRetry() {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
$mutableState.write { $0.retryCount += 1 }
|
mutableState.write { $0.retryCount += 1 }
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
@@ -513,9 +514,9 @@ public class Request {
|
|||||||
func finish(error: AFError? = nil) {
|
func finish(error: AFError? = nil) {
|
||||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||||
|
|
||||||
guard !$mutableState.isFinishing else { return }
|
guard !mutableState.isFinishing else { return }
|
||||||
|
|
||||||
$mutableState.isFinishing = true
|
mutableState.isFinishing = true
|
||||||
|
|
||||||
if let error = error { self.error = error }
|
if let error = error { self.error = error }
|
||||||
|
|
||||||
@@ -531,7 +532,7 @@ public class Request {
|
|||||||
///
|
///
|
||||||
/// - Parameter closure: The closure containing the response serialization call.
|
/// - Parameter closure: The closure containing the response serialization call.
|
||||||
func appendResponseSerializer(_ closure: @escaping () -> Void) {
|
func appendResponseSerializer(_ closure: @escaping () -> Void) {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
mutableState.responseSerializers.append(closure)
|
mutableState.responseSerializers.append(closure)
|
||||||
|
|
||||||
if mutableState.state == .finished {
|
if mutableState.state == .finished {
|
||||||
@@ -554,7 +555,7 @@ public class Request {
|
|||||||
func nextResponseSerializer() -> (() -> Void)? {
|
func nextResponseSerializer() -> (() -> Void)? {
|
||||||
var responseSerializer: (() -> Void)?
|
var responseSerializer: (() -> Void)?
|
||||||
|
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
let responseSerializerIndex = mutableState.responseSerializerCompletions.count
|
let responseSerializerIndex = mutableState.responseSerializerCompletions.count
|
||||||
|
|
||||||
if responseSerializerIndex < mutableState.responseSerializers.count {
|
if responseSerializerIndex < mutableState.responseSerializers.count {
|
||||||
@@ -571,7 +572,7 @@ public class Request {
|
|||||||
// Execute all response serializer completions and clear them
|
// Execute all response serializer completions and clear them
|
||||||
var completions: [() -> Void] = []
|
var completions: [() -> Void] = []
|
||||||
|
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
completions = mutableState.responseSerializerCompletions
|
completions = mutableState.responseSerializerCompletions
|
||||||
|
|
||||||
// Clear out all response serializers and response serializer completions in mutable state since the
|
// Clear out all response serializers and response serializer completions in mutable state since the
|
||||||
@@ -605,7 +606,7 @@ public class Request {
|
|||||||
/// - Parameter completion: The completion handler provided with the response serializer, called when all serializers
|
/// - Parameter completion: The completion handler provided with the response serializer, called when all serializers
|
||||||
/// are complete.
|
/// are complete.
|
||||||
func responseSerializerDidComplete(completion: @escaping () -> Void) {
|
func responseSerializerDidComplete(completion: @escaping () -> Void) {
|
||||||
$mutableState.write { $0.responseSerializerCompletions.append(completion) }
|
mutableState.write { $0.responseSerializerCompletions.append(completion) }
|
||||||
processNextResponseSerializer()
|
processNextResponseSerializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +619,7 @@ public class Request {
|
|||||||
downloadProgress.totalUnitCount = 0
|
downloadProgress.totalUnitCount = 0
|
||||||
downloadProgress.completedUnitCount = 0
|
downloadProgress.completedUnitCount = 0
|
||||||
|
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.isFinishing = false
|
state.isFinishing = false
|
||||||
state.responseSerializerCompletions = []
|
state.responseSerializerCompletions = []
|
||||||
}
|
}
|
||||||
@@ -640,7 +641,7 @@ public class Request {
|
|||||||
///
|
///
|
||||||
/// - Parameter perform: The closure to perform.
|
/// - Parameter perform: The closure to perform.
|
||||||
func withState(perform: (State) -> Void) {
|
func withState(perform: (State) -> Void) {
|
||||||
$mutableState.withState(perform: perform)
|
mutableState.withState(perform: perform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Task Creation
|
// MARK: Task Creation
|
||||||
@@ -667,7 +668,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func cancel() -> Self {
|
public func cancel() -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
||||||
|
|
||||||
mutableState.state = .cancelled
|
mutableState.state = .cancelled
|
||||||
@@ -693,7 +694,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func suspend() -> Self {
|
public func suspend() -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
guard mutableState.state.canTransitionTo(.suspended) else { return }
|
guard mutableState.state.canTransitionTo(.suspended) else { return }
|
||||||
|
|
||||||
mutableState.state = .suspended
|
mutableState.state = .suspended
|
||||||
@@ -714,7 +715,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func resume() -> Self {
|
public func resume() -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
guard mutableState.state.canTransitionTo(.resumed) else { return }
|
guard mutableState.state.canTransitionTo(.resumed) else { return }
|
||||||
|
|
||||||
mutableState.state = .resumed
|
mutableState.state = .resumed
|
||||||
@@ -754,7 +755,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func authenticate(with credential: URLCredential) -> Self {
|
public func authenticate(with credential: URLCredential) -> Self {
|
||||||
$mutableState.credential = credential
|
mutableState.credential = credential
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@@ -770,7 +771,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func downloadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
public func downloadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
||||||
$mutableState.downloadProgressHandler = (handler: closure, queue: queue)
|
mutableState.downloadProgressHandler = (handler: closure, queue: queue)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@@ -786,7 +787,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func uploadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
public func uploadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
||||||
$mutableState.uploadProgressHandler = (handler: closure, queue: queue)
|
mutableState.uploadProgressHandler = (handler: closure, queue: queue)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@@ -802,7 +803,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func redirect(using handler: RedirectHandler) -> Self {
|
public func redirect(using handler: RedirectHandler) -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
precondition(mutableState.redirectHandler == nil, "Redirect handler has already been set.")
|
precondition(mutableState.redirectHandler == nil, "Redirect handler has already been set.")
|
||||||
mutableState.redirectHandler = handler
|
mutableState.redirectHandler = handler
|
||||||
}
|
}
|
||||||
@@ -821,7 +822,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func cacheResponse(using handler: CachedResponseHandler) -> Self {
|
public func cacheResponse(using handler: CachedResponseHandler) -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
precondition(mutableState.cachedResponseHandler == nil, "Cached response handler has already been set.")
|
precondition(mutableState.cachedResponseHandler == nil, "Cached response handler has already been set.")
|
||||||
mutableState.cachedResponseHandler = handler
|
mutableState.cachedResponseHandler = handler
|
||||||
}
|
}
|
||||||
@@ -842,7 +843,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func cURLDescription(on queue: DispatchQueue, calling handler: @escaping (String) -> Void) -> Self {
|
public func cURLDescription(on queue: DispatchQueue, calling handler: @escaping (String) -> Void) -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
if mutableState.requests.last != nil {
|
if mutableState.requests.last != nil {
|
||||||
queue.async { handler(self.cURLDescription()) }
|
queue.async { handler(self.cURLDescription()) }
|
||||||
} else {
|
} else {
|
||||||
@@ -863,13 +864,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func cURLDescription(calling handler: @escaping (String) -> Void) -> Self {
|
public func cURLDescription(calling handler: @escaping (String) -> Void) -> Self {
|
||||||
$mutableState.write { mutableState in
|
cURLDescription(on: underlyingQueue, calling: handler)
|
||||||
if mutableState.requests.last != nil {
|
|
||||||
underlyingQueue.async { handler(self.cURLDescription()) }
|
|
||||||
} else {
|
|
||||||
mutableState.cURLHandler = (underlyingQueue, handler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@@ -885,7 +880,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func onURLRequestCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLRequest) -> Void) -> Self {
|
public func onURLRequestCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLRequest) -> Void) -> Self {
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
if let request = state.requests.last {
|
if let request = state.requests.last {
|
||||||
queue.async { handler(request) }
|
queue.async { handler(request) }
|
||||||
}
|
}
|
||||||
@@ -909,7 +904,7 @@ public class Request {
|
|||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func onURLSessionTaskCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLSessionTask) -> Void) -> Self {
|
public func onURLSessionTaskCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLSessionTask) -> Void) -> Self {
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
if let task = state.tasks.last {
|
if let task = state.tasks.last {
|
||||||
queue.async { handler(task) }
|
queue.async { handler(task) }
|
||||||
}
|
}
|
||||||
@@ -928,19 +923,37 @@ public class Request {
|
|||||||
func onFinish(perform finishHandler: @escaping () -> Void) {
|
func onFinish(perform finishHandler: @escaping () -> Void) {
|
||||||
guard !isFinished else { finishHandler(); return }
|
guard !isFinished else { finishHandler(); return }
|
||||||
|
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.finishHandlers.append(finishHandler)
|
state.finishHandlers.append(finishHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Final cleanup step executed when the instance finishes response serialization.
|
/// Final cleanup step executed when the instance finishes response serialization.
|
||||||
func cleanup() {
|
func cleanup() {
|
||||||
delegate?.cleanup(after: self)
|
let handlers = mutableState.finishHandlers
|
||||||
let handlers = $mutableState.finishHandlers
|
|
||||||
handlers.forEach { $0() }
|
handlers.forEach { $0() }
|
||||||
$mutableState.write { state in
|
mutableState.write { state in
|
||||||
state.finishHandlers.removeAll()
|
state.finishHandlers.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delegate?.cleanup(after: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Request {
|
||||||
|
/// Type indicating how a `DataRequest` or `DataStreamRequest` should proceed after receiving an `HTTPURLResponse`.
|
||||||
|
public enum ResponseDisposition {
|
||||||
|
/// Allow the request to continue normally.
|
||||||
|
case allow
|
||||||
|
/// Cancel the request, similar to calling `cancel()`.
|
||||||
|
case cancel
|
||||||
|
|
||||||
|
var sessionDisposition: URLSession.ResponseDisposition {
|
||||||
|
switch self {
|
||||||
|
case .allow: return .allow
|
||||||
|
case .cancel: return .cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,11 +1098,16 @@ public class DataRequest: Request {
|
|||||||
/// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
|
/// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
|
||||||
public let convertible: URLRequestConvertible
|
public let convertible: URLRequestConvertible
|
||||||
/// `Data` read from the server so far.
|
/// `Data` read from the server so far.
|
||||||
public var data: Data? { mutableData }
|
public var data: Data? { dataMutableState.data }
|
||||||
|
|
||||||
/// Protected storage for the `Data` read by the instance.
|
private struct DataMutableState {
|
||||||
@Protected
|
var data: Data?
|
||||||
private var mutableData: Data? = nil
|
var httpResponseHandler: (queue: DispatchQueue,
|
||||||
|
handler: (_ response: HTTPURLResponse,
|
||||||
|
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
|
||||||
|
}
|
||||||
|
|
||||||
|
private let dataMutableState = Protected(DataMutableState())
|
||||||
|
|
||||||
/// Creates a `DataRequest` using the provided parameters.
|
/// Creates a `DataRequest` using the provided parameters.
|
||||||
///
|
///
|
||||||
@@ -1122,7 +1140,9 @@ public class DataRequest: Request {
|
|||||||
override func reset() {
|
override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
|
|
||||||
mutableData = nil
|
dataMutableState.write { mutableState in
|
||||||
|
mutableState.data = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when `Data` is received by this instance.
|
/// Called when `Data` is received by this instance.
|
||||||
@@ -1131,15 +1151,41 @@ public class DataRequest: Request {
|
|||||||
///
|
///
|
||||||
/// - Parameter data: The `Data` received.
|
/// - Parameter data: The `Data` received.
|
||||||
func didReceive(data: Data) {
|
func didReceive(data: Data) {
|
||||||
if self.data == nil {
|
dataMutableState.write { mutableState in
|
||||||
mutableData = data
|
if mutableState.data == nil {
|
||||||
} else {
|
mutableState.data = data
|
||||||
$mutableData.write { $0?.append(data) }
|
} else {
|
||||||
|
mutableState.data?.append(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDownloadProgress()
|
updateDownloadProgress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||||
|
dataMutableState.read { dataMutableState in
|
||||||
|
guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
|
||||||
|
underlyingQueue.async { completionHandler(.allow) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
httpResponseHandler.queue.async {
|
||||||
|
httpResponseHandler.handler(response) { disposition in
|
||||||
|
if disposition == .cancel {
|
||||||
|
self.mutableState.write { mutableState in
|
||||||
|
mutableState.state = .cancelled
|
||||||
|
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.underlyingQueue.async {
|
||||||
|
completionHandler(disposition.sessionDisposition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
|
override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
|
||||||
let copiedRequest = request
|
let copiedRequest = request
|
||||||
return session.dataTask(with: copiedRequest)
|
return session.dataTask(with: copiedRequest)
|
||||||
@@ -1179,7 +1225,48 @@ public class DataRequest: Request {
|
|||||||
withResult: result)
|
withResult: result)
|
||||||
}
|
}
|
||||||
|
|
||||||
$validators.write { $0.append(validator) }
|
validators.write { $0.append(validator) }
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
|
||||||
|
/// handler to return a `ResponseDisposition` value.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||||
|
/// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
|
||||||
|
/// MUST be called, otherwise the request will never complete.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@_disfavoredOverload
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(
|
||||||
|
on queue: DispatchQueue = .main,
|
||||||
|
perform handler: @escaping (_ response: HTTPURLResponse,
|
||||||
|
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
|
||||||
|
) -> Self {
|
||||||
|
dataMutableState.write { mutableState in
|
||||||
|
mutableState.httpResponseHandler = (queue, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||||
|
/// - handler: Closure called when the instance produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(on queue: DispatchQueue = .main,
|
||||||
|
perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
|
||||||
|
onHTTPResponse(on: queue) { response, completionHandler in
|
||||||
|
handler(response)
|
||||||
|
completionHandler(.allow)
|
||||||
|
}
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@@ -1259,10 +1346,13 @@ public final class DataStreamRequest: Request {
|
|||||||
var numberOfExecutingStreams = 0
|
var numberOfExecutingStreams = 0
|
||||||
/// Completion calls enqueued while streams are still executing.
|
/// Completion calls enqueued while streams are still executing.
|
||||||
var enqueuedCompletionEvents: [() -> Void] = []
|
var enqueuedCompletionEvents: [() -> Void] = []
|
||||||
|
/// Handler for any `HTTPURLResponse`s received.
|
||||||
|
var httpResponseHandler: (queue: DispatchQueue,
|
||||||
|
handler: (_ response: HTTPURLResponse,
|
||||||
|
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Protected
|
let streamMutableState = Protected(StreamMutableState())
|
||||||
var streamMutableState = StreamMutableState()
|
|
||||||
|
|
||||||
/// Creates a `DataStreamRequest` using the provided parameters.
|
/// Creates a `DataStreamRequest` using the provided parameters.
|
||||||
///
|
///
|
||||||
@@ -1306,7 +1396,7 @@ public final class DataStreamRequest: Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func finish(error: AFError? = nil) {
|
override func finish(error: AFError? = nil) {
|
||||||
$streamMutableState.write { state in
|
streamMutableState.write { state in
|
||||||
state.outputStream?.close()
|
state.outputStream?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,8 +1404,8 @@ public final class DataStreamRequest: Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func didReceive(data: Data) {
|
func didReceive(data: Data) {
|
||||||
$streamMutableState.write { state in
|
streamMutableState.write { state in
|
||||||
#if !(os(Linux) || os(Windows))
|
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||||
if let stream = state.outputStream {
|
if let stream = state.outputStream {
|
||||||
underlyingQueue.async {
|
underlyingQueue.async {
|
||||||
var bytes = Array(data)
|
var bytes = Array(data)
|
||||||
@@ -1329,6 +1419,30 @@ public final class DataStreamRequest: Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||||
|
streamMutableState.read { dataMutableState in
|
||||||
|
guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
|
||||||
|
underlyingQueue.async { completionHandler(.allow) }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
httpResponseHandler.queue.async {
|
||||||
|
httpResponseHandler.handler(response) { disposition in
|
||||||
|
if disposition == .cancel {
|
||||||
|
self.mutableState.write { mutableState in
|
||||||
|
mutableState.state = .cancelled
|
||||||
|
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.underlyingQueue.async {
|
||||||
|
completionHandler(disposition.sessionDisposition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Validates the `URLRequest` and `HTTPURLResponse` received for the instance using the provided `Validation` closure.
|
/// Validates the `URLRequest` and `HTTPURLResponse` received for the instance using the provided `Validation` closure.
|
||||||
///
|
///
|
||||||
/// - Parameter validation: `Validation` closure used to validate the request and response.
|
/// - Parameter validation: `Validation` closure used to validate the request and response.
|
||||||
@@ -1351,12 +1465,12 @@ public final class DataStreamRequest: Request {
|
|||||||
withResult: result)
|
withResult: result)
|
||||||
}
|
}
|
||||||
|
|
||||||
$validators.write { $0.append(validator) }
|
validators.write { $0.append(validator) }
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||||
/// Produces an `InputStream` that receives the `Data` received by the instance.
|
/// Produces an `InputStream` that receives the `Data` received by the instance.
|
||||||
///
|
///
|
||||||
/// - Note: The `InputStream` produced by this method must have `open()` called before being able to read `Data`.
|
/// - Note: The `InputStream` produced by this method must have `open()` called before being able to read `Data`.
|
||||||
@@ -1370,7 +1484,7 @@ public final class DataStreamRequest: Request {
|
|||||||
defer { resume() }
|
defer { resume() }
|
||||||
|
|
||||||
var inputStream: InputStream?
|
var inputStream: InputStream?
|
||||||
$streamMutableState.write { state in
|
streamMutableState.write { state in
|
||||||
Foundation.Stream.getBoundStreams(withBufferSize: bufferSize,
|
Foundation.Stream.getBoundStreams(withBufferSize: bufferSize,
|
||||||
inputStream: &inputStream,
|
inputStream: &inputStream,
|
||||||
outputStream: &state.outputStream)
|
outputStream: &state.outputStream)
|
||||||
@@ -1381,6 +1495,47 @@ public final class DataStreamRequest: Request {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
|
||||||
|
/// handler to return a `ResponseDisposition` value.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||||
|
/// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
|
||||||
|
/// MUST be called, otherwise the request will never complete.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@_disfavoredOverload
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(
|
||||||
|
on queue: DispatchQueue = .main,
|
||||||
|
perform handler: @escaping (_ response: HTTPURLResponse,
|
||||||
|
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
|
||||||
|
) -> Self {
|
||||||
|
streamMutableState.write { mutableState in
|
||||||
|
mutableState.httpResponseHandler = (queue, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||||
|
/// - handler: Closure called when the instance produces an `HTTPURLResponse`.
|
||||||
|
///
|
||||||
|
/// - Returns: The instance.
|
||||||
|
@discardableResult
|
||||||
|
public func onHTTPResponse(on queue: DispatchQueue = .main,
|
||||||
|
perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
|
||||||
|
onHTTPResponse(on: queue) { response, completionHandler in
|
||||||
|
handler(response)
|
||||||
|
completionHandler(.allow)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func capturingError(from closure: () throws -> Void) {
|
func capturingError(from closure: () throws -> Void) {
|
||||||
do {
|
do {
|
||||||
try closure()
|
try closure()
|
||||||
@@ -1395,7 +1550,7 @@ public final class DataStreamRequest: Request {
|
|||||||
appendResponseSerializer {
|
appendResponseSerializer {
|
||||||
self.underlyingQueue.async {
|
self.underlyingQueue.async {
|
||||||
self.responseSerializerDidComplete {
|
self.responseSerializerDidComplete {
|
||||||
self.$streamMutableState.write { state in
|
self.streamMutableState.write { state in
|
||||||
guard state.numberOfExecutingStreams == 0 else {
|
guard state.numberOfExecutingStreams == 0 else {
|
||||||
state.enqueuedCompletionEvents.append {
|
state.enqueuedCompletionEvents.append {
|
||||||
self.enqueueCompletion(on: queue, stream: stream)
|
self.enqueueCompletion(on: queue, stream: stream)
|
||||||
@@ -1546,23 +1701,22 @@ public class DownloadRequest: Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Protected mutable state specific to `DownloadRequest`.
|
/// Protected mutable state specific to `DownloadRequest`.
|
||||||
@Protected
|
private let mutableDownloadState = Protected(DownloadRequestMutableState())
|
||||||
private var mutableDownloadState = DownloadRequestMutableState()
|
|
||||||
|
|
||||||
/// If the download is resumable and is eventually cancelled or fails, this value may be used to resume the download
|
/// If the download is resumable and is eventually cancelled or fails, this value may be used to resume the download
|
||||||
/// using the `download(resumingWith data:)` API.
|
/// using the `download(resumingWith data:)` API.
|
||||||
///
|
///
|
||||||
/// - Note: For more information about `resumeData`, see [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel).
|
/// - Note: For more information about `resumeData`, see [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel).
|
||||||
public var resumeData: Data? {
|
public var resumeData: Data? {
|
||||||
#if !(os(Linux) || os(Windows))
|
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||||
return $mutableDownloadState.resumeData ?? error?.downloadResumeData
|
return mutableDownloadState.resumeData ?? error?.downloadResumeData
|
||||||
#else
|
#else
|
||||||
return $mutableDownloadState.resumeData
|
return mutableDownloadState.resumeData
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the download is successful, the `URL` where the file was downloaded.
|
/// If the download is successful, the `URL` where the file was downloaded.
|
||||||
public var fileURL: URL? { $mutableDownloadState.fileURL }
|
public var fileURL: URL? { mutableDownloadState.fileURL }
|
||||||
|
|
||||||
// MARK: Initial State
|
// MARK: Initial State
|
||||||
|
|
||||||
@@ -1605,7 +1759,7 @@ public class DownloadRequest: Request {
|
|||||||
override func reset() {
|
override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
|
|
||||||
$mutableDownloadState.write {
|
mutableDownloadState.write {
|
||||||
$0.resumeData = nil
|
$0.resumeData = nil
|
||||||
$0.fileURL = nil
|
$0.fileURL = nil
|
||||||
}
|
}
|
||||||
@@ -1620,7 +1774,7 @@ public class DownloadRequest: Request {
|
|||||||
eventMonitor?.request(self, didFinishDownloadingUsing: task, with: result)
|
eventMonitor?.request(self, didFinishDownloadingUsing: task, with: result)
|
||||||
|
|
||||||
switch result {
|
switch result {
|
||||||
case let .success(url): $mutableDownloadState.fileURL = url
|
case let .success(url): mutableDownloadState.fileURL = url
|
||||||
case let .failure(error): self.error = error
|
case let .failure(error): self.error = error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1698,7 +1852,7 @@ public class DownloadRequest: Request {
|
|||||||
///
|
///
|
||||||
/// - Returns: The instance.
|
/// - Returns: The instance.
|
||||||
private func cancel(optionallyProducingResumeData completionHandler: ((_ resumeData: Data?) -> Void)?) -> Self {
|
private func cancel(optionallyProducingResumeData completionHandler: ((_ resumeData: Data?) -> Void)?) -> Self {
|
||||||
$mutableState.write { mutableState in
|
mutableState.write { mutableState in
|
||||||
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
||||||
|
|
||||||
mutableState.state = .cancelled
|
mutableState.state = .cancelled
|
||||||
@@ -1714,7 +1868,7 @@ public class DownloadRequest: Request {
|
|||||||
// Resume to ensure metrics are gathered.
|
// Resume to ensure metrics are gathered.
|
||||||
task.resume()
|
task.resume()
|
||||||
task.cancel { resumeData in
|
task.cancel { resumeData in
|
||||||
self.$mutableDownloadState.resumeData = resumeData
|
self.mutableDownloadState.resumeData = resumeData
|
||||||
self.underlyingQueue.async { self.didCancelTask(task) }
|
self.underlyingQueue.async { self.didCancelTask(task) }
|
||||||
completionHandler(resumeData)
|
completionHandler(resumeData)
|
||||||
}
|
}
|
||||||
@@ -1754,7 +1908,7 @@ public class DownloadRequest: Request {
|
|||||||
withResult: result)
|
withResult: result)
|
||||||
}
|
}
|
||||||
|
|
||||||
$validators.write { $0.append(validator) }
|
validators.write { $0.append(validator) }
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|||||||
2
Pods/Alamofire/Source/RequestTaskMap.swift
generated
2
Pods/Alamofire/Source/RequestTaskMap.swift
generated
@@ -131,7 +131,7 @@ struct RequestTaskMap {
|
|||||||
|
|
||||||
switch (events.completed, events.metricsGathered) {
|
switch (events.completed, events.metricsGathered) {
|
||||||
case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
|
case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
|
||||||
#if os(Linux) // Linux doesn't gather metrics, so unconditionally remove the reference and return true.
|
#if os(Linux) || os(Android) // Linux doesn't gather metrics, so unconditionally remove the reference and return true.
|
||||||
default: self[task] = nil; return true
|
default: self[task] = nil; return true
|
||||||
#else
|
#else
|
||||||
case (false, false):
|
case (false, false):
|
||||||
|
|||||||
@@ -1153,7 +1153,7 @@ extension DataStreamRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$streamMutableState.write { $0.streams.append(parser) }
|
streamMutableState.write { $0.streams.append(parser) }
|
||||||
appendStreamCompletion(on: queue, stream: stream)
|
appendStreamCompletion(on: queue, stream: stream)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -1195,7 +1195,7 @@ extension DataStreamRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$streamMutableState.write { $0.streams.append(parser) }
|
streamMutableState.write { $0.streams.append(parser) }
|
||||||
appendStreamCompletion(on: queue, stream: stream)
|
appendStreamCompletion(on: queue, stream: stream)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -1230,14 +1230,14 @@ extension DataStreamRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$streamMutableState.write { $0.streams.append(parser) }
|
streamMutableState.write { $0.streams.append(parser) }
|
||||||
appendStreamCompletion(on: queue, stream: stream)
|
appendStreamCompletion(on: queue, stream: stream)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateAndCompleteIfPossible() {
|
private func updateAndCompleteIfPossible() {
|
||||||
$streamMutableState.write { state in
|
streamMutableState.write { state in
|
||||||
state.numberOfExecutingStreams -= 1
|
state.numberOfExecutingStreams -= 1
|
||||||
|
|
||||||
guard state.numberOfExecutingStreams == 0, !state.enqueuedCompletionEvents.isEmpty else { return }
|
guard state.numberOfExecutingStreams == 0, !state.enqueuedCompletionEvents.isEmpty else { return }
|
||||||
|
|||||||
66
Pods/Alamofire/Source/ServerTrustEvaluation.swift
generated
66
Pods/Alamofire/Source/ServerTrustEvaluation.swift
generated
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// ServerTrustPolicy.swift
|
// ServerTrustEvaluation.swift
|
||||||
//
|
//
|
||||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||||
//
|
//
|
||||||
@@ -48,7 +48,7 @@ open class ServerTrustManager {
|
|||||||
self.evaluators = evaluators
|
self.evaluators = evaluators
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// Returns the `ServerTrustEvaluating` value for the given host, if one is set.
|
/// Returns the `ServerTrustEvaluating` value for the given host, if one is set.
|
||||||
///
|
///
|
||||||
/// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
|
/// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
|
||||||
@@ -75,8 +75,8 @@ open class ServerTrustManager {
|
|||||||
|
|
||||||
/// A protocol describing the API used to evaluate server trusts.
|
/// A protocol describing the API used to evaluate server trusts.
|
||||||
public protocol ServerTrustEvaluating {
|
public protocol ServerTrustEvaluating {
|
||||||
#if os(Linux) || os(Windows)
|
#if !canImport(Security)
|
||||||
// Implement this once Linux/Windows has API for evaluating server trusts.
|
// Implement this once other platforms have API for evaluating server trusts.
|
||||||
#else
|
#else
|
||||||
/// Evaluates the given `SecTrust` value for the given `host`.
|
/// Evaluates the given `SecTrust` value for the given `host`.
|
||||||
///
|
///
|
||||||
@@ -91,7 +91,7 @@ public protocol ServerTrustEvaluating {
|
|||||||
|
|
||||||
// MARK: - Server Trust Evaluators
|
// MARK: - Server Trust Evaluators
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// An evaluator which uses the default server trust evaluation while allowing you to control whether to validate the
|
/// An evaluator which uses the default server trust evaluation while allowing you to control whether to validate the
|
||||||
/// host provided by the challenge. Applications are encouraged to always validate the host in production environments
|
/// host provided by the challenge. Applications are encouraged to always validate the host in production environments
|
||||||
/// to guarantee the validity of the server's certificate chain.
|
/// to guarantee the validity of the server's certificate chain.
|
||||||
@@ -181,6 +181,15 @@ public final class RevocationTrustEvaluator: ServerTrustEvaluating {
|
|||||||
try trust.af.performValidation(forHost: host)
|
try trust.af.performValidation(forHost: host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, visionOS 1, *) {
|
||||||
|
try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
|
||||||
|
} else {
|
||||||
|
try trust.af.validate(policy: SecPolicy.af.revocation(options: options)) { status, result in
|
||||||
|
AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
||||||
try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
|
try trust.af.evaluate(afterApplying: SecPolicy.af.revocation(options: options))
|
||||||
} else {
|
} else {
|
||||||
@@ -188,6 +197,7 @@ public final class RevocationTrustEvaluator: ServerTrustEvaluating {
|
|||||||
AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
|
AFError.serverTrustEvaluationFailed(reason: .revocationCheckFailed(output: .init(host, trust, status, result), options: options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,10 +365,8 @@ public final class PublicKeysTrustEvaluator: ServerTrustEvaluating {
|
|||||||
|
|
||||||
let pinnedKeysInServerKeys: Bool = {
|
let pinnedKeysInServerKeys: Bool = {
|
||||||
for serverPublicKey in trust.af.publicKeys {
|
for serverPublicKey in trust.af.publicKeys {
|
||||||
for pinnedPublicKey in keys {
|
if keys.contains(serverPublicKey) {
|
||||||
if serverPublicKey == pinnedPublicKey {
|
return true
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -449,7 +457,7 @@ public final class DisabledTrustEvaluator: ServerTrustEvaluating {
|
|||||||
// MARK: - Extensions
|
// MARK: - Extensions
|
||||||
|
|
||||||
extension Array where Element == ServerTrustEvaluating {
|
extension Array where Element == ServerTrustEvaluating {
|
||||||
#if os(Linux) || os(Windows)
|
#if os(Linux) || os(Windows) || os(Android)
|
||||||
// Add this same convenience method for Linux/Windows.
|
// Add this same convenience method for Linux/Windows.
|
||||||
#else
|
#else
|
||||||
/// Evaluates the given `SecTrust` value for the given `host`.
|
/// Evaluates the given `SecTrust` value for the given `host`.
|
||||||
@@ -598,7 +606,15 @@ extension AlamofireExtension where ExtendedType == SecTrust {
|
|||||||
|
|
||||||
/// The `SecCertificate`s contained in `self`.
|
/// The `SecCertificate`s contained in `self`.
|
||||||
public var certificates: [SecCertificate] {
|
public var certificates: [SecCertificate] {
|
||||||
#if swift(>=5.5.1) // Xcode 13.1 / 2021 SDKs.
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 15, macOS 12, tvOS 15, watchOS 8, visionOS 1, *) {
|
||||||
|
return (SecTrustCopyCertificateChain(type) as? [SecCertificate]) ?? []
|
||||||
|
} else {
|
||||||
|
return (0..<SecTrustGetCertificateCount(type)).compactMap { index in
|
||||||
|
SecTrustGetCertificateAtIndex(type, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elseif swift(>=5.5.1) // Xcode 13.1 / 2021 SDKs.
|
||||||
if #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) {
|
if #available(iOS 15, macOS 12, tvOS 15, watchOS 8, *) {
|
||||||
return (SecTrustCopyCertificateChain(type) as? [SecCertificate]) ?? []
|
return (SecTrustCopyCertificateChain(type) as? [SecCertificate]) ?? []
|
||||||
} else {
|
} else {
|
||||||
@@ -623,6 +639,15 @@ extension AlamofireExtension where ExtendedType == SecTrust {
|
|||||||
/// - Parameter host: The hostname, used only in the error output if validation fails.
|
/// - Parameter host: The hostname, used only in the error output if validation fails.
|
||||||
/// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
|
/// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
|
||||||
public func performDefaultValidation(forHost host: String) throws {
|
public func performDefaultValidation(forHost host: String) throws {
|
||||||
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, visionOS 1, *) {
|
||||||
|
try evaluate(afterApplying: SecPolicy.af.default)
|
||||||
|
} else {
|
||||||
|
try validate(policy: SecPolicy.af.default) { status, result in
|
||||||
|
AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
||||||
try evaluate(afterApplying: SecPolicy.af.default)
|
try evaluate(afterApplying: SecPolicy.af.default)
|
||||||
} else {
|
} else {
|
||||||
@@ -630,6 +655,7 @@ extension AlamofireExtension where ExtendedType == SecTrust {
|
|||||||
AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
|
AFError.serverTrustEvaluationFailed(reason: .defaultEvaluationFailed(output: .init(host, type, status, result)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates `self` after applying `SecPolicy.af.hostname(host)`, which performs the default validation as well as
|
/// Validates `self` after applying `SecPolicy.af.hostname(host)`, which performs the default validation as well as
|
||||||
@@ -638,6 +664,15 @@ extension AlamofireExtension where ExtendedType == SecTrust {
|
|||||||
/// - Parameter host: The hostname to use in the validation.
|
/// - Parameter host: The hostname to use in the validation.
|
||||||
/// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
|
/// - Throws: An `AFError.serverTrustEvaluationFailed` instance with a `.defaultEvaluationFailed` reason.
|
||||||
public func performValidation(forHost host: String) throws {
|
public func performValidation(forHost host: String) throws {
|
||||||
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, visionOS 1, *) {
|
||||||
|
try evaluate(afterApplying: SecPolicy.af.hostname(host))
|
||||||
|
} else {
|
||||||
|
try validate(policy: SecPolicy.af.hostname(host)) { status, result in
|
||||||
|
AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
if #available(iOS 12, macOS 10.14, tvOS 12, watchOS 5, *) {
|
||||||
try evaluate(afterApplying: SecPolicy.af.hostname(host))
|
try evaluate(afterApplying: SecPolicy.af.hostname(host))
|
||||||
} else {
|
} else {
|
||||||
@@ -645,6 +680,7 @@ extension AlamofireExtension where ExtendedType == SecTrust {
|
|||||||
AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
|
AFError.serverTrustEvaluationFailed(reason: .hostValidationFailed(output: .init(host, type, status, result)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,11 +740,19 @@ extension AlamofireExtension where ExtendedType == SecCertificate {
|
|||||||
|
|
||||||
guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
|
guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
|
||||||
|
|
||||||
|
#if swift(>=5.9)
|
||||||
|
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, visionOS 1, *) {
|
||||||
|
return SecTrustCopyKey(createdTrust)
|
||||||
|
} else {
|
||||||
|
return SecTrustCopyPublicKey(createdTrust)
|
||||||
|
}
|
||||||
|
#else
|
||||||
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, *) {
|
if #available(iOS 14, macOS 11, tvOS 14, watchOS 7, *) {
|
||||||
return SecTrustCopyKey(createdTrust)
|
return SecTrustCopyKey(createdTrust)
|
||||||
} else {
|
} else {
|
||||||
return SecTrustCopyPublicKey(createdTrust)
|
return SecTrustCopyPublicKey(createdTrust)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
Pods/Alamofire/Source/SessionDelegate.swift
generated
25
Pods/Alamofire/Source/SessionDelegate.swift
generated
@@ -94,7 +94,7 @@ extension SessionDelegate: URLSessionTaskDelegate {
|
|||||||
case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM,
|
case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM,
|
||||||
NSURLAuthenticationMethodNegotiate:
|
NSURLAuthenticationMethodNegotiate:
|
||||||
evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
|
evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
case NSURLAuthenticationMethodServerTrust:
|
case NSURLAuthenticationMethodServerTrust:
|
||||||
evaluation = attemptServerTrustAuthentication(with: challenge)
|
evaluation = attemptServerTrustAuthentication(with: challenge)
|
||||||
case NSURLAuthenticationMethodClientCertificate:
|
case NSURLAuthenticationMethodClientCertificate:
|
||||||
@@ -111,7 +111,7 @@ extension SessionDelegate: URLSessionTaskDelegate {
|
|||||||
completionHandler(evaluation.disposition, evaluation.credential)
|
completionHandler(evaluation.disposition, evaluation.credential)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(os(Linux) || os(Windows))
|
#if canImport(Security)
|
||||||
/// Evaluates the server trust `URLAuthenticationChallenge` received.
|
/// Evaluates the server trust `URLAuthenticationChallenge` received.
|
||||||
///
|
///
|
||||||
/// - Parameter challenge: The `URLAuthenticationChallenge`.
|
/// - Parameter challenge: The `URLAuthenticationChallenge`.
|
||||||
@@ -230,6 +230,25 @@ extension SessionDelegate: URLSessionTaskDelegate {
|
|||||||
// MARK: URLSessionDataDelegate
|
// MARK: URLSessionDataDelegate
|
||||||
|
|
||||||
extension SessionDelegate: URLSessionDataDelegate {
|
extension SessionDelegate: URLSessionDataDelegate {
|
||||||
|
open func urlSession(_ session: URLSession,
|
||||||
|
dataTask: URLSessionDataTask,
|
||||||
|
didReceive response: URLResponse,
|
||||||
|
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||||
|
eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: response)
|
||||||
|
|
||||||
|
guard let response = response as? HTTPURLResponse else { completionHandler(.allow); return }
|
||||||
|
|
||||||
|
if let request = request(for: dataTask, as: DataRequest.self) {
|
||||||
|
request.didReceiveResponse(response, completionHandler: completionHandler)
|
||||||
|
} else if let request = request(for: dataTask, as: DataStreamRequest.self) {
|
||||||
|
request.didReceiveResponse(response, completionHandler: completionHandler)
|
||||||
|
} else {
|
||||||
|
assertionFailure("dataTask did not find DataRequest or DataStreamRequest in didReceive response")
|
||||||
|
completionHandler(.allow)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||||
eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
|
eventMonitor?.urlSession(session, dataTask: dataTask, didReceive: data)
|
||||||
|
|
||||||
@@ -238,7 +257,7 @@ extension SessionDelegate: URLSessionDataDelegate {
|
|||||||
} else if let request = request(for: dataTask, as: DataStreamRequest.self) {
|
} else if let request = request(for: dataTask, as: DataStreamRequest.self) {
|
||||||
request.didReceive(data: data)
|
request.didReceive(data: data)
|
||||||
} else {
|
} else {
|
||||||
assertionFailure("dataTask did not find DataRequest or DataStreamRequest in didReceive")
|
assertionFailure("dataTask did not find DataRequest or DataStreamRequest in didReceive data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
68
Pods/Alamofire/Source/URLEncodedFormEncoder.swift
generated
68
Pods/Alamofire/Source/URLEncodedFormEncoder.swift
generated
@@ -695,6 +695,74 @@ extension _URLEncodedFormEncoder.KeyedContainer: KeyedEncodingContainerProtocol
|
|||||||
try encode(nilValue, forKey: key)
|
try encode(nilValue, forKey: key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: String?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeIfPresent<Value>(_ value: Value?, forKey key: Key) throws where Value: Encodable {
|
||||||
|
try _encodeIfPresent(value, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _encodeIfPresent<Value>(_ value: Value?, forKey key: Key) throws where Value: Encodable {
|
||||||
|
if let value = value {
|
||||||
|
try encode(value, forKey: key)
|
||||||
|
} else {
|
||||||
|
try encodeNil(forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
|
func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
|
||||||
var container = nestedSingleValueEncoder(for: key)
|
var container = nestedSingleValueEncoder(for: key)
|
||||||
try container.encode(value)
|
try container.encode(value)
|
||||||
|
|||||||
@@ -17,52 +17,76 @@ extension DDAlamofire {
|
|||||||
public init() {}
|
public init() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum DDError : Error {
|
||||||
|
case allError
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: example
|
// MARK: example
|
||||||
public func get<T:Decodable,P:Encodable>(urlString:String,parameters:P? = DDParameters(),encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self) -> Single<T?> {
|
public func get<T:Decodable,P:Encodable>(urlString:String,parameters:P? = DDParameters(),encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: (((SingleEvent<T?>) -> Void,AFDataResponse<T>) -> Void)? = nil) -> Single<T?> {
|
||||||
return Single<T?>.create {[weak self] single in
|
return Single<T?>.create {[weak self] single in
|
||||||
self?.request(urlString: urlString, method: .get,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
self?.request(urlString: urlString, method: .get,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
||||||
self?.logInfo(parameters: parameters, response: response)
|
self?.logInfo(parameters: parameters, response: response)
|
||||||
single(.success(response.value))
|
if let completionHandler {
|
||||||
|
completionHandler(single,response)
|
||||||
|
}else{
|
||||||
|
single(.success(response.value))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Disposables.create()
|
return Disposables.create()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func post<T:Decodable,P:Encodable>(urlString:String,parameters:P? = DDParameters(),encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self) -> Single<T?> {
|
public func post<T:Decodable,P:Encodable>(urlString:String,parameters:P? = DDParameters(),encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: (((SingleEvent<T?>) -> Void,AFDataResponse<T>) -> Void)? = nil) -> Single<T?> {
|
||||||
return Single<T?>.create {[weak self] single in
|
return Single<T?>.create {[weak self] single in
|
||||||
self?.request(urlString: urlString, method: .post,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
self?.request(urlString: urlString, method: .post,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
||||||
self?.logInfo(parameters: parameters, response: response)
|
self?.logInfo(parameters: parameters, response: response)
|
||||||
single(.success(response.value))
|
if let completionHandler {
|
||||||
|
completionHandler(single,response)
|
||||||
|
}else{
|
||||||
|
single(.success(response.value))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Disposables.create()
|
return Disposables.create()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func get<T:Decodable>(urlString:String,parameters:[String:Any]? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self) -> Single<T?> {
|
public func get<T:Decodable>(urlString:String,parameters:[String:Any]? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: (((SingleEvent<T?>) -> Void,AFDataResponse<T>) -> Void)? = nil) -> Single<T?> {
|
||||||
return Single<T?>.create {[weak self] single in
|
return Single<T?>.create {[weak self] single in
|
||||||
self?.request(urlString: urlString, method: .get,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
self?.request(urlString: urlString, method: .get,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
||||||
self?.logInfo(parameters: parameters, response: response)
|
self?.logInfo(parameters: parameters, response: response)
|
||||||
single(.success(response.value))
|
if let completionHandler {
|
||||||
|
completionHandler(single,response)
|
||||||
|
}else{
|
||||||
|
single(.success(response.value))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Disposables.create()
|
return Disposables.create()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func post<T:Decodable>(urlString:String,parameters:[String:Any]? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self) -> Single<T?> {
|
public func post<T:Decodable>(urlString:String,parameters:[String:Any]? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: (((SingleEvent<T?>) -> Void,AFDataResponse<T>) -> Void)? = nil) -> Single<T?> {
|
||||||
return Single<T?>.create {[weak self] single in
|
return Single<T?>.create {[weak self] single in
|
||||||
self?.request(urlString: urlString, method: .post,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
self?.request(urlString: urlString, method: .post,parameters: parameters,encoding: encoding,headers: headers,responseType: responseType,completionHandler: {[weak self] response in
|
||||||
self?.logInfo(parameters: parameters, response: response)
|
self?.logInfo(parameters: parameters, response: response)
|
||||||
single(.success(response.value))
|
if let completionHandler {
|
||||||
|
completionHandler(single,response)
|
||||||
|
}else{
|
||||||
|
single(.success(response.value))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Disposables.create()
|
return Disposables.create()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func upload<T:Decodable>(urlString:String,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,multipartFormData: @escaping (MultipartFormData) -> Void,uploadProgress: @escaping (Progress) -> Void) -> Single<T?> {
|
public func upload<T:Decodable>(urlString:String,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,multipartFormData: @escaping (MultipartFormData) -> Void,uploadProgress: @escaping (Progress) -> Void,completionHandler: (((SingleEvent<T?>) -> Void,AFDataResponse<T>) -> Void)? = nil) -> Single<T?> {
|
||||||
return Single<T?>.create {[weak self] single in
|
return Single<T?>.create {[weak self] single in
|
||||||
self?.upload(urlString: urlString,method: .post,headers: headers,responseType: responseType,multipartFormData: multipartFormData,uploadProgress: uploadProgress,completionHandler: { response in
|
self?.upload(urlString: urlString,method: .post,headers: headers,responseType: responseType,multipartFormData: multipartFormData,uploadProgress: uploadProgress,completionHandler: { response in
|
||||||
self?.logInfo(parameters: nil, response: response)
|
self?.logInfo(parameters: nil, response: response)
|
||||||
single(.success(response.value))
|
if let completionHandler {
|
||||||
|
completionHandler(single,response)
|
||||||
|
}else{
|
||||||
|
single(.success(response.value))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Disposables.create()
|
return Disposables.create()
|
||||||
}
|
}
|
||||||
|
|||||||
8
Pods/Manifest.lock
generated
8
Pods/Manifest.lock
generated
@@ -1,5 +1,5 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Alamofire (5.7.1)
|
- Alamofire (5.8.1)
|
||||||
- AMapFoundation-NO-IDFA (1.8.2)
|
- AMapFoundation-NO-IDFA (1.8.2)
|
||||||
- AMapLocation-NO-IDFA (2.9.0):
|
- AMapLocation-NO-IDFA (2.9.0):
|
||||||
- AMapFoundation-NO-IDFA (>= 1.7.0)
|
- AMapFoundation-NO-IDFA (>= 1.7.0)
|
||||||
@@ -270,7 +270,7 @@ PODS:
|
|||||||
- DDLogKit_Private
|
- DDLogKit_Private
|
||||||
- DDMAMapKit_Private/DDMAUtil (0.1.5):
|
- DDMAMapKit_Private/DDMAUtil (0.1.5):
|
||||||
- DDMAMapKit_Private/DDMAMap
|
- DDMAMapKit_Private/DDMAMap
|
||||||
- DDNetworkingOfAlamofireKit_Private (0.1.8):
|
- DDNetworkingOfAlamofireKit_Private (0.2.1):
|
||||||
- Alamofire
|
- Alamofire
|
||||||
- DDLogKit_Private
|
- DDLogKit_Private
|
||||||
- RxSwift
|
- RxSwift
|
||||||
@@ -412,7 +412,7 @@ SPEC REPOS:
|
|||||||
- ZLPhotoBrowser
|
- ZLPhotoBrowser
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: 0123a34370cb170936ae79a8df46cc62b2edeb88
|
Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7
|
||||||
AMapFoundation-NO-IDFA: 6ce0ef596d4eb8d934ff498e56747b6de1247b05
|
AMapFoundation-NO-IDFA: 6ce0ef596d4eb8d934ff498e56747b6de1247b05
|
||||||
AMapLocation-NO-IDFA: 6839d1543b3138ae594ddd36ab72741dc87df66f
|
AMapLocation-NO-IDFA: 6839d1543b3138ae594ddd36ab72741dc87df66f
|
||||||
AMapNavi-NO-IDFA: 70c724400376bfadcb8ec08b9761f526096cfdb6
|
AMapNavi-NO-IDFA: 70c724400376bfadcb8ec08b9761f526096cfdb6
|
||||||
@@ -430,7 +430,7 @@ SPEC CHECKSUMS:
|
|||||||
DDFontKit_Private: 7b8f4ebf0f60622874036202734d8460dc7b3806
|
DDFontKit_Private: 7b8f4ebf0f60622874036202734d8460dc7b3806
|
||||||
DDLogKit_Private: 1ed442cc7be004bd05f27bfda9b525e113df54e0
|
DDLogKit_Private: 1ed442cc7be004bd05f27bfda9b525e113df54e0
|
||||||
DDMAMapKit_Private: b378d69f693d6998d136155cd5c81be2e4545fae
|
DDMAMapKit_Private: b378d69f693d6998d136155cd5c81be2e4545fae
|
||||||
DDNetworkingOfAlamofireKit_Private: d65c96f99bc59311d374e7b7a7e8a9e042d9b5ea
|
DDNetworkingOfAlamofireKit_Private: 652eb70a7d8bac81d77d036fabeb52f807120f6d
|
||||||
DDPersistenceKit_Private: c150822543ffa6ece3900178629812f64902ed90
|
DDPersistenceKit_Private: c150822543ffa6ece3900178629812f64902ed90
|
||||||
DDProgressHUDKit_Private: 1e219062ddeb7801a4bb13b367efa1f3fbf17f1e
|
DDProgressHUDKit_Private: 1e219062ddeb7801a4bb13b367efa1f3fbf17f1e
|
||||||
DDTimerSwiftKit_Private: cce3fe58b1b581fe4cddb3fb84fcde31b4e83541
|
DDTimerSwiftKit_Private: cce3fe58b1b581fe4cddb3fb84fcde31b4e83541
|
||||||
|
|||||||
Reference in New Issue
Block a user