[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:
Bruno Coelho 2024-10-14 12:55:25 +01:00 committed by GitHub
parent b5b760a8a2
commit 2354d402a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
103 changed files with 3862 additions and 811 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 | |

View File

@ -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("################################################################################");
}

View File

@ -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";

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -147,6 +147,7 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication
## Author

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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> {

View File

@ -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> {

View File

@ -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> {

View File

@ -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> {

View File

@ -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> {

View File

@ -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> {

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -28,7 +28,6 @@ open class DefaultAPI {
/**
- GET /
- parameter openAPIClient: The OpenAPIClient that contains the configuration for the http request.
- returns: RequestBuilder<Fruit>
*/

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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

View File

@ -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

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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>
*/

View File

@ -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