From 1893c350e9282173bc6a893877b1616de32ef7a9 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 14:20:41 +0000 Subject: [PATCH 1/6] [swift] create a sample of bearer token authentication with URLSession --- .../SwaggerClient.xcodeproj/project.pbxproj | 4 + .../BearerDecodableRequestBuilder.swift | 130 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj index f3d009d59af9..9c371f929dbf 100644 --- a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; A5EA12622419439700E30FC3 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = ""; }; A5EA12632419439700E30FC3 /* UIImage+Extras.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extras.swift"; sourceTree = ""; }; 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 = ""; }; @@ -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; diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift new file mode 100644 index 000000000000..531c2286b59b --- /dev/null +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -0,0 +1,130 @@ +// +// 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() -> RequestBuilder.Type { + BearerRequestBuilder.self + } + + func getBuilder() -> RequestBuilder.Type { + BearerDecodableRequestBuilder.self + } +} + +class BearerRequestBuilder: URLSessionRequestBuilder { + override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result, Error>) -> Void) { + + BearerTokenHandler.refreshTokenIfDoesntExist { + + super.execute(apiResponseQueue) { result in + + switch result { + case .success: + completion(result) + + case let .failure(error): + + if case let ErrorResponse.error(_, data, response, error) = error { + BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse( + data: data, + response: response, + error: error + ) { isTokenRefreshed in + if isTokenRefreshed { + self.execute(apiResponseQueue, completion) + } else { + completion(result) + } + } + } else { + completion(result) + } + + } + } + } + } +} + +class BearerDecodableRequestBuilder: URLSessionDecodableRequestBuilder { + override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result, Error>) -> Void) { + + BearerTokenHandler.refreshTokenIfDoesntExist { + + super.execute(apiResponseQueue) { result in + + switch result { + case .success: + completion(result) + + case let .failure(error): + + if case let ErrorResponse.error(_, data, response, error) = error { + BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse( + data: data, + response: response, + error: error + ) { isTokenRefreshed in + if isTokenRefreshed { + self.execute(apiResponseQueue, completion) + } else { + completion(result) + } + } + } else { + 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) { + guard let response = response as? HTTPURLResponse else { + completionHandler(false) + return + } + + if 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() + } +} From ca0004f8b8f198b1a3b1904f441e9af74df0e4bd Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 14:41:06 +0000 Subject: [PATCH 2/6] [swift] create a sample of bearer token authentication with URLSession --- .../BearerDecodableRequestBuilder.swift | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift index 531c2286b59b..e6b8924dacf6 100644 --- a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -21,30 +21,40 @@ class BearerRequestBuilderFactory: RequestBuilderFactory { class BearerRequestBuilder: URLSessionRequestBuilder { override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result, 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 - ) { isTokenRefreshed in - if isTokenRefreshed { + ) { 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) } @@ -56,30 +66,40 @@ class BearerRequestBuilder: URLSessionRequestBuilder { class BearerDecodableRequestBuilder: URLSessionDecodableRequestBuilder { override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result, 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 - ) { isTokenRefreshed in - if isTokenRefreshed { + ) { 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) } From 64405fa242f978d5056ec43f8db5f3e18e981da5 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 15:00:50 +0000 Subject: [PATCH 3/6] [swift] create a sample of bearer token authentication with URLSession --- .../SwaggerClientTests/SwaggerClient/AppDelegate.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift index b1896774c738..b89c28a3ca78 100644 --- a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift @@ -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 } From 5867942cf8e191d5fcd87060bd4ab3a9747d8739 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 15:21:44 +0000 Subject: [PATCH 4/6] [swift] create a sample of bearer token authentication with URLSession --- .../SwaggerClient/BearerDecodableRequestBuilder.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift index e6b8924dacf6..25cc1abcb2ad 100644 --- a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -124,12 +124,7 @@ class BearerTokenHandler { } static func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error?, completionHandler: @escaping (Bool) -> Void) { - guard let response = response as? HTTPURLResponse else { - completionHandler(false) - return - } - - if response.statusCode == 401 { + if let response = response as? HTTPURLResponse, response.statusCode == 401 { startRefreshingToken { completionHandler(true) } From ac4225ab9c0e0151ec1e37ebba16b56173c11bc3 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 16:23:53 +0000 Subject: [PATCH 5/6] [swift] create a sample of bearer token authentication with Alamofire --- .../SwaggerClientTests/Podfile.lock | 2 +- .../SwaggerClient.xcodeproj/project.pbxproj | 107 +++++++++--------- .../SwaggerClient/AppDelegate.swift | 5 + .../BearerDecodableRequestBuilder.swift | 79 +++++++++++++ .../BearerDecodableRequestBuilder.swift | 1 - 5 files changed, 141 insertions(+), 53 deletions(-) create mode 100644 samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/Podfile.lock b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/Podfile.lock index 5ded1f788906..30f84a6b9c3a 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/Podfile.lock +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/Podfile.lock @@ -20,4 +20,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 509bec696cc1d8641751b52e4fe4bef04ac4542c -COCOAPODS: 1.9.0 +COCOAPODS: 1.10.0 diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj index c9ad03859708..901182fb107a 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient.xcodeproj/project.pbxproj @@ -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 = ""; }; 1A501F47219C3DC600F372F6 /* DateFormatTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormatTests.swift; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; 6D4EFB961C692C6300B96B06 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -47,14 +48,15 @@ 6D4EFBB41C693BE200B96B06 /* PetAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetAPITests.swift; sourceTree = ""; }; 6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreAPITests.swift; sourceTree = ""; }; 6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAPITests.swift; sourceTree = ""; }; - 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 = ""; }; + 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 = ""; }; + A5465872259E306E00C3929B /* BearerDecodableRequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BearerDecodableRequestBuilder.swift; sourceTree = ""; }; A5EA12522419387100E30FC3 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = ""; }; A5EA12532419387100E30FC3 /* UIImage+Extras.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extras.swift"; sourceTree = ""; }; - 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 = ""; }; 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 = ""; }; - 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 = ""; }; + 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 = ""; }; /* 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 = ""; - }; 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 = ""; @@ -105,7 +96,7 @@ 6D4EFBA81C692C6300B96B06 /* SwaggerClientTests */, 6D4EFB921C692C6300B96B06 /* Products */, 3FABC56EC0BA84CBF4F99564 /* Frameworks */, - 203D4495376E4EB72474B091 /* Pods */, + AC485EA5DC51CA28F3F7FECF /* Pods */, ); sourceTree = ""; }; @@ -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 = ""; }; + 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 = ""; + }; /* 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,29 +251,27 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 5BC9214E8D9BA5A427A3775B /* [CP] Check Pods Manifest.lock */ = { + 3E0F8DF721D95AAFC75864D4 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "${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 = ( - "$(DERIVED_FILE_DIR)/Pods-SwaggerClient-checkManifestLockResult.txt", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PetstoreClient.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - 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"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - EEDC5E683F9569976B7C1192 /* [CP] Check Pods Manifest.lock */ = { + 53EC90CFFB0E0FABA75F972D /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -284,31 +286,33 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SwaggerClientTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-SwaggerClient-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; 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 */ = { + 89F684025365A60C007C7DA9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", - "${BUILT_PRODUCTS_DIR}/PetstoreClient/PetstoreClient.framework", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PetstoreClient.framework", + "$(DERIVED_FILE_DIR)/Pods-SwaggerClientTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient-frameworks.sh\"\n"; + 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; }; /* End PBXShellScriptBuildPhase 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; diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift index b1896774c738..b89c28a3ca78 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift @@ -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 } diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift new file mode 100644 index 000000000000..f19d544ae1af --- /dev/null +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -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() -> RequestBuilder.Type { + BearerRequestBuilder.self + } + + func getBuilder() -> RequestBuilder.Type { + BearerDecodableRequestBuilder.self + } +} + +class BearerRequestBuilder: AlamofireRequestBuilder { + override func createSessionManager() -> SessionManager { + let sessionManager = super.createSessionManager() + + let jwtHandler = BearerTokenHandler() + sessionManager.adapter = jwtHandler + sessionManager.retrier = jwtHandler + + return sessionManager + } +} + +class BearerDecodableRequestBuilder: AlamofireDecodableRequestBuilder { + override func createSessionManager() -> SessionManager { + let sessionManager = super.createSessionManager() + + let jwtHandler = BearerTokenHandler() + sessionManager.adapter = jwtHandler + sessionManager.retrier = jwtHandler + + 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) + } +} diff --git a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift index 25cc1abcb2ad..a28a4c90c0e9 100644 --- a/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift +++ b/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -113,7 +113,6 @@ class BearerTokenHandler { private static var bearerToken: String? = nil static func refreshTokenIfDoesntExist(completionHandler: @escaping () -> Void) { - if bearerToken != nil { completionHandler() } else { From 1641b1f236021c138abf49984772e603321f4725 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@gmail.com> Date: Thu, 31 Dec 2020 16:33:45 +0000 Subject: [PATCH 6/6] [swift] create a sample of bearer token authentication with Alamofire --- .../BearerDecodableRequestBuilder.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift index f19d544ae1af..f71480b0bd51 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift @@ -24,9 +24,9 @@ class BearerRequestBuilder: AlamofireRequestBuilder { override func createSessionManager() -> SessionManager { let sessionManager = super.createSessionManager() - let jwtHandler = BearerTokenHandler() - sessionManager.adapter = jwtHandler - sessionManager.retrier = jwtHandler + let bearerTokenHandler = BearerTokenHandler() + sessionManager.adapter = bearerTokenHandler + sessionManager.retrier = bearerTokenHandler return sessionManager } @@ -36,9 +36,9 @@ class BearerDecodableRequestBuilder: AlamofireDecodableRequestBuil override func createSessionManager() -> SessionManager { let sessionManager = super.createSessionManager() - let jwtHandler = BearerTokenHandler() - sessionManager.adapter = jwtHandler - sessionManager.retrier = jwtHandler + let bearerTokenHandler = BearerTokenHandler() + sessionManager.adapter = bearerTokenHandler + sessionManager.retrier = bearerTokenHandler return sessionManager }