[Swift] shorter readme (#19884)

* [Swift] shorter readme

* [Swift] update docs

* [Swift] update docs

* [Swift] format codegen

* [Swift] try to make CI pass
This commit is contained in:
Bruno Coelho 2024-10-16 11:55:18 +01:00 committed by GitHub
parent 65b1859161
commit ca032113f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 215 additions and 3077 deletions

View File

@ -477,6 +477,8 @@ Here is a working sample that put's together all of this.
### How do I migrate from the Swift 5 generator to the swift 6 generator? ### How do I migrate from the Swift 5 generator to the swift 6 generator?
- Change the generator to the new `swift6` generator, e.g. `openapi-generator generate -i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g swift6 -o /tmp/test/`
- Check the `swift6` [URLSession](https://github.com/OpenAPITools/openapi-generator/tree/master/samples/client/petstore/swift6/urlsessionLibrary) and [Alamofire](https://github.com/OpenAPITools/openapi-generator/tree/master/samples/client/petstore/swift6/alamofireLibrary) samples.
- The infrastructure files have been moved to a new directory called `Infrastructure`. Please delete the old ones. - 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 `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`. - 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`.

View File

@ -366,7 +366,6 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
codegenModel.vars = codegenProperties; codegenModel.vars = codegenProperties;
} }
return codegenModel; return codegenModel;
} }
@ -847,7 +846,6 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
operationId = camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER); operationId = camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER);
} }
return operationId; return operationId;
} }
@ -1306,9 +1304,11 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
System.out.println("# swift5 generator is contributed by Bruno Coelho (https://github.com/4brunu). #"); 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("# Please support his work directly via https://paypal.com/paypalme/4brunu \uD83D\uDE4F #");
System.out.println("# #"); System.out.println("# #");
System.out.println("# There is a new `swift6` generator, that is currently in beta. #"); 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("# 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/generators/swift6 #");
System.out.println("# #");
System.out.println("# If you need help migrating from the swift5 to the swift6 generator, check the following url.#");
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("# https://openapi-generator.tech/docs/faq-generators/#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator");
System.out.println("################################################################################"); System.out.println("################################################################################");
} }

View File

@ -86,45 +86,25 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
protected static final String RESPONSE_LIBRARY_ASYNC_AWAIT = "AsyncAwait"; protected static final String RESPONSE_LIBRARY_ASYNC_AWAIT = "AsyncAwait";
protected static final String RESPONSE_LIBRARY_OBJC_BLOCK = "ObjcBlock"; protected static final String RESPONSE_LIBRARY_OBJC_BLOCK = "ObjcBlock";
protected static final String[] RESPONSE_LIBRARIES = { RESPONSE_LIBRARY_ASYNC_AWAIT, RESPONSE_LIBRARY_COMBINE, RESPONSE_LIBRARY_RESULT, RESPONSE_LIBRARY_RX_SWIFT, RESPONSE_LIBRARY_OBJC_BLOCK, RESPONSE_LIBRARY_PROMISE_KIT }; protected static final String[] RESPONSE_LIBRARIES = { RESPONSE_LIBRARY_ASYNC_AWAIT, RESPONSE_LIBRARY_COMBINE, RESPONSE_LIBRARY_RESULT, RESPONSE_LIBRARY_RX_SWIFT, RESPONSE_LIBRARY_OBJC_BLOCK, RESPONSE_LIBRARY_PROMISE_KIT };
@Setter @Setter protected String projectName = "OpenAPIClient";
protected String projectName = "OpenAPIClient"; @Setter protected boolean nonPublicApi = false;
@Setter @Setter protected boolean objcCompatible = false;
protected boolean nonPublicApi = false; @Setter protected boolean readonlyProperties = false;
@Setter @Setter protected boolean swiftUseApiNamespace = false;
protected boolean objcCompatible = false; @Setter protected boolean useSPMFileStructure = true;
@Setter @Setter protected String swiftPackagePath = "Sources" + File.separator + projectName;
protected boolean readonlyProperties = false; @Setter protected boolean oneOfUnknownDefaultCase = false;
@Setter @Setter protected boolean useClasses = false;
protected boolean swiftUseApiNamespace = false; @Setter protected boolean useBacktickEscapes = false;
@Setter @Setter protected boolean generateModelAdditionalProperties = true;
protected boolean useSPMFileStructure = true; @Setter protected boolean hashableModels = true;
@Setter @Setter protected boolean useJsonEncodable = true;
protected String swiftPackagePath = "Sources" + File.separator + projectName; @Getter @Setter protected boolean mapFileBinaryToData = false;
@Setter @Setter protected boolean useCustomDateWithoutTime = false;
protected boolean oneOfUnknownDefaultCase = false; @Setter protected boolean validatable = true;
@Setter @Setter protected boolean apiStaticMethod = true;
protected boolean useClasses = false; @Setter protected boolean combineDeferred = true;
@Setter @Setter protected String[] responseAs = { RESPONSE_LIBRARY_ASYNC_AWAIT };
protected boolean useBacktickEscapes = false;
@Setter
protected boolean generateModelAdditionalProperties = true;
@Setter
protected boolean hashableModels = true;
@Setter
protected boolean useJsonEncodable = true;
@Getter
@Setter
protected boolean mapFileBinaryToData = false;
@Setter
protected boolean useCustomDateWithoutTime = false;
@Setter
protected boolean validatable = true;
@Setter
protected boolean apiStaticMethod = true;
@Setter
protected boolean combineDeferred = true;
@Setter
protected String[] responseAs = { RESPONSE_LIBRARY_ASYNC_AWAIT };
protected String sourceFolder = swiftPackagePath; protected String sourceFolder = swiftPackagePath;
protected HashSet objcReservedWords; protected HashSet objcReservedWords;
protected String apiDocPath = "docs/"; protected String apiDocPath = "docs/";
@ -184,19 +164,20 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
"Empty", "Empty",
"AnyObject", "AnyObject",
"Any", "Any",
"Decimal")); "Decimal")
);
objcReservedWords = new HashSet<>( objcReservedWords = new HashSet<>(
Arrays.asList( Arrays.asList(
// Added for Objective-C compatibility // Added for Objective-C compatibility
"id", "description", "NSArray", "NSURL", "CGFloat", "NSSet", "NSString", "NSInteger", "id", "description", "NSArray", "NSURL", "CGFloat", "NSSet", "NSString", "NSInteger", "NSUInteger",
"NSUInteger",
"NSError", "NSDictionary", "NSError", "NSDictionary",
// 'Property 'hash' with type 'String' cannot override a property with type // 'Property 'hash' with type 'String' cannot override a property with type 'Int' (when objcCompatible=true)
// 'Int' (when objcCompatible=true)
"hash", "hash",
// Cannot override with a stored property 'className' // Cannot override with a stored property 'className'
"className")); "className"
)
);
reservedWords = new HashSet<>( reservedWords = new HashSet<>(
Arrays.asList( Arrays.asList(
@ -207,29 +188,22 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410 // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410
// //
// Keywords used in declarations // Keywords used in declarations
"associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "init",
"init", "inout", "internal", "let", "open", "operator", "private", "protocol", "public", "static", "struct",
"inout", "internal", "let", "open", "operator", "private", "protocol", "public", "static",
"struct",
"subscript", "typealias", "var", "subscript", "typealias", "var",
// Keywords uses in statements // Keywords uses in statements
"break", "case", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "break", "case", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if",
"if",
"in", "repeat", "return", "switch", "where", "while", "in", "repeat", "return", "switch", "where", "while",
// Keywords used in expressions and types // Keywords used in expressions and types
"as", "Any", "catch", "false", "is", "nil", "rethrows", "super", "self", "Self", "throw", "as", "Any", "catch", "false", "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws", "true", "try",
"throws", "true", "try",
// Keywords used in patterns // Keywords used in patterns
"_", "_",
// Keywords that begin with a number sign // Keywords that begin with a number sign
"#available", "#colorLiteral", "#column", "#else", "#elseif", "#endif", "#file", "#fileLiteral", "#available", "#colorLiteral", "#column", "#else", "#elseif", "#endif", "#file", "#fileLiteral", "#function", "#if",
"#function", "#if",
"#imageLiteral", "#line", "#selector", "#sourceLocation", "#imageLiteral", "#line", "#selector", "#sourceLocation",
// Keywords reserved in particular contexts // Keywords reserved in particular contexts
"associativity", "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", "associativity", "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", "lazy", "left",
"lazy", "left", "mutating", "none", "nonmutating", "optional", "override", "postfix", "precedence", "prefix", "Protocol",
"mutating", "none", "nonmutating", "optional", "override", "postfix", "precedence", "prefix",
"Protocol",
"required", "right", "set", "Type", "unowned", "weak", "willSet", "required", "right", "set", "Type", "unowned", "weak", "willSet",
// //
@ -239,8 +213,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
// Numbers and Basic Values // Numbers and Basic Values
"Bool", "Int", "Double", "Float", "Range", "ClosedRange", "Error", "Optional", "Bool", "Int", "Double", "Float", "Range", "ClosedRange", "Error", "Optional",
// Special-Use Numeric Types // Special-Use Numeric Types
"UInt", "UInt8", "UInt16", "UInt32", "UInt64", "Int8", "Int16", "Int32", "Int64", "Float80", "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "Int8", "Int16", "Int32", "Int64", "Float80", "Float32", "Float64",
"Float32", "Float64",
// Strings and Text // Strings and Text
"String", "Character", "Unicode", "StaticString", "String", "Character", "Unicode", "StaticString",
// Collections // Collections
@ -250,7 +223,9 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
"URL", "Data", "Codable", "Encodable", "Decodable", "URL", "Data", "Codable", "Encodable", "Decodable",
// The following are other words we want to reserve // The following are other words we want to reserve
"Void", "AnyObject", "Class", "dynamicType", "COLUMN", "FILE", "FUNCTION", "LINE")); "Void", "AnyObject", "Class", "dynamicType", "COLUMN", "FILE", "FUNCTION", "LINE"
)
);
typeMapping = new HashMap<>(); typeMapping = new HashMap<>();
typeMapping.put("array", "Array"); typeMapping.put("array", "Array");
@ -435,8 +410,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
inner = ModelUtils.getAdditionalProperties(schema); inner = ModelUtils.getAdditionalProperties(schema);
} }
codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties);
: getSchemaType(additionalProperties);
} }
} }
@ -445,10 +419,8 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
super.processOpts(); super.processOpts();
if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) { if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) {
LOGGER.info( LOGGER.info("Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)");
"Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)"); LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
LOGGER.info(
"NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
} else if (!this.isEnablePostProcessFile()) { } else if (!this.isEnablePostProcessFile()) {
LOGGER.info("Warning: Environment variable 'SWIFT_POST_PROCESS_FILE' is set but file post-processing is not enabled. To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI)."); LOGGER.info("Warning: Environment variable 'SWIFT_POST_PROCESS_FILE' is set but file post-processing is not enabled. To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
} }
@ -536,8 +508,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
sourceFolder = projectName + File.separator + "Classes" + File.separator + "OpenAPIs"; sourceFolder = projectName + File.separator + "Classes" + File.separator + "OpenAPIs";
} }
if (additionalProperties.containsKey(SWIFT_PACKAGE_PATH) if (additionalProperties.containsKey(SWIFT_PACKAGE_PATH) && ((String) additionalProperties.get(SWIFT_PACKAGE_PATH)).length() > 0) {
&& ((String) additionalProperties.get(SWIFT_PACKAGE_PATH)).length() > 0) {
setSwiftPackagePath((String) additionalProperties.get(SWIFT_PACKAGE_PATH)); setSwiftPackagePath((String) additionalProperties.get(SWIFT_PACKAGE_PATH));
sourceFolder = swiftPackagePath; sourceFolder = swiftPackagePath;
} }
@ -547,8 +518,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
} }
if (additionalProperties.containsKey(GENERATE_MODEL_ADDITIONAL_PROPERTIES)) { if (additionalProperties.containsKey(GENERATE_MODEL_ADDITIONAL_PROPERTIES)) {
setGenerateModelAdditionalProperties( setGenerateModelAdditionalProperties(convertPropertyToBooleanAndWriteBack(GENERATE_MODEL_ADDITIONAL_PROPERTIES));
convertPropertyToBooleanAndWriteBack(GENERATE_MODEL_ADDITIONAL_PROPERTIES));
} }
additionalProperties.put(GENERATE_MODEL_ADDITIONAL_PROPERTIES, generateModelAdditionalProperties); additionalProperties.put(GENERATE_MODEL_ADDITIONAL_PROPERTIES, generateModelAdditionalProperties);
@ -704,7 +674,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
protected boolean isReservedWord(String word) { protected boolean isReservedWord(String word) {
return word != null && reservedWords.contains(word); // don't lowercase as super does return word != null && reservedWords.contains(word); //don't lowercase as super does
} }
@Override @Override
@ -731,8 +701,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
public String getTypeDeclaration(Schema p) { public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) { if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p); Schema inner = ModelUtils.getSchemaItems(p);
return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" return ModelUtils.isSet(p) ? "Set<" + getTypeDeclaration(inner) + ">" : "[" + getTypeDeclaration(inner) + "]";
: "[" + getTypeDeclaration(inner) + "]";
} else if (ModelUtils.isMapSchema(p)) { } else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p); Schema inner = ModelUtils.getAdditionalProperties(p);
return "[String: " + getTypeDeclaration(inner) + "]"; return "[String: " + getTypeDeclaration(inner) + "]";
@ -835,13 +804,10 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) { if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p) || ModelUtils.isBooleanSchema(p)) {
return p.getDefault().toString(); return p.getDefault().toString();
} else if (ModelUtils.isDateTimeSchema(p)) { } else if (ModelUtils.isDateTimeSchema(p)) {
// Datetime time stamps in Swift are expressed as Seconds with Microsecond // Datetime time stamps in Swift are expressed as Seconds with Microsecond precision.
// precision. // In Java, we need to be creative to get the Timestamp in Microseconds as a long.
// In Java, we need to be creative to get the Timestamp in Microseconds as a
// long.
Instant instant = ((OffsetDateTime) p.getDefault()).toInstant(); Instant instant = ((OffsetDateTime) p.getDefault()).toInstant();
long epochMicro = TimeUnit.SECONDS.toMicros(instant.getEpochSecond()) long epochMicro = TimeUnit.SECONDS.toMicros(instant.getEpochSecond()) + (instant.get(ChronoField.MICRO_OF_SECOND));
+ (instant.get(ChronoField.MICRO_OF_SECOND));
return "Date(timeIntervalSince1970: " + epochMicro + ".0 / 1_000_000)"; return "Date(timeIntervalSince1970: " + epochMicro + ".0 / 1_000_000)";
} else if (ModelUtils.isStringSchema(p)) { } else if (ModelUtils.isStringSchema(p)) {
return "\"" + escapeText(String.valueOf(p.getDefault())) + "\""; return "\"" + escapeText(String.valueOf(p.getDefault())) + "\"";
@ -909,8 +875,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
// operationId starts with a number // operationId starts with a number
if (operationId.matches("^\\d.*")) { if (operationId.matches("^\\d.*")) {
LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER));
camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER));
operationId = camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER); operationId = camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER);
} }
@ -1055,8 +1020,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
// for symbol, e.g. $, # // for symbol, e.g. $, #
if (getSymbolName(name) != null) { if (getSymbolName(name) != null) {
return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)), return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)), LOWERCASE_FIRST_LETTER);
LOWERCASE_FIRST_LETTER);
} }
// Camelize only when we have a structure defined below // Camelize only when we have a structure defined below
@ -1079,7 +1043,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
return replaceSpecialCharacters(name); return replaceSpecialCharacters(name);
} }
char[] separators = { '-', '_', ' ', ':', '(', ')' }; char[] separators = {'-', '_', ' ', ':', '(', ')'};
return camelize(replaceSpecialCharacters(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators) return camelize(replaceSpecialCharacters(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators)
.replaceAll("[-_ :\\(\\)]", "")), .replaceAll("[-_ :\\(\\)]", "")),
LOWERCASE_FIRST_LETTER); LOWERCASE_FIRST_LETTER);
@ -1169,8 +1133,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
// //
// CodegenProperty.vendorExtensions["x-codegen-escaped-property-name"] = true // CodegenProperty.vendorExtensions["x-codegen-escaped-property-name"] = true
// //
// Also, if any property in the model has x-codegen-escaped-property-name=true, // Also, if any property in the model has x-codegen-escaped-property-name=true, then we mark:
// then we mark:
// //
// CodegenModel.vendorExtensions["x-codegen-has-escaped-property-names"] = true // CodegenModel.vendorExtensions["x-codegen-has-escaped-property-names"] = true
// //
@ -1188,8 +1151,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
if (prop.defaultValue == null || prop.defaultValue.equals("null")) { if (prop.defaultValue == null || prop.defaultValue.equals("null")) {
prop.vendorExtensions.put("x-null-encodable-default-value", ".encodeNull"); prop.vendorExtensions.put("x-null-encodable-default-value", ".encodeNull");
} else { } else {
prop.vendorExtensions.put("x-null-encodable-default-value", prop.vendorExtensions.put("x-null-encodable-default-value", ".encodeValue(" + prop.defaultValue + ")");
".encodeValue(" + prop.defaultValue + ")");
} }
} }
} }
@ -1259,8 +1221,7 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
return objs; return objs;
} }
public String constructExampleCode(CodegenParameter codegenParameter, HashMap<String, CodegenModel> modelMaps, public String constructExampleCode(CodegenParameter codegenParameter, HashMap<String, CodegenModel> modelMaps, Set<String> visitedModels) {
Set<String> visitedModels) {
if (codegenParameter.isArray) { // array if (codegenParameter.isArray) { // array
return "[" + constructExampleCode(codegenParameter.items, modelMaps, visitedModels) + "]"; return "[" + constructExampleCode(codegenParameter.items, modelMaps, visitedModels) + "]";
} else if (codegenParameter.isMap) { // TODO: map, file type } else if (codegenParameter.isMap) { // TODO: map, file type
@ -1302,15 +1263,13 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, visitedModels); return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, visitedModels);
} }
} else { } else {
// LOGGER.error("Error in constructing examples. Failed to look up the model " + //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType);
// codegenParameter.dataType);
return "TODO"; return "TODO";
} }
} }
} }
public String constructExampleCode(CodegenProperty codegenProperty, HashMap<String, CodegenModel> modelMaps, public String constructExampleCode(CodegenProperty codegenProperty, HashMap<String, CodegenModel> modelMaps, Set<String> visitedModels) {
Set<String> visitedModels) {
if (codegenProperty.isArray) { // array if (codegenProperty.isArray) { // array
return "[" + constructExampleCode(codegenProperty.items, modelMaps, visitedModels) + "]"; return "[" + constructExampleCode(codegenProperty.items, modelMaps, visitedModels) + "]";
} else if (codegenProperty.isMap) { // TODO: map, file type } else if (codegenProperty.isMap) { // TODO: map, file type
@ -1350,21 +1309,18 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, visitedModels); return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, visitedModels);
} }
} else { } else {
// LOGGER.error("Error in constructing examples. Failed to look up the model " + //LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenProperty.dataType);
// codegenProperty.dataType);
return "\"TODO\""; return "\"TODO\"";
} }
} }
} }
public String constructExampleCode(CodegenModel codegenModel, HashMap<String, CodegenModel> modelMaps, public String constructExampleCode(CodegenModel codegenModel, HashMap<String, CodegenModel> modelMaps, Set<String> visitedModels) {
Set<String> visitedModels) {
String example; String example;
example = codegenModel.name + "("; example = codegenModel.name + "(";
List<String> propertyExamples = new ArrayList<>(); List<String> propertyExamples = new ArrayList<>();
for (CodegenProperty codegenProperty : codegenModel.vars) { for (CodegenProperty codegenProperty : codegenModel.vars) {
propertyExamples propertyExamples.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps, visitedModels));
.add(codegenProperty.name + ": " + constructExampleCode(codegenProperty, modelMaps, visitedModels));
} }
example += StringUtils.join(propertyExamples, ", "); example += StringUtils.join(propertyExamples, ", ");
example += ")"; example += ")";
@ -1375,13 +1331,14 @@ public class Swift6ClientCodegen extends DefaultCodegen implements CodegenConfig
public void postProcess() { public void postProcess() {
System.out.println("################################################################################"); System.out.println("################################################################################");
System.out.println("# Thanks for using OpenAPI Generator. #"); System.out.println("# Thanks for using OpenAPI Generator. #");
System.out System.out.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
System.out.println("# https://opencollective.com/openapi_generator/donate #"); System.out.println("# https://opencollective.com/openapi_generator/donate #");
System.out.println("# #"); System.out.println("# #");
System.out.println("# swift6 generator is contributed by Bruno Coelho (https://github.com/4brunu). #"); System.out.println("# swift6 generator is contributed by Bruno Coelho (https://github.com/4brunu). #");
System.out System.out.println("# Please support his work directly via https://paypal.com/paypalme/4brunu \uD83D\uDE4F #");
.println("# Please support his work directly via https://paypal.com/paypalme/4brunu \uD83D\uDE4F #"); System.out.println("# #");
System.out.println("# If you need help migrating from the swift5 to the swift6 generator, check the following url.#");
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("################################################################################"); System.out.println("################################################################################");
} }

View File

@ -78,250 +78,20 @@ Class | Method | HTTP request | Description
{{/authMethods}} {{/authMethods}}
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
{{#useURLSession}} {{#useURLSession}}
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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}} {{/useURLSession}}
{{#useAlamofire}} {{#useAlamofire}}
### How do I implement bearer token authentication with Alamofire on the Swift 5 API client? ### How do I implement bearer token authentication with Alamofire on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-alamofire-on-the-swift-5-api-client
```
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}} {{/useAlamofire}}
## Author ## Author

