[Swift 5] create sample for URLSsession and Alamofire bearer authentication (#8302)

* [swift] create a sample of bearer token authentication with URLSession

* [swift] create a sample of bearer token authentication with URLSession

* [swift] create a sample of bearer token authentication with URLSession

* [swift] create a sample of bearer token authentication with URLSession

* [swift] create a sample of bearer token authentication with Alamofire

* [swift] create a sample of bearer token authentication with Alamofire
This commit is contained in:
Bruno Coelho 2021-01-04 02:03:26 +00:00 committed by GitHub
parent 72d6cff188
commit 163c70e7d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 296 additions and 54 deletions

View File

@ -20,4 +20,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 509bec696cc1d8641751b52e4fe4bef04ac4542c
COCOAPODS: 1.9.0
COCOAPODS: 1.10.0

View File

@ -7,8 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
198019EEC6E3CB01FC884C7A /* Pods_SwaggerClientTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D829DFE4E137D91D6174D75A /* Pods_SwaggerClientTests.framework */; };
1A501F48219C3DC600F372F6 /* DateFormatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A501F47219C3DC600F372F6 /* DateFormatTests.swift */; };
23B2E76564651097BE2FE501 /* Pods_SwaggerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F98CC8B18E5FA9213F6A68D /* Pods_SwaggerClient.framework */; };
6D4EFB951C692C6300B96B06 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFB941C692C6300B96B06 /* AppDelegate.swift */; };
6D4EFB971C692C6300B96B06 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFB961C692C6300B96B06 /* ViewController.swift */; };
6D4EFB9A1C692C6300B96B06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D4EFB981C692C6300B96B06 /* Main.storyboard */; };
@ -17,9 +17,10 @@
6D4EFBB51C693BE200B96B06 /* PetAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB41C693BE200B96B06 /* PetAPITests.swift */; };
6D4EFBB71C693BED00B96B06 /* StoreAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */; };
6D4EFBB91C693BFC00B96B06 /* UserAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */; };
A5465873259E306E00C3929B /* BearerDecodableRequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5465872259E306E00C3929B /* BearerDecodableRequestBuilder.swift */; };
A5EA12542419387200E30FC3 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA12522419387100E30FC3 /* FileUtils.swift */; };
A5EA12552419387200E30FC3 /* UIImage+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA12532419387100E30FC3 /* UIImage+Extras.swift */; };
FB5CCC7EFA680BB2746B695B /* Pods_SwaggerClientTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83FDC034BBA2A07AE9975250 /* Pods_SwaggerClientTests.framework */; };
B68489033454646C60C16C88 /* Pods_SwaggerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79549D5237E5E83F567030EC /* Pods_SwaggerClient.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -33,8 +34,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
081E9B893DEB1589CB807EA7 /* Pods-SwaggerClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.debug.xcconfig"; sourceTree = "<group>"; };
1A501F47219C3DC600F372F6 /* DateFormatTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormatTests.swift; sourceTree = "<group>"; };
32ED0E88E0B89A537075D9C9 /* Pods-SwaggerClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.debug.xcconfig"; path = "Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.debug.xcconfig"; sourceTree = "<group>"; };
6D4EFB911C692C6300B96B06 /* SwaggerClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwaggerClient.app; sourceTree = BUILT_PRODUCTS_DIR; };
6D4EFB941C692C6300B96B06 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6D4EFB961C692C6300B96B06 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@ -47,14 +48,15 @@
6D4EFBB41C693BE200B96B06 /* PetAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetAPITests.swift; sourceTree = "<group>"; };
6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreAPITests.swift; sourceTree = "<group>"; };
6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAPITests.swift; sourceTree = "<group>"; };
7F98CC8B18E5FA9213F6A68D /* Pods_SwaggerClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83FDC034BBA2A07AE9975250 /* Pods_SwaggerClientTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClientTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74246FD63841F7C179AD697F /* Pods-SwaggerClientTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClientTests.debug.xcconfig"; path = "Target Support Files/Pods-SwaggerClientTests/Pods-SwaggerClientTests.debug.xcconfig"; sourceTree = "<group>"; };
79549D5237E5E83F567030EC /* Pods_SwaggerClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8ABA6AE59F792DAA1F79C48F /* Pods-SwaggerClientTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClientTests.release.xcconfig"; path = "Target Support Files/Pods-SwaggerClientTests/Pods-SwaggerClientTests.release.xcconfig"; sourceTree = "<group>"; };
A5465872259E306E00C3929B /* BearerDecodableRequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BearerDecodableRequestBuilder.swift; sourceTree = "<group>"; };
A5EA12522419387100E30FC3 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
A5EA12532419387100E30FC3 /* UIImage+Extras.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extras.swift"; sourceTree = "<group>"; };
ACB80AC61FA8D8916D4559AA /* Pods-SwaggerClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.release.xcconfig"; sourceTree = "<group>"; };
C07EC0A94AA0F86D60668B32 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E43FC34A9681D65ED44EE914 /* Pods-SwaggerClientTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClientTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClientTests/Pods-SwaggerClientTests.debug.xcconfig"; sourceTree = "<group>"; };
ED8576754DBB828CAE63EA87 /* Pods-SwaggerClientTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClientTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClientTests/Pods-SwaggerClientTests.release.xcconfig"; sourceTree = "<group>"; };
D829DFE4E137D91D6174D75A /* Pods_SwaggerClientTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClientTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FB503FF47F354A87D697DD0A /* Pods-SwaggerClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.release.xcconfig"; path = "Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -62,7 +64,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
23B2E76564651097BE2FE501 /* Pods_SwaggerClient.framework in Frameworks */,
B68489033454646C60C16C88 /* Pods_SwaggerClient.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -70,30 +72,19 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FB5CCC7EFA680BB2746B695B /* Pods_SwaggerClientTests.framework in Frameworks */,
198019EEC6E3CB01FC884C7A /* Pods_SwaggerClientTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
203D4495376E4EB72474B091 /* Pods */ = {
isa = PBXGroup;
children = (
081E9B893DEB1589CB807EA7 /* Pods-SwaggerClient.debug.xcconfig */,
ACB80AC61FA8D8916D4559AA /* Pods-SwaggerClient.release.xcconfig */,
E43FC34A9681D65ED44EE914 /* Pods-SwaggerClientTests.debug.xcconfig */,
ED8576754DBB828CAE63EA87 /* Pods-SwaggerClientTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
3FABC56EC0BA84CBF4F99564 /* Frameworks */ = {
isa = PBXGroup;
children = (
C07EC0A94AA0F86D60668B32 /* Pods.framework */,
7F98CC8B18E5FA9213F6A68D /* Pods_SwaggerClient.framework */,
83FDC034BBA2A07AE9975250 /* Pods_SwaggerClientTests.framework */,
79549D5237E5E83F567030EC /* Pods_SwaggerClient.framework */,
D829DFE4E137D91D6174D75A /* Pods_SwaggerClientTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -105,7 +96,7 @@
6D4EFBA81C692C6300B96B06 /* SwaggerClientTests */,
6D4EFB921C692C6300B96B06 /* Products */,
3FABC56EC0BA84CBF4F99564 /* Frameworks */,
203D4495376E4EB72474B091 /* Pods */,
AC485EA5DC51CA28F3F7FECF /* Pods */,
);
sourceTree = "<group>";
};
@ -123,6 +114,7 @@
children = (
6D4EFB941C692C6300B96B06 /* AppDelegate.swift */,
6D4EFB961C692C6300B96B06 /* ViewController.swift */,
A5465872259E306E00C3929B /* BearerDecodableRequestBuilder.swift */,
6D4EFB981C692C6300B96B06 /* Main.storyboard */,
6D4EFB9B1C692C6300B96B06 /* Assets.xcassets */,
6D4EFB9D1C692C6300B96B06 /* LaunchScreen.storyboard */,
@ -145,6 +137,18 @@
path = SwaggerClientTests;
sourceTree = "<group>";
};
AC485EA5DC51CA28F3F7FECF /* Pods */ = {
isa = PBXGroup;
children = (
32ED0E88E0B89A537075D9C9 /* Pods-SwaggerClient.debug.xcconfig */,
FB503FF47F354A87D697DD0A /* Pods-SwaggerClient.release.xcconfig */,
74246FD63841F7C179AD697F /* Pods-SwaggerClientTests.debug.xcconfig */,
8ABA6AE59F792DAA1F79C48F /* Pods-SwaggerClientTests.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -152,11 +156,11 @@
isa = PBXNativeTarget;
buildConfigurationList = 6D4EFBAE1C692C6300B96B06 /* Build configuration list for PBXNativeTarget "SwaggerClient" */;
buildPhases = (
5BC9214E8D9BA5A427A3775B /* [CP] Check Pods Manifest.lock */,
53EC90CFFB0E0FABA75F972D /* [CP] Check Pods Manifest.lock */,
6D4EFB8D1C692C6300B96B06 /* Sources */,
6D4EFB8E1C692C6300B96B06 /* Frameworks */,
6D4EFB8F1C692C6300B96B06 /* Resources */,
FDCA0F14611FE114BFEBA8BB /* [CP] Embed Pods Frameworks */,
3E0F8DF721D95AAFC75864D4 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -171,7 +175,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 6D4EFBB11C692C6300B96B06 /* Build configuration list for PBXNativeTarget "SwaggerClientTests" */;
buildPhases = (
EEDC5E683F9569976B7C1192 /* [CP] Check Pods Manifest.lock */,
89F684025365A60C007C7DA9 /* [CP] Check Pods Manifest.lock */,
6D4EFBA11C692C6300B96B06 /* Sources */,
6D4EFBA21C692C6300B96B06 /* Frameworks */,
6D4EFBA31C692C6300B96B06 /* Resources */,
@ -247,7 +251,27 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
5BC9214E8D9BA5A427A3775B /* [CP] Check Pods Manifest.lock */ = {
3E0F8DF721D95AAFC75864D4 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
"${BUILT_PRODUCTS_DIR}/PetstoreClient/PetstoreClient.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PetstoreClient.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
53EC90CFFB0E0FABA75F972D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -269,7 +293,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
EEDC5E683F9569976B7C1192 /* [CP] Check Pods Manifest.lock */ = {
89F684025365A60C007C7DA9 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -291,26 +315,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FDCA0F14611FE114BFEBA8BB /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
"${BUILT_PRODUCTS_DIR}/PetstoreClient/PetstoreClient.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PetstoreClient.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -319,6 +323,7 @@
buildActionMask = 2147483647;
files = (
6D4EFB971C692C6300B96B06 /* ViewController.swift in Sources */,
A5465873259E306E00C3929B /* BearerDecodableRequestBuilder.swift in Sources */,
6D4EFB951C692C6300B96B06 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -476,7 +481,7 @@
};
6D4EFBAF1C692C6300B96B06 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 081E9B893DEB1589CB807EA7 /* Pods-SwaggerClient.debug.xcconfig */;
baseConfigurationReference = 32ED0E88E0B89A537075D9C9 /* Pods-SwaggerClient.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SwaggerClient/Info.plist;
@ -489,7 +494,7 @@
};
6D4EFBB01C692C6300B96B06 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = ACB80AC61FA8D8916D4559AA /* Pods-SwaggerClient.release.xcconfig */;
baseConfigurationReference = FB503FF47F354A87D697DD0A /* Pods-SwaggerClient.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SwaggerClient/Info.plist;
@ -502,7 +507,7 @@
};
6D4EFBB21C692C6300B96B06 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E43FC34A9681D65ED44EE914 /* Pods-SwaggerClientTests.debug.xcconfig */;
baseConfigurationReference = 74246FD63841F7C179AD697F /* Pods-SwaggerClientTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = SwaggerClientTests/Info.plist;
@ -516,7 +521,7 @@
};
6D4EFBB31C692C6300B96B06 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = ED8576754DBB828CAE63EA87 /* Pods-SwaggerClientTests.release.xcconfig */;
baseConfigurationReference = 8ABA6AE59F792DAA1F79C48F /* Pods-SwaggerClientTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
INFOPLIST_FILE = SwaggerClientTests/Info.plist;

View File

@ -7,6 +7,7 @@
//
import UIKit
import PetstoreClient
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ -15,6 +16,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Customize requestBuilderFactory
PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()
return true
}

View File

@ -0,0 +1,79 @@
//
// BearerDecodableRequestBuilder.swift
// SwaggerClient
//
// Created by Bruno Coelho on 31/12/2020.
// Copyright © 2020 Swagger. All rights reserved.
//
import Foundation
import Alamofire
import PetstoreClient
class BearerRequestBuilderFactory: RequestBuilderFactory {
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
BearerRequestBuilder<T>.self
}
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
BearerDecodableRequestBuilder<T>.self
}
}
class BearerRequestBuilder<T>: AlamofireRequestBuilder<T> {
override func createSessionManager() -> SessionManager {
let sessionManager = super.createSessionManager()
let bearerTokenHandler = BearerTokenHandler()
sessionManager.adapter = bearerTokenHandler
sessionManager.retrier = bearerTokenHandler
return sessionManager
}
}
class BearerDecodableRequestBuilder<T: Decodable>: AlamofireDecodableRequestBuilder<T> {
override func createSessionManager() -> SessionManager {
let sessionManager = super.createSessionManager()
let bearerTokenHandler = BearerTokenHandler()
sessionManager.adapter = bearerTokenHandler
sessionManager.retrier = bearerTokenHandler
return sessionManager
}
}
class BearerTokenHandler: RequestAdapter, RequestRetrier {
private static var bearerToken: String? = nil
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
if let bearerToken = Self.bearerToken {
var urlRequest = urlRequest
urlRequest.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
return urlRequest
}
return urlRequest
}
func should(_: SessionManager, retry request: Request, with _: Error, completion: @escaping RequestRetryCompletion) {
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
Self.startRefreshingToken { isTokenRefreshed in
completion(isTokenRefreshed, 0.0)
}
} else {
completion(false, 0.0)
}
}
private static func startRefreshingToken(completionHandler: @escaping (Bool) -> Void) {
// Get a bearer token
let dummyBearerToken = "..."
bearerToken = dummyBearerToken
PetstoreClientAPI.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
completionHandler(true)
}
}

View File

@ -17,6 +17,7 @@
6D4EFBB51C693BE200B96B06 /* PetAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB41C693BE200B96B06 /* PetAPITests.swift */; };
6D4EFBB71C693BED00B96B06 /* StoreAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */; };
6D4EFBB91C693BFC00B96B06 /* UserAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */; };
A5465867259E09C600C3929B /* BearerDecodableRequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5465866259E09C600C3929B /* BearerDecodableRequestBuilder.swift */; };
A5EA12642419439700E30FC3 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA12622419439700E30FC3 /* FileUtils.swift */; };
A5EA12652419439700E30FC3 /* UIImage+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA12632419439700E30FC3 /* UIImage+Extras.swift */; };
FB5CCC7EFA680BB2746B695B /* Pods_SwaggerClientTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83FDC034BBA2A07AE9975250 /* Pods_SwaggerClientTests.framework */; };
@ -49,6 +50,7 @@
6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAPITests.swift; sourceTree = "<group>"; };
7F98CC8B18E5FA9213F6A68D /* Pods_SwaggerClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83FDC034BBA2A07AE9975250 /* Pods_SwaggerClientTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClientTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A5465866259E09C600C3929B /* BearerDecodableRequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BearerDecodableRequestBuilder.swift; sourceTree = "<group>"; };
A5EA12622419439700E30FC3 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
A5EA12632419439700E30FC3 /* UIImage+Extras.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extras.swift"; sourceTree = "<group>"; };
ACB80AC61FA8D8916D4559AA /* Pods-SwaggerClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.release.xcconfig"; sourceTree = "<group>"; };
@ -123,6 +125,7 @@
children = (
6D4EFB941C692C6300B96B06 /* AppDelegate.swift */,
6D4EFB961C692C6300B96B06 /* ViewController.swift */,
A5465866259E09C600C3929B /* BearerDecodableRequestBuilder.swift */,
6D4EFB981C692C6300B96B06 /* Main.storyboard */,
6D4EFB9B1C692C6300B96B06 /* Assets.xcassets */,
6D4EFB9D1C692C6300B96B06 /* LaunchScreen.storyboard */,
@ -317,6 +320,7 @@
buildActionMask = 2147483647;
files = (
6D4EFB971C692C6300B96B06 /* ViewController.swift in Sources */,
A5465867259E09C600C3929B /* BearerDecodableRequestBuilder.swift in Sources */,
6D4EFB951C692C6300B96B06 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -7,6 +7,7 @@
//
import UIKit
import PetstoreClient
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ -15,6 +16,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Customize requestBuilderFactory
PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()
return true
}

