Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • O openapi-generator
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,476
    • Issues 3,476
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 402
    • Merge requests 402
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenAPI Tools
  • openapi-generator
  • Wiki
  • FAQ

FAQ · Changes

Page history
Updated FAQ (markdown) authored Dec 02, 2021 by Bruno Coelho's avatar Bruno Coelho
Hide whitespace changes
Inline Side-by-side
FAQ.md
View page @ ea56f1b3
...@@ -331,136 +331,134 @@ Please use `swift5` generator because Swift 4.x is deprecated. ...@@ -331,136 +331,134 @@ Please use `swift5` generator because Swift 4.x is deprecated.
<details> <details>
<summary>Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder </summary> <summary>Then you subclass URLSessionRequestBuilder and URLSessionDecodableRequestBuilder </summary>
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> {
class BearerRequestBuilder<T>: URLSessionRequestBuilder<T> { @discardableResult
@discardableResult override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> OpenApiRequestCancellable {
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> OpenApiRequestCancellable {
// Before making the request, we can validate if we have a bearer token to be able to make a request
// Before making the request, we can validate if we have a bearer token to be able to make a request BearerTokenHandler.refreshTokenIfDoesntExist {
BearerTokenHandler.refreshTokenIfDoesntExist {
// Here we make the request
super.execute(apiResponseQueue) { result in
switch result { // Here we make the request
case .success: super.execute(apiResponseQueue) { result in
// 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 switch result {
if case let ErrorResponse.error(_, data, response, error) = error { case .success:
// If we got a successful response, we send the response to the completion block
completion(result)
// 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 case let .failure(error):
BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse(
data: data, // If we got a failure response, we will analyse the error to see what we should do with it
response: response, if case let ErrorResponse.error(_, data, response, error) = error {
error: error
) { wasTokenRefreshed in
if wasTokenRefreshed { // 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
// 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() BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse(
self.execute(apiResponseQueue, completion) data: data,
} else { response: response,
// If the token was not refreshed, it's because it was not a 401 error, so we send the response to the completion block error: error
completion(result) ) { 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)
} }
} else {
// If it's an unknown error, we send the response to the completion block
completion(result)
} }
} }
} }
return requestCancellable
} }
return requestCancellable
} }
}
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
class BearerDecodableRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> { @discardableResult
@discardableResult override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> OpenApiRequestCancellable {
override func execute(_ apiResponseQueue: DispatchQueue = PetstoreClientAPI.apiResponseQueue, _ completion: @escaping (Result<Response<T>, ErrorResponse>) -> Void) -> OpenApiRequestCancellable { // Before making the request, we can validate if we have a bearer token to be able to make a request
// Before making the request, we can validate if we have a bearer token to be able to make a request BearerTokenHandler.refreshTokenIfDoesntExist {
BearerTokenHandler.refreshTokenIfDoesntExist {
// Here we make the request
super.execute(apiResponseQueue) { result in
switch result { // Here we make the request
case .success: super.execute(apiResponseQueue) { result in
// If we got a successful response, we send the response to the completion block
completion(result)
case let .failure(error): switch result {
case .success:
// If we got a failure response, we will analyse the error to see what we should do with it // If we got a successful response, we send the response to the completion block
if case let ErrorResponse.error(_, data, response, error) = error { completion(result)
case let .failure(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 // If we got a failure response, we will analyse the error to see what we should do with it
BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse( if case let ErrorResponse.error(_, data, response, error) = error {
data: data,
response: response,
error: error
) { wasTokenRefreshed in
if wasTokenRefreshed { // 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
// 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() BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse(
self.execute(apiResponseQueue, completion) data: data,
} else { response: response,
// If the token was not refreshed, it's because it was not a 401 error, so we send the response to the completion block error: error
completion(result) ) { 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)
} }
} else {
// If it's an unknown error, we send the response to the completion block
completion(result)
} }
} }
} }
return requestCancellable
} }
return requestCancellable
} }
}
class BearerTokenHandler {
private static var bearerToken: String? = nil
static func refreshTokenIfDoesntExist(completionHandler: @escaping () -> Void) { class BearerTokenHandler {
if bearerToken != nil { private static var bearerToken: String? = nil
completionHandler()
} else { static func refreshTokenIfDoesntExist(completionHandler: @escaping () -> Void) {
startRefreshingToken { if bearerToken != nil {
completionHandler() completionHandler()
} else {
startRefreshingToken {
completionHandler()
}
} }
} }
}
static func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error?, completionHandler: @escaping (Bool) -> Void) {
static func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error?, completionHandler: @escaping (Bool) -> Void) { if let response = response as? HTTPURLResponse, response.statusCode == 401 {
if let response = response as? HTTPURLResponse, response.statusCode == 401 { startRefreshingToken {
startRefreshingToken { completionHandler(true)
completionHandler(true) }
} else {
completionHandler(false)
} }
} else {
completionHandler(false)
} }
}
private static func startRefreshingToken(completionHandler: @escaping () -> Void) {
// Get a bearer token
let dummyBearerToken = "..."
bearerToken = dummyBearerToken private static func startRefreshingToken(completionHandler: @escaping () -> Void) {
PetstoreClientAPI.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)" // Get a bearer token
let dummyBearerToken = "..."
completionHandler()
bearerToken = dummyBearerToken
PetstoreClientAPI.customHeaders["Authorization"] = "Bearer \(dummyBearerToken)"
completionHandler()
}
} }
}
</details> </details>
Then you assign the `BearerRequestBuilderFactory` to the property requestBuilderFactory in the APIs.swift file. Then you assign the `BearerRequestBuilderFactory` to the property requestBuilderFactory in the APIs.swift file.
......
Clone repository
  • API client generator HOWTO
  • Building your own Templates
  • Customizing client code generation
  • FAQ
  • Git Branches
  • Home
  • How to add a generator for a new language or framework
  • Integration Tests
  • Migration Guide
  • Mustache Template Variables
  • Pull Request Checklist
  • Release Checklist
  • Samples folder
  • Server stub generator HOWTO
  • Vendor Extensions
View All Pages