View File

@ -78,140 +78,20 @@ Class | Method | HTTP request | Description
{{/authMethods}} {{/authMethods}}
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
{{#useURLSession}} {{#useURLSession}}
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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}} {{/useURLSession}}
{{#useAlamofire}} {{#useAlamofire}}
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client? ### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
First implement the `Alamofire` `RequestInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-alamofire-on-the-swift-6-api-client
```
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}} {{/useAlamofire}}
## Author ## Author

View File

@ -140,91 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with Alamofire on the Swift 5 API client? ### How do I implement bearer token authentication with Alamofire on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-alamofire-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -151,162 +151,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -42,162 +42,13 @@ Class | Method | HTTP request | Description
Endpoints do not require authorization. Endpoints do not require authorization.
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -8,7 +8,7 @@ DIRECTORY=`dirname $0`
(cd $DIRECTORY/asyncAwaitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/asyncAwaitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/combineLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/combineLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/default/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/default/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/promisekitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) # (cd $DIRECTORY/promisekitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/rxswiftLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/rxswiftLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
# (cd $DIRECTORY/urlsessionLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) # (cd $DIRECTORY/urlsessionLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
@ -19,7 +19,7 @@ DIRECTORY=`dirname $0`
(cd $DIRECTORY/default/ && ./run_spmbuild.sh) (cd $DIRECTORY/default/ && ./run_spmbuild.sh)
(cd $DIRECTORY/objcCompatible/ && ./run_spmbuild.sh) (cd $DIRECTORY/objcCompatible/ && ./run_spmbuild.sh)
(cd $DIRECTORY/oneOf/ && ./run_spmbuild.sh) (cd $DIRECTORY/oneOf/ && ./run_spmbuild.sh)
(cd $DIRECTORY/promisekitLibrary/ && ./run_spmbuild.sh) # (cd $DIRECTORY/promisekitLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/resultLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/resultLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/rxswiftLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/rxswiftLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/urlsessionLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/urlsessionLibrary/ && ./run_spmbuild.sh)