View File

@ -0,0 +1,144 @@
//
// BearerDecodableRequestBuilder.swift
// SwaggerClient
//
// Created by Bruno Coelho on 31/12/2020.
// Copyright © 2020 Swagger. All rights reserved.
//
import Foundation
import PetstoreClient
class BearerRequestBuilderFactory: RequestBuilderFactory {
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
BearerRequestBuilder<T>.self
}
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
BearerDecodableRequestBuilder<T>.self
}
}
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, Error>) -> Void) {
// Before making the request, we can validate if we have a bearer token to be able to make a request
BearerTokenHandler.refreshTokenIfDoesntExist {
// Here we make the request
super.execute(apiResponseQueue) { result in
switch result {
case .success:
// If we got a successful response, we send the response to the completion block
completion(result)
case let .failure(error):
// If we got a failure response, we will analyse the error to see what we should do with it
if case let ErrorResponse.error(_, data, response, error) = error {
// If the error is an ErrorResponse.error() we will analyse it to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse(
data: data,
response: response,
error: error
) { wasTokenRefreshed in
if wasTokenRefreshed {
// If the token was refreshed, it's because it was a 401 error, so we refreshed the token, and we are going to retry the request by calling self.execute()
self.execute(apiResponseQueue, completion)
} else {
// If the token was not refreshed, it's because it was not a 401 error, so we send the response to the completion block
completion(result)
}
}
} else {
// If it's an unknown error, we send the response to the completion block
completion(result)
}
}
}
}
}
}
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, Error>) -> Void) {
// Before making the request, we can validate if we have a bearer token to be able to make a request
BearerTokenHandler.refreshTokenIfDoesntExist {
// Here we make the request
super.execute(apiResponseQueue) { result in
switch result {
case .success:
// If we got a successful response, we send the response to the completion block
completion(result)
case let .failure(error):
// If we got a failure response, we will analyse the error to see what we should do with it
if case let ErrorResponse.error(_, data, response, error) = error {
// If the error is an ErrorResponse.error() we will analyse it to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse(
data: data,
response: response,
error: error
) { wasTokenRefreshed in
if wasTokenRefreshed {
// If the token was refreshed, it's because it was a 401 error, so we refreshed the token, and we are going to retry the request by calling self.execute()
self.execute(apiResponseQueue, completion)
} else {
// If the token was not refreshed, it's because it was not a 401 error, so we send the response to the completion block
completion(result)
}
}
} else {
// If it's an unknown error, we send the response to the completion block
completion(result)
}
}
}
}
}
}
class BearerTokenHandler {
private static var bearerToken: String? = nil
static func refreshTokenIfDoesntExist(completionHandler: @escaping () -> Void) {
if bearerToken != nil {
completionHandler()
} else {
startRefreshingToken {
completionHandler()
}
}
}
static func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error?, completionHandler: @escaping (Bool) -> Void) {
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
startRefreshingToken {
completionHandler(true)
}
} else {
completionHandler(false)
}
}
private static func startRefreshingToken(completionHandler: @escaping () -> Void) {
// Get a bearer token
let dummyBearerToken = "..."
bearerToken = dummyBearerToken
PetstoreClientAPI.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
completionHandler()
}
}