mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-12 12:40:53 +00:00
[swift6] promote to beta and improve documentation (#19856)
* [swift6] promote to beta * [swift6] format code * [swift] authentication docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs * [swift] update docs
This commit is contained in:
parent
b5b760a8a2
commit
2354d402a8
@ -92,16 +92,402 @@ git clone https://github.com/openapitools/openapi-generator.git
|
||||
cd openapi-generator/samples/client/petstore/swift/default/OpenAPIClientTests
|
||||
mvn integration-test
|
||||
```
|
||||
Besides `default` (folder), there's another folder `promisekit` for Swift API client with [PromiseKit support](https://github.com/mxcl/PromiseKit)
|
||||
```
|
||||
git clone https://github.com/openapitools/openapi-generator.git
|
||||
cd openapi-generator/samples/client/petstore/swift/promisekit/OpenAPIClientTests
|
||||
mvn integration-test
|
||||
```
|
||||
|
||||
### Is Swift (2.x) generator still actively maintained?
|
||||
### Which Swift generator is still actively maintained?
|
||||
|
||||
No, please use `swift3` or `swift4` generator instead as we want to focus on Swift 3.x, 4.x.
|
||||
Please use `swift5` generator because Swift 4.x is deprecated.
|
||||
There is a new `swift6` generator, that is currently in beta, try it and give us your feedback.
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
<details>
|
||||
<summary>First you subclass RequestBuilderFactory</summary>
|
||||
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder </summary>
|
||||
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
</details>
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 5 API client?
|
||||
|
||||
<details>
|
||||
<summary>First you subclass RequestBuilderFactory</summary>
|
||||
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Then you subclass AlamofireRequestBuilder and AlamofireDecodableRequestBuilder</summary>
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
</details>
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
<details>
|
||||
<summary>First you implement the `OpenAPIInterceptor` protocol.</summary>
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
</details>
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
|
||||
|
||||
<details>
|
||||
<summary>First implement the `Alamofire` `RequestInterceptor` protocol.</summary>
|
||||
class BearerTokenHandler: RequestInterceptor, @unchecked Sendable {
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
var urlRequest = urlRequest
|
||||
urlRequest.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
completion(.success(urlRequest))
|
||||
return
|
||||
}
|
||||
|
||||
completion(.success(urlRequest))
|
||||
}
|
||||
|
||||
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
|
||||
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { isTokenRefreshed in
|
||||
completion(.retry)
|
||||
}
|
||||
} else {
|
||||
completion(.doNotRetryWithError(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (Bool) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
OpenAPIClient.shared.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
|
||||
|
||||
completionHandler(true)
|
||||
}
|
||||
}
|
||||
</details>
|
||||
|
||||
Then you assign the `BearerTokenHandler` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerTokenHandler()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift)
|
||||
|
||||
### How do I migrate from the Swift 5 generator to the swift 6 generator?
|
||||
|
||||
- The infrastructure files have been moved to a new directory called `Infrastructure`. Please delete the old ones.
|
||||
- The `AnyCodable` dependency has been removed and replaced with a new enum called `JSONValue`, allowing you to use this generator without external dependencies.
|
||||
- The `Combine` response is now deferred by default, meaning the request will only start when you begin listening to it. To restore the previous behavior, set the `combineDeferred` flag to `false`.
|
||||
- A new configuration, `apiStaticMethod`, allows you to use instance methods instead of class methods for API calls. For more information, check the sample project [apiNonStaticMethod](https://github.com/OpenAPITools/openapi-generator/tree/master/samples/client/petstore/swift6/apiNonStaticMethod).
|
||||
- The new default response is based on async/await. To revert to the previous behavior, set the `responseAs` flag to `ObjcBlock`.
|
||||
- The default project structure now follows the SPM (Swift Package Manager) structure. To revert to the old structure, set the `useSPMFileStructure` flag to `false`.
|
||||
- The former `{{projectName}}API` is now called `OpenAPIClient`.
|
||||
- You can now set a request interceptor and retrier by configuring `OpenAPIClient.shared.interceptor`, making authenticated requests easier to manage.
|
||||
|
||||
## TypeScript
|
||||
|
||||
|
@ -66,7 +66,7 @@ The following generators are available:
|
||||
* [scalaz](generators/scalaz.md)
|
||||
* [swift-combine](generators/swift-combine.md)
|
||||
* [swift5](generators/swift5.md)
|
||||
* [swift6 (experimental)](generators/swift6.md)
|
||||
* [swift6 (beta)](generators/swift6.md)
|
||||
* [typescript (experimental)](generators/typescript.md)
|
||||
* [typescript-angular](generators/typescript-angular.md)
|
||||
* [typescript-aurelia](generators/typescript-aurelia.md)
|
||||
|
@ -7,7 +7,7 @@ title: Documentation for the swift6 Generator
|
||||
| Property | Value | Notes |
|
||||
| -------- | ----- | ----- |
|
||||
| generator name | swift6 | pass this to the generate command after -g |
|
||||
| generator stability | EXPERIMENTAL | |
|
||||
| generator stability | BETA | |
|
||||
| generator type | CLIENT | |
|
||||
| generator language | Swift | |
|
||||
| generator default templating engine | mustache | |
|
||||
|
@ -1305,6 +1305,11 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
System.out.println("# #");
|
||||
System.out.println("# swift5 generator is contributed by Bruno Coelho (https://github.com/4brunu). #");
|
||||
System.out.println("# Please support his work directly via https://paypal.com/paypalme/4brunu \uD83D\uDE4F #");
|
||||
System.out.println("# #");
|
||||
System.out.println("# There is a new `swift6` generator, that is currently in beta. #");
|
||||
System.out.println("# Try it and give us your feedback. #");
|
||||
System.out.println("# https://openapi-generator.tech/docs/generators/swift6 #");
|
||||
System.out.println("# https://openapi-generator.tech/docs/faq-generators/#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator");
|
||||
System.out.println("################################################################################");
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
this.useOneOfInterfaces = true;
|
||||
|
||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||
.stability(Stability.EXPERIMENTAL)
|
||||
.stability(Stability.BETA)
|
||||
.build();
|
||||
|
||||
outputFolder = "generated-code" + File.separator + "swift";
|
||||
|
@ -78,6 +78,252 @@ Class | Method | HTTP request | Description
|
||||
|
||||
{{/authMethods}}
|
||||
|
||||
{{#useURLSession}}
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
{{/useURLSession}}
|
||||
{{#useAlamofire}}
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass AlamofireRequestBuilder and AlamofireDecodableRequestBuilder
|
||||
```
|
||||
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)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
{{/useAlamofire}}
|
||||
|
||||
## Author
|
||||
|
||||
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
|
||||
|
@ -78,6 +78,142 @@ Class | Method | HTTP request | Description
|
||||
|
||||
{{/authMethods}}
|
||||
|
||||
{{#useURLSession}}
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
{{/useURLSession}}
|
||||
{{#useAlamofire}}
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
|
||||
|
||||
First implement the `Alamofire` `RequestInterceptor` protocol.
|
||||
```
|
||||
class BearerTokenHandler: RequestInterceptor, @unchecked Sendable {
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
var urlRequest = urlRequest
|
||||
urlRequest.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
completion(.success(urlRequest))
|
||||
return
|
||||
}
|
||||
|
||||
completion(.success(urlRequest))
|
||||
}
|
||||
|
||||
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
|
||||
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { isTokenRefreshed in
|
||||
completion(.retry)
|
||||
}
|
||||
} else {
|
||||
completion(.doNotRetryWithError(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (Bool) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
OpenAPIClient.shared.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
|
||||
|
||||
completionHandler(true)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then you assign the `BearerTokenHandler` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerTokenHandler()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift)
|
||||
{{/useAlamofire}}
|
||||
|
||||
## Author
|
||||
|
||||
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
|
||||
|
@ -270,8 +270,10 @@ extension {{projectName}}API {
|
||||
{{/externalDocs}}
|
||||
{{#allParams}}
|
||||
- parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
|
||||
{{/allParams}}{{#apiStaticMethod}}
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.{{/apiStaticMethod}}
|
||||
{{/allParams}}
|
||||
{{#apiStaticMethod}}
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
{{/apiStaticMethod}}
|
||||
- returns: RequestBuilder<{{{returnType}}}{{#returnType}}{{#isResponseOptional}}?{{/isResponseOptional}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{description}}
|
||||
*/
|
||||
{{#isDeprecated}}
|
||||
|
@ -140,6 +140,92 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass AlamofireRequestBuilder and AlamofireDecodableRequestBuilder
|
||||
```
|
||||
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)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -151,6 +151,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -42,6 +42,163 @@ Class | Method | HTTP request | Description
|
||||
Endpoints do not require authorization.
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,163 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -40,6 +40,163 @@ Class | Method | HTTP request | Description
|
||||
Endpoints do not require authorization.
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
|
||||
|
||||
First you subclass RequestBuilderFactory
|
||||
```
|
||||
class BearerRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
BearerRequestBuilder<T>.self
|
||||
}
|
||||
|
||||
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
|
||||
BearerDecodableRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder
|
||||
```
|
||||
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
|
||||
@discardableResult
|
||||
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
|
||||
// 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestTask
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerRequestBuilderFactory` to the property `requestBuilderFactory`.
|
||||
|
||||
`PetstoreClientAPI.requestBuilderFactory = BearerRequestBuilderFactory()`
|
||||
|
||||
The name `PetstoreClientAPI.requestBuilderFactory` will change depending on your project name.
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerDecodableRequestBuilder.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -147,6 +147,7 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,56 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
|
||||
|
||||
First implement the `Alamofire` `RequestInterceptor` protocol.
|
||||
```
|
||||
class BearerTokenHandler: RequestInterceptor, @unchecked Sendable {
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
var urlRequest = urlRequest
|
||||
urlRequest.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
completion(.success(urlRequest))
|
||||
return
|
||||
}
|
||||
|
||||
completion(.success(urlRequest))
|
||||
}
|
||||
|
||||
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
|
||||
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { isTokenRefreshed in
|
||||
completion(.retry)
|
||||
}
|
||||
} else {
|
||||
completion(.doNotRetryWithError(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (Bool) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
OpenAPIClient.shared.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
|
||||
|
||||
completionHandler(true)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then you assign the `BearerTokenHandler` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerTokenHandler()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -33,7 +33,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -75,7 +74,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -119,7 +117,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -163,7 +160,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -207,7 +203,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -252,7 +247,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -301,7 +295,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -376,7 +369,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -521,7 +513,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -591,7 +582,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -643,7 +633,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -690,7 +679,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -36,7 +36,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -88,7 +87,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -149,7 +147,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -202,7 +199,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -255,7 +251,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -306,7 +301,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -358,7 +352,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -419,7 +412,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -480,7 +472,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -83,7 +82,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -129,7 +127,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -177,7 +174,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -78,7 +77,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -123,7 +121,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -169,7 +166,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -217,7 +213,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -268,7 +263,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -315,7 +309,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -363,7 +356,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -138,6 +138,56 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
|
||||
|
||||
First implement the `Alamofire` `RequestInterceptor` protocol.
|
||||
```
|
||||
class BearerTokenHandler: RequestInterceptor, @unchecked Sendable {
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
var urlRequest = urlRequest
|
||||
urlRequest.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
completion(.success(urlRequest))
|
||||
return
|
||||
}
|
||||
|
||||
completion(.success(urlRequest))
|
||||
}
|
||||
|
||||
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
|
||||
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { isTokenRefreshed in
|
||||
completion(.retry)
|
||||
}
|
||||
} else {
|
||||
completion(.doNotRetryWithError(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (Bool) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
OpenAPIClient.shared.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
|
||||
|
||||
completionHandler(true)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Then you assign the `BearerTokenHandler` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerTokenHandler()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/alamofireLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -144,7 +144,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
open func call123testSpecialTagsWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
|
||||
|
@ -137,7 +137,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
open func fakeOuterBooleanSerializeWithRequestBuilder(body: Bool? = nil) -> RequestBuilder<Bool> {
|
||||
@ -277,7 +276,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
open func fakeOuterCompositeSerializeWithRequestBuilder(body: OuterComposite? = nil) -> RequestBuilder<OuterComposite> {
|
||||
@ -417,7 +415,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
open func fakeOuterNumberSerializeWithRequestBuilder(body: Double? = nil) -> RequestBuilder<Double> {
|
||||
@ -557,7 +554,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
open func fakeOuterStringSerializeWithRequestBuilder(body: String? = nil) -> RequestBuilder<String> {
|
||||
@ -697,7 +693,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testBodyWithFileSchemaWithRequestBuilder(body: FileSchemaTestClass) -> RequestBuilder<Void> {
|
||||
@ -843,7 +838,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testBodyWithQueryParamsWithRequestBuilder(query: String, body: User) -> RequestBuilder<Void> {
|
||||
@ -993,7 +987,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
open func testClientModelWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
|
||||
@ -1234,7 +1227,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testEndpointParametersWithRequestBuilder(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int? = nil, int32: Int? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil) -> RequestBuilder<Void> {
|
||||
@ -1515,7 +1507,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testEnumParametersWithRequestBuilder(enumHeaderStringArray: [EnumHeaderStringArray_testEnumParameters]? = nil, enumHeaderString: EnumHeaderString_testEnumParameters? = nil, enumQueryStringArray: [EnumQueryStringArray_testEnumParameters]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: EnumQueryInteger_testEnumParameters? = nil, enumQueryDouble: EnumQueryDouble_testEnumParameters? = nil, enumFormStringArray: [EnumFormStringArray_testEnumParameters]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil) -> RequestBuilder<Void> {
|
||||
@ -1711,7 +1702,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testGroupParametersWithRequestBuilder(requiredStringGroup: Int, requiredBooleanGroup: Bool, requiredInt64Group: Int64, stringGroup: Int? = nil, booleanGroup: Bool? = nil, int64Group: Int64? = nil) -> RequestBuilder<Void> {
|
||||
@ -1864,7 +1854,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testInlineAdditionalPropertiesWithRequestBuilder(param: [String: String]) -> RequestBuilder<Void> {
|
||||
@ -2017,7 +2006,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func testJsonFormDataWithRequestBuilder(param: String, param2: String) -> RequestBuilder<Void> {
|
||||
|
@ -147,7 +147,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
open func testClassnameWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
|
||||
|
@ -149,7 +149,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func addPetWithRequestBuilder(body: Pet) -> RequestBuilder<Void> {
|
||||
@ -305,7 +304,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder<Void> {
|
||||
@ -467,7 +465,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
open func findPetsByStatusWithRequestBuilder(status: [Status_findPetsByStatus]) -> RequestBuilder<[Pet]> {
|
||||
@ -626,7 +623,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@available(*, deprecated, message: "This operation is deprecated.")
|
||||
@ -780,7 +776,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
open func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder<Pet> {
|
||||
@ -932,7 +927,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func updatePetWithRequestBuilder(body: Pet) -> RequestBuilder<Void> {
|
||||
@ -1095,7 +1089,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder<Void> {
|
||||
@ -1267,7 +1260,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
open func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil) -> RequestBuilder<ApiResponse> {
|
||||
@ -1439,7 +1431,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
open func uploadFileWithRequiredFileWithRequestBuilder(petId: Int64, requiredFile: Data, additionalMetadata: String? = nil) -> RequestBuilder<ApiResponse> {
|
||||
|
@ -144,7 +144,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder<Void> {
|
||||
@ -290,7 +289,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
open func getInventoryWithRequestBuilder() -> RequestBuilder<[String: Int]> {
|
||||
@ -437,7 +435,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
open func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder<Order> {
|
||||
@ -586,7 +583,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
open func placeOrderWithRequestBuilder(body: Order) -> RequestBuilder<Order> {
|
||||
|
@ -144,7 +144,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func createUserWithRequestBuilder(body: User) -> RequestBuilder<Void> {
|
||||
@ -290,7 +289,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func createUsersWithArrayInputWithRequestBuilder(body: [User]) -> RequestBuilder<Void> {
|
||||
@ -436,7 +434,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func createUsersWithListInputWithRequestBuilder(body: [User]) -> RequestBuilder<Void> {
|
||||
@ -583,7 +580,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func deleteUserWithRequestBuilder(username: String) -> RequestBuilder<Void> {
|
||||
@ -732,7 +728,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
open func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder<User> {
|
||||
@ -889,7 +884,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
open func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder<String> {
|
||||
@ -1032,7 +1026,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func logoutUserWithRequestBuilder() -> RequestBuilder<Void> {
|
||||
@ -1186,7 +1179,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open func updateUserWithRequestBuilder(username: String, body: User) -> RequestBuilder<Void> {
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -26,7 +26,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -24,7 +24,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -61,7 +60,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -98,7 +96,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -135,7 +132,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -172,7 +168,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -210,7 +205,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -252,7 +246,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -320,7 +313,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -458,7 +450,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -521,7 +512,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -566,7 +556,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -606,7 +595,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -29,7 +29,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -74,7 +73,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -128,7 +126,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -174,7 +171,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -220,7 +216,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -264,7 +259,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -309,7 +303,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -363,7 +356,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -417,7 +409,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -69,7 +68,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -108,7 +106,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -149,7 +146,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -64,7 +63,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -102,7 +100,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -141,7 +138,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -182,7 +178,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -226,7 +221,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -266,7 +260,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -307,7 +300,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -49,7 +49,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -47,7 +47,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -104,7 +103,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -161,7 +159,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -218,7 +215,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -275,7 +271,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -333,7 +328,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -395,7 +389,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -483,7 +476,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -641,7 +633,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -724,7 +715,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -789,7 +779,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -849,7 +838,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -52,7 +52,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -54,7 +54,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -117,7 +116,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -191,7 +189,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -257,7 +254,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -323,7 +319,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -387,7 +382,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -452,7 +446,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -526,7 +519,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -600,7 +592,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -49,7 +49,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -112,7 +111,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -171,7 +169,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -232,7 +229,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -49,7 +49,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -107,7 +106,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -165,7 +163,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -224,7 +221,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -285,7 +281,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -349,7 +344,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -409,7 +403,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -470,7 +463,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -47,7 +47,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -45,7 +45,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -100,7 +99,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -155,7 +153,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -210,7 +207,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -265,7 +261,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -321,7 +316,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -381,7 +375,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -467,7 +460,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -623,7 +615,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -704,7 +695,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -767,7 +757,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -825,7 +814,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -50,7 +50,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -52,7 +52,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -113,7 +112,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -185,7 +183,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -249,7 +246,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -313,7 +309,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -375,7 +370,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -438,7 +432,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -510,7 +503,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -582,7 +574,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -47,7 +47,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -108,7 +107,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -165,7 +163,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -224,7 +221,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -47,7 +47,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -103,7 +102,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -159,7 +157,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -216,7 +213,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -275,7 +271,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -337,7 +332,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -395,7 +389,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -454,7 +447,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -151,6 +151,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -28,7 +28,6 @@ open class AnotherFakeAPI {
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter uuidTest: (header) to test uuid example value
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ open class FakeAPI {
|
||||
- POST /fake/create_xml_item
|
||||
- this route creates an XmlItem
|
||||
- parameter xmlItem: (body) XmlItem Body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -63,7 +62,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -100,7 +98,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -137,7 +134,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -174,7 +170,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -211,7 +206,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -249,7 +243,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -291,7 +284,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -359,7 +351,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -497,7 +488,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -560,7 +550,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -605,7 +594,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -645,7 +633,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -696,7 +683,6 @@ open class FakeAPI {
|
||||
- parameter http: (query)
|
||||
- parameter url: (query)
|
||||
- parameter context: (query)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -29,7 +29,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -28,7 +28,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -71,7 +70,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -125,7 +123,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -171,7 +168,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Set<Pet>>
|
||||
*/
|
||||
@ -217,7 +213,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -261,7 +256,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -306,7 +300,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -360,7 +353,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -414,7 +406,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -69,7 +68,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -108,7 +106,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -149,7 +146,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -64,7 +63,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -102,7 +100,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -141,7 +138,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -182,7 +178,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -226,7 +221,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -266,7 +260,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -307,7 +300,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -33,7 +33,6 @@ import Foundation
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@ import Foundation
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -75,7 +74,6 @@ import Foundation
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -119,7 +117,6 @@ import Foundation
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -163,7 +160,6 @@ import Foundation
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -207,7 +203,6 @@ import Foundation
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -252,7 +247,6 @@ import Foundation
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -301,7 +295,6 @@ import Foundation
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -376,7 +369,6 @@ import Foundation
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -521,7 +513,6 @@ import Foundation
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -591,7 +582,6 @@ import Foundation
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -643,7 +633,6 @@ import Foundation
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -690,7 +679,6 @@ import Foundation
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -36,7 +36,6 @@ import Foundation
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@ import Foundation
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -88,7 +87,6 @@ import Foundation
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -149,7 +147,6 @@ import Foundation
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -202,7 +199,6 @@ import Foundation
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -255,7 +251,6 @@ import Foundation
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -306,7 +301,6 @@ import Foundation
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -358,7 +352,6 @@ import Foundation
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -419,7 +412,6 @@ import Foundation
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -480,7 +472,6 @@ import Foundation
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ import Foundation
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -83,7 +82,6 @@ import Foundation
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -129,7 +127,6 @@ import Foundation
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -177,7 +174,6 @@ import Foundation
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ import Foundation
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -78,7 +77,6 @@ import Foundation
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -123,7 +121,6 @@ import Foundation
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -169,7 +166,6 @@ import Foundation
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -217,7 +213,6 @@ import Foundation
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -268,7 +263,6 @@ import Foundation
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -315,7 +309,6 @@ import Foundation
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -363,7 +356,6 @@ import Foundation
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -28,7 +28,6 @@ open class DefaultAPI {
|
||||
|
||||
/**
|
||||
- GET /
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Fruit>
|
||||
*/
|
||||
|
@ -42,6 +42,89 @@ Class | Method | HTTP request | Description
|
||||
Endpoints do not require authorization.
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -35,7 +35,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -78,7 +77,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -123,7 +121,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -168,7 +165,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -213,7 +209,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -259,7 +254,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -309,7 +303,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -385,7 +378,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -531,7 +523,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -602,7 +593,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -655,7 +645,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -703,7 +692,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -40,7 +40,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -91,7 +90,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -153,7 +151,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -207,7 +204,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -261,7 +257,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -313,7 +308,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -366,7 +360,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -428,7 +421,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -490,7 +482,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -35,7 +35,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -86,7 +85,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -133,7 +131,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -182,7 +179,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -35,7 +35,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -81,7 +80,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -127,7 +125,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -174,7 +171,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -223,7 +219,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -275,7 +270,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -323,7 +317,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -372,7 +365,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -33,7 +33,6 @@ internal class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -31,7 +31,6 @@ internal class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -75,7 +74,6 @@ internal class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -119,7 +117,6 @@ internal class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -163,7 +160,6 @@ internal class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -207,7 +203,6 @@ internal class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -252,7 +247,6 @@ internal class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -301,7 +295,6 @@ internal class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -376,7 +369,6 @@ internal class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -521,7 +513,6 @@ internal class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -591,7 +582,6 @@ internal class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -643,7 +633,6 @@ internal class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -690,7 +679,6 @@ internal class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -36,7 +36,6 @@ internal class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@ internal class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -88,7 +87,6 @@ internal class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter apiKey: (header) (optional)
|
||||
- parameter petId: (path) Pet id to delete
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -149,7 +147,6 @@ internal class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -202,7 +199,6 @@ internal class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -255,7 +251,6 @@ internal class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -306,7 +301,6 @@ internal class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -358,7 +352,6 @@ internal class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -419,7 +412,6 @@ internal class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -480,7 +472,6 @@ internal class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter requiredFile: (form) file to upload
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ internal class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -83,7 +82,6 @@ internal class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -129,7 +127,6 @@ internal class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -177,7 +174,6 @@ internal class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -33,7 +33,6 @@ internal class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -78,7 +77,6 @@ internal class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -123,7 +121,6 @@ internal class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -169,7 +166,6 @@ internal class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -217,7 +213,6 @@ internal class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -268,7 +263,6 @@ internal class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -315,7 +309,6 @@ internal class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -363,7 +356,6 @@ internal class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -40,7 +40,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -88,7 +87,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -138,7 +136,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -188,7 +185,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -238,7 +234,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -289,7 +284,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -344,7 +338,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -425,7 +418,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -576,7 +568,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -652,7 +643,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -710,7 +700,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -763,7 +752,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -43,7 +43,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -45,7 +45,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -101,7 +100,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -168,7 +166,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -227,7 +224,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -286,7 +282,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -343,7 +338,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -401,7 +395,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -468,7 +461,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -535,7 +527,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -40,7 +40,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -96,7 +95,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -148,7 +146,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -202,7 +199,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -40,7 +40,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -91,7 +90,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -142,7 +140,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -194,7 +191,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -248,7 +244,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -305,7 +300,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -358,7 +352,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -412,7 +405,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -140,6 +140,89 @@ Authentication schemes defined for the API:
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
|
||||
### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
|
||||
|
||||
First you implement the `OpenAPIInterceptor` protocol.
|
||||
```
|
||||
public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(token)"
|
||||
|
||||
completion(.success(newUrlRequest))
|
||||
}
|
||||
}
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
) { (wasTokenRefreshed, newToken) in
|
||||
|
||||
if wasTokenRefreshed, let newToken = newToken {
|
||||
|
||||
// Change the global headers
|
||||
openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)"
|
||||
|
||||
completion(.retry)
|
||||
} 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(.dontRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
func refreshTokenIfDoesntExist(completionHandler: @escaping (String) -> Void) {
|
||||
if let bearerToken = bearerToken {
|
||||
completionHandler(bearerToken)
|
||||
} else {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) {
|
||||
if let response = response as? HTTPURLResponse, response.statusCode == 401 {
|
||||
startRefreshingToken { token in
|
||||
completionHandler(true, token)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func startRefreshingToken(completionHandler: @escaping (String) -> Void) {
|
||||
// Get a bearer token
|
||||
let dummyBearerToken = "..."
|
||||
|
||||
bearerToken = dummyBearerToken
|
||||
|
||||
completionHandler(dummyBearerToken)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you assign the `BearerOpenAPIInterceptor` to the property `OpenAPIClient.shared.interceptor`.
|
||||
|
||||
`OpenAPIClient.shared.interceptor = BearerOpenAPIInterceptor()`
|
||||
|
||||
Here is a working sample that put's together all of this.
|
||||
[AppDelegate.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift)
|
||||
[BearerTokenHandler.swift](https://github.com/OpenAPITools/openapi-generator/blob/master/samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift)
|
||||
|
||||
## Author
|
||||
|
||||
|
||||
|
@ -36,7 +36,6 @@ open class AnotherFakeAPI {
|
||||
- PATCH /another-fake/dummy
|
||||
- To test special tags and operation ID starting with number
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -34,7 +34,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/boolean
|
||||
- Test serialization of outer boolean types
|
||||
- parameter body: (body) Input boolean as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Bool>
|
||||
*/
|
||||
@ -78,7 +77,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/composite
|
||||
- Test serialization of object with outer number type
|
||||
- parameter body: (body) Input composite as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<OuterComposite>
|
||||
*/
|
||||
@ -122,7 +120,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/number
|
||||
- Test serialization of outer number types
|
||||
- parameter body: (body) Input number as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Double>
|
||||
*/
|
||||
@ -166,7 +163,6 @@ open class FakeAPI {
|
||||
- POST /fake/outer/string
|
||||
- Test serialization of outer string types
|
||||
- parameter body: (body) Input string as post body (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -210,7 +206,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-file-schema
|
||||
- For this test, the body for this request much reference a schema named `File`.
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -255,7 +250,6 @@ open class FakeAPI {
|
||||
- PUT /fake/body-with-query-params
|
||||
- parameter query: (query)
|
||||
- parameter body: (body)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -304,7 +298,6 @@ open class FakeAPI {
|
||||
- PATCH /fake
|
||||
- To test \"client\" model
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
@ -379,7 +372,6 @@ open class FakeAPI {
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -524,7 +516,6 @@ open class FakeAPI {
|
||||
- parameter enumQueryDouble: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional, default to .dollar)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -594,7 +585,6 @@ open class FakeAPI {
|
||||
- parameter stringGroup: (query) String in group parameters (optional)
|
||||
- parameter booleanGroup: (header) Boolean in group parameters (optional)
|
||||
- parameter int64Group: (query) Integer in group parameters (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -646,7 +636,6 @@ open class FakeAPI {
|
||||
test inline additionalProperties
|
||||
- POST /fake/inline-additionalProperties
|
||||
- parameter param: (body) request body
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -693,7 +682,6 @@ open class FakeAPI {
|
||||
- GET /fake/jsonFormData
|
||||
- parameter param: (form) field1
|
||||
- parameter param2: (form) field2
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -39,7 +39,6 @@ open class FakeClassnameTags123API {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) client model
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
|
@ -41,7 +41,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key_query (QUERY)
|
||||
- name: api_key_query
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -91,7 +90,6 @@ open class PetAPI {
|
||||
- name: petstore_auth
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter apiKey: (header) (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -152,7 +150,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -205,7 +202,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
@ -258,7 +254,6 @@ open class PetAPI {
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
@ -309,7 +304,6 @@ open class PetAPI {
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -361,7 +355,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -422,7 +415,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
@ -483,7 +475,6 @@ open class PetAPI {
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter requiredFile: (form) file to upload
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
|
@ -36,7 +36,6 @@ open class StoreAPI {
|
||||
- DELETE /store/order/{order_id}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -86,7 +85,6 @@ open class StoreAPI {
|
||||
- API Key:
|
||||
- type: apiKey api_key (HEADER)
|
||||
- name: api_key
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<[String: Int]>
|
||||
*/
|
||||
@ -132,7 +130,6 @@ open class StoreAPI {
|
||||
- GET /store/order/{order_id}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
@ -180,7 +177,6 @@ open class StoreAPI {
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
|
@ -36,7 +36,6 @@ open class UserAPI {
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -81,7 +80,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -126,7 +124,6 @@ open class UserAPI {
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -172,7 +169,6 @@ open class UserAPI {
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -220,7 +216,6 @@ open class UserAPI {
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
@ -271,7 +266,6 @@ open class UserAPI {
|
||||
- responseHeaders: [X-Rate-Limit(Int), X-Expires-After(Date)]
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
@ -318,7 +312,6 @@ open class UserAPI {
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
@ -366,7 +359,6 @@ open class UserAPI {
|
||||
- This can only be done by the logged in user.
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
|
@ -13,7 +13,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
public init() {}
|
||||
|
||||
public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result<URLRequest, any Error>) -> Void) {
|
||||
BearerTokenHandler.shared.refreshTokenIfDoesntExist { token in
|
||||
refreshTokenIfDoesntExist { token in
|
||||
|
||||
// Change the current url request
|
||||
var newUrlRequest = urlRequest
|
||||
@ -28,7 +28,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
|
||||
public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) {
|
||||
// We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request
|
||||
BearerTokenHandler.shared.refreshTokenIfUnauthorizedRequestResponse(
|
||||
refreshTokenIfUnauthorizedRequestResponse(
|
||||
data: data,
|
||||
response: response,
|
||||
error: error
|
||||
@ -46,12 +46,6 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BearerTokenHandler: @unchecked Sendable {
|
||||
private init() {}
|
||||
static let shared = BearerTokenHandler()
|
||||
|
||||
|
||||
private var bearerToken: String? = nil
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user