View File

@ -140,162 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -40,162 +40,13 @@ Class | Method | HTTP request | Description
Endpoints do not require authorization. Endpoints do not require authorization.
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 5 API client? ### How do I implement bearer token authentication with URLSession on the Swift 5 API client?
First you subclass RequestBuilderFactory https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-5-api-client
```
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 ## Author

View File

@ -147,6 +147,9 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
## Author ## Author

View File

@ -140,55 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client? ### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
First implement the `Alamofire` `RequestInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-alamofire-on-the-swift-6-api-client
```
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 ## Author

View File

@ -138,55 +138,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with Alamofire on the Swift 6 API client? ### How do I implement bearer token authentication with Alamofire on the Swift 6 API client?
First implement the `Alamofire` `RequestInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-alamofire-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -151,88 +151,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -42,88 +42,13 @@ Class | Method | HTTP request | Description
Endpoints do not require authorization. Endpoints do not require authorization.
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -10,7 +10,7 @@ DIRECTORY=`dirname $0`
# (cd $DIRECTORY/combineLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) # (cd $DIRECTORY/combineLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/combineDeferredLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/combineDeferredLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/default/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/default/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/promisekitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) # (cd $DIRECTORY/promisekitLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/rxswiftLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/rxswiftLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
(cd $DIRECTORY/urlsessionLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh) (cd $DIRECTORY/urlsessionLibrary/SwaggerClientTests/ && ./run_xcodebuild.sh)
@ -23,7 +23,7 @@ DIRECTORY=`dirname $0`
(cd $DIRECTORY/default/ && ./run_spmbuild.sh) (cd $DIRECTORY/default/ && ./run_spmbuild.sh)
(cd $DIRECTORY/objcCompatible/ && ./run_spmbuild.sh) (cd $DIRECTORY/objcCompatible/ && ./run_spmbuild.sh)
(cd $DIRECTORY/oneOf/ && ./run_spmbuild.sh) (cd $DIRECTORY/oneOf/ && ./run_spmbuild.sh)
(cd $DIRECTORY/promisekitLibrary/ && ./run_spmbuild.sh) # (cd $DIRECTORY/promisekitLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/resultLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/resultLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/rxswiftLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/rxswiftLibrary/ && ./run_spmbuild.sh)
(cd $DIRECTORY/urlsessionLibrary/ && ./run_spmbuild.sh) (cd $DIRECTORY/urlsessionLibrary/ && ./run_spmbuild.sh)

View File

@ -140,88 +140,13 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -40,88 +40,13 @@ Class | Method | HTTP request | Description
Endpoints do not require authorization. Endpoints do not require authorization.
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
### How do I implement bearer token authentication with URLSession on the Swift 6 API client? ### How do I implement bearer token authentication with URLSession on the Swift 6 API client?
First you implement the `OpenAPIInterceptor` protocol. https://openapi-generator.tech/docs/faq-generators#how-do-i-implement-bearer-token-authentication-with-urlsession-on-the-swift-6-api-client
```
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 ## Author

View File

@ -147,6 +147,9 @@ Authentication schemes defined for the API:
- **Type**: HTTP basic authentication - **Type**: HTTP basic authentication
# How do I migrate from the Swift 5 generator to the swift 6 generator?
https://openapi-generator.tech/docs/faq-generators#how-do-i-migrate-from-the-swift-5-generator-to-the-swift-6-generator
## Author ## Author