forked from loafle/openapi-generator-original
[Swift] Adding Swift3 generator
* This address #3788 * Contains all changes made in #3823 * Also contains many changes made by @ewanmellor, thanks!
This commit is contained in:
40
bin/swift3-petstore-all.sh
Executable file
40
bin/swift3-petstore-all.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore.json -o samples/client/petstore/swift3/default"
|
||||
|
||||
echo "#### Petstore Swift API client (default) ####"
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-promisekit.json -o samples/client/petstore/swift3/promisekit"
|
||||
echo "#### Petstore Swift API client (promisekit) ####"
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-rxswift.json -o samples/client/petstore/swift3/rxswift"
|
||||
echo "#### Petstore Swift API client (rxswift) ####"
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
7
bin/swift3-petstore-promisekit.json
Normal file
7
bin/swift3-petstore-promisekit.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"podSummary": "PetstoreClient",
|
||||
"podHomepage": "https://github.com/swagger-api/swagger-codegen",
|
||||
"podAuthors": "",
|
||||
"projectName": "PetstoreClient",
|
||||
"responseAs": "PromiseKit"
|
||||
}
|
||||
31
bin/swift3-petstore-promisekit.sh
Executable file
31
bin/swift3-petstore-promisekit.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-promisekit.json -o samples/client/petstore/swift/promisekit"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
7
bin/swift3-petstore-rxswift.json
Normal file
7
bin/swift3-petstore-rxswift.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"podSummary": "PetstoreClient",
|
||||
"podHomepage": "https://github.com/swagger-api/swagger-codegen",
|
||||
"podAuthors": "",
|
||||
"projectName": "PetstoreClient",
|
||||
"responseAs": "RxSwift"
|
||||
}
|
||||
31
bin/swift3-petstore-rxswift.sh
Executable file
31
bin/swift3-petstore-rxswift.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-rxswift.json -o samples/client/petstore/swift3/rxswift"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
6
bin/swift3-petstore.json
Normal file
6
bin/swift3-petstore.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"podSummary": "PetstoreClient",
|
||||
"podHomepage": "https://github.com/swagger-api/swagger-codegen",
|
||||
"podAuthors": "",
|
||||
"projectName": "PetstoreClient"
|
||||
}
|
||||
31
bin/swift3-petstore.sh
Executable file
31
bin/swift3-petstore.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore.json -o samples/client/petstore/swift3/default"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
@@ -9,7 +9,7 @@ public class CodegenParameter {
|
||||
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
|
||||
isCookieParam, isBodyParam, hasMore, isContainer,
|
||||
secondaryParam, isCollectionFormatMulti, isPrimitiveType;
|
||||
public String baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue;
|
||||
public String baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName;
|
||||
public String example; // example value (x-example)
|
||||
public String jsonSchema;
|
||||
public Boolean isString, isInteger, isLong, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime;
|
||||
@@ -85,6 +85,7 @@ public class CodegenParameter {
|
||||
output.paramName = this.paramName;
|
||||
output.dataType = this.dataType;
|
||||
output.datatypeWithEnum = this.datatypeWithEnum;
|
||||
output.enumName = this.enumName;
|
||||
output.dataFormat = this.dataFormat;
|
||||
output.collectionFormat = this.collectionFormat;
|
||||
output.isCollectionFormatMulti = this.isCollectionFormatMulti;
|
||||
@@ -182,6 +183,8 @@ public class CodegenParameter {
|
||||
return false;
|
||||
if (datatypeWithEnum != null ? !datatypeWithEnum.equals(that.datatypeWithEnum) : that.datatypeWithEnum != null)
|
||||
return false;
|
||||
if (enumName != null ? !enumName.equals(that.enumName) : that.enumName != null)
|
||||
return false;
|
||||
if (dataFormat != null ? !dataFormat.equals(that.dataFormat) : that.dataFormat != null)
|
||||
return false;
|
||||
if (collectionFormat != null ? !collectionFormat.equals(that.collectionFormat) : that.collectionFormat != null)
|
||||
@@ -279,6 +282,7 @@ public class CodegenParameter {
|
||||
result = 31 * result + (paramName != null ? paramName.hashCode() : 0);
|
||||
result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
|
||||
result = 31 * result + (datatypeWithEnum != null ? datatypeWithEnum.hashCode() : 0);
|
||||
result = 31 * result + (enumName != null ? enumName.hashCode() : 0);
|
||||
result = 31 * result + (dataFormat != null ? dataFormat.hashCode() : 0);
|
||||
result = 31 * result + (collectionFormat != null ? collectionFormat.hashCode() : 0);
|
||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||
|
||||
@@ -1307,13 +1307,15 @@ public class DefaultCodegen {
|
||||
addVars(m, properties, required, allProperties, allRequired);
|
||||
} else {
|
||||
ModelImpl impl = (ModelImpl) model;
|
||||
if (m != null && impl.getType() != null) {
|
||||
Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
|
||||
m.dataType = getSwaggerType(p);
|
||||
}
|
||||
if(impl.getEnum() != null && impl.getEnum().size() > 0) {
|
||||
m.isEnum = true;
|
||||
// comment out below as allowableValues is not set in post processing model enum
|
||||
m.allowableValues = new HashMap<String, Object>();
|
||||
m.allowableValues.put("values", impl.getEnum());
|
||||
Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
|
||||
m.dataType = getSwaggerType(p);
|
||||
}
|
||||
if (impl.getAdditionalProperties() != null) {
|
||||
addAdditionPropertiesToCodeGenModel(m, impl);
|
||||
@@ -2263,6 +2265,7 @@ public class DefaultCodegen {
|
||||
p.dataFormat = cp.dataFormat;
|
||||
if(cp.isEnum) {
|
||||
p.datatypeWithEnum = cp.datatypeWithEnum;
|
||||
p.enumName = cp.enumName;
|
||||
}
|
||||
|
||||
// enum
|
||||
@@ -2274,6 +2277,7 @@ public class DefaultCodegen {
|
||||
|
||||
if (cp.items != null && cp.items.isEnum) {
|
||||
p.datatypeWithEnum = cp.datatypeWithEnum;
|
||||
p.enumName = cp.enumName;
|
||||
p.items = cp.items;
|
||||
}
|
||||
p.collectionFormat = collectionFormat;
|
||||
|
||||
@@ -0,0 +1,549 @@
|
||||
package io.swagger.codegen.languages;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.swagger.codegen.*;
|
||||
import io.swagger.models.Model;
|
||||
import io.swagger.models.Operation;
|
||||
import io.swagger.models.Swagger;
|
||||
import io.swagger.models.parameters.HeaderParameter;
|
||||
import io.swagger.models.parameters.Parameter;
|
||||
import io.swagger.models.properties.ArrayProperty;
|
||||
import io.swagger.models.properties.MapProperty;
|
||||
import io.swagger.models.properties.Property;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
public static final String PROJECT_NAME = "projectName";
|
||||
public static final String RESPONSE_AS = "responseAs";
|
||||
public static final String UNWRAP_REQUIRED = "unwrapRequired";
|
||||
public static final String POD_SOURCE = "podSource";
|
||||
public static final String POD_AUTHORS = "podAuthors";
|
||||
public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL";
|
||||
public static final String POD_DOCSET_URL = "podDocsetURL";
|
||||
public static final String POD_LICENSE = "podLicense";
|
||||
public static final String POD_HOMEPAGE = "podHomepage";
|
||||
public static final String POD_SUMMARY = "podSummary";
|
||||
public static final String POD_DESCRIPTION = "podDescription";
|
||||
public static final String POD_SCREENSHOTS = "podScreenshots";
|
||||
public static final String POD_DOCUMENTATION_URL = "podDocumentationURL";
|
||||
public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace";
|
||||
public static final String DEFAULT_POD_AUTHORS = "Swagger Codegen";
|
||||
protected static final String LIBRARY_PROMISE_KIT = "PromiseKit";
|
||||
protected static final String LIBRARY_RX_SWIFT = "RxSwift";
|
||||
protected static final String[] RESPONSE_LIBRARIES = {LIBRARY_PROMISE_KIT, LIBRARY_RX_SWIFT};
|
||||
protected String projectName = "SwaggerClient";
|
||||
protected boolean unwrapRequired;
|
||||
protected boolean swiftUseApiNamespace;
|
||||
protected String[] responseAs = new String[0];
|
||||
protected String sourceFolder = "Classes" + File.separator + "Swaggers";
|
||||
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}");
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "swift3";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a swift client library.";
|
||||
}
|
||||
|
||||
public Swift3Codegen() {
|
||||
super();
|
||||
outputFolder = "generated-code" + File.separator + "swift";
|
||||
modelTemplateFiles.put("model.mustache", ".swift");
|
||||
apiTemplateFiles.put("api.mustache", ".swift");
|
||||
embeddedTemplateDir = templateDir = "swift";
|
||||
apiPackage = File.separator + "APIs";
|
||||
modelPackage = File.separator + "Models";
|
||||
|
||||
languageSpecificPrimitives = new HashSet<>(
|
||||
Arrays.asList(
|
||||
"Int",
|
||||
"Int32",
|
||||
"Int64",
|
||||
"Float",
|
||||
"Double",
|
||||
"Bool",
|
||||
"Void",
|
||||
"String",
|
||||
"Character",
|
||||
"AnyObject",
|
||||
"Any")
|
||||
);
|
||||
defaultIncludes = new HashSet<>(
|
||||
Arrays.asList(
|
||||
"Data",
|
||||
"Date",
|
||||
"URL", // for file
|
||||
"UUID",
|
||||
"Array",
|
||||
"Dictionary",
|
||||
"Set",
|
||||
"Any",
|
||||
"Empty",
|
||||
"AnyObject",
|
||||
"Any")
|
||||
);
|
||||
reservedWords = new HashSet<>(
|
||||
Arrays.asList(
|
||||
"Int", "Int32", "Int64", "Int64", "Float", "Double", "Bool", "Void", "String", "Character", "AnyObject", "Any",
|
||||
"class", "Class", "break", "as", "associativity", "deinit", "case", "dynamicType", "convenience", "enum", "continue",
|
||||
"false", "dynamic", "extension", "default", "is", "didSet", "func", "do", "nil", "final", "import", "else",
|
||||
"self", "get", "init", "fallthrough", "Self", "infix", "internal", "for", "super", "inout", "let", "if",
|
||||
"true", "lazy", "operator", "in", "COLUMN", "left", "private", "return", "FILE", "mutating", "protocol",
|
||||
"switch", "FUNCTION", "none", "public", "where", "LINE", "nonmutating", "static", "while", "optional",
|
||||
"struct", "override", "subscript", "postfix", "typealias", "precedence", "var", "prefix", "Protocol",
|
||||
"required", "right", "set", "Type", "unowned", "weak")
|
||||
);
|
||||
|
||||
typeMapping = new HashMap<>();
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("map", "Dictionary");
|
||||
typeMapping.put("date", "Date");
|
||||
typeMapping.put("Date", "Date");
|
||||
typeMapping.put("DateTime", "Date");
|
||||
typeMapping.put("boolean", "Bool");
|
||||
typeMapping.put("string", "String");
|
||||
typeMapping.put("char", "Character");
|
||||
typeMapping.put("short", "Int");
|
||||
typeMapping.put("int", "Int32");
|
||||
typeMapping.put("long", "Int64");
|
||||
typeMapping.put("integer", "Int32");
|
||||
typeMapping.put("Integer", "Int32");
|
||||
typeMapping.put("float", "Float");
|
||||
typeMapping.put("number", "Double");
|
||||
typeMapping.put("double", "Double");
|
||||
typeMapping.put("object", "Any");
|
||||
typeMapping.put("file", "URL");
|
||||
typeMapping.put("binary", "Data");
|
||||
typeMapping.put("ByteArray", "Data");
|
||||
typeMapping.put("UUID", "UUID");
|
||||
|
||||
importMapping = new HashMap<>();
|
||||
|
||||
cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode"));
|
||||
cliOptions.add(new CliOption(RESPONSE_AS, "Optionally use libraries to manage response. Currently " +
|
||||
StringUtils.join(RESPONSE_LIBRARIES, ", ") + " are available."));
|
||||
cliOptions.add(new CliOption(UNWRAP_REQUIRED, "Treat 'required' properties in response as non-optional " +
|
||||
"(which would crash the app if api returns null as opposed to required option specified in json schema"));
|
||||
cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_SOCIAL_MEDIA_URL, "Social Media URL used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_DOCSET_URL, "Docset URL used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_LICENSE, "License used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_HOMEPAGE, "Homepage used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_SUMMARY, "Summary used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_DESCRIPTION, "Description used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_SCREENSHOTS, "Screenshots used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_DOCUMENTATION_URL, "Documentation URL used for Podspec"));
|
||||
cliOptions.add(new CliOption(SWIFT_USE_API_NAMESPACE, "Flag to make all the API classes inner-class of {{projectName}}API"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "hides the timestamp when files were generated")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
// default HIDE_GENERATION_TIMESTAMP to true
|
||||
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
|
||||
}
|
||||
|
||||
// Setup project name
|
||||
if (additionalProperties.containsKey(PROJECT_NAME)) {
|
||||
setProjectName((String) additionalProperties.get(PROJECT_NAME));
|
||||
} else {
|
||||
additionalProperties.put(PROJECT_NAME, projectName);
|
||||
}
|
||||
sourceFolder = projectName + File.separator + sourceFolder;
|
||||
|
||||
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
|
||||
if (additionalProperties.containsKey(UNWRAP_REQUIRED)) {
|
||||
setUnwrapRequired(Boolean.parseBoolean(String.valueOf(additionalProperties.get(UNWRAP_REQUIRED))));
|
||||
}
|
||||
additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired);
|
||||
|
||||
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
|
||||
if (additionalProperties.containsKey(RESPONSE_AS)) {
|
||||
Object responseAsObject = additionalProperties.get(RESPONSE_AS);
|
||||
if (responseAsObject instanceof String) {
|
||||
setResponseAs(((String) responseAsObject).split(","));
|
||||
} else {
|
||||
setResponseAs((String[]) responseAsObject);
|
||||
}
|
||||
}
|
||||
additionalProperties.put(RESPONSE_AS, responseAs);
|
||||
if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) {
|
||||
additionalProperties.put("usePromiseKit", true);
|
||||
}
|
||||
if (ArrayUtils.contains(responseAs, LIBRARY_RX_SWIFT)) {
|
||||
additionalProperties.put("useRxSwift", true);
|
||||
}
|
||||
|
||||
// Setup swiftUseApiNamespace option, which makes all the API classes inner-class of {{projectName}}API
|
||||
if (additionalProperties.containsKey(SWIFT_USE_API_NAMESPACE)) {
|
||||
swiftUseApiNamespace = Boolean.parseBoolean(String.valueOf(additionalProperties.get(SWIFT_USE_API_NAMESPACE)));
|
||||
}
|
||||
additionalProperties.put(SWIFT_USE_API_NAMESPACE, swiftUseApiNamespace);
|
||||
|
||||
if (!additionalProperties.containsKey(POD_AUTHORS)) {
|
||||
additionalProperties.put(POD_AUTHORS, DEFAULT_POD_AUTHORS);
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("Podspec.mustache", "", projectName + ".podspec"));
|
||||
supportingFiles.add(new SupportingFile("Cartfile.mustache", "", "Cartfile"));
|
||||
supportingFiles.add(new SupportingFile("APIHelper.mustache", sourceFolder, "APIHelper.swift"));
|
||||
supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", sourceFolder,
|
||||
"AlamofireImplementations.swift"));
|
||||
supportingFiles.add(new SupportingFile("Extensions.mustache", sourceFolder, "Extensions.swift"));
|
||||
supportingFiles.add(new SupportingFile("Models.mustache", sourceFolder, "Models.swift"));
|
||||
supportingFiles.add(new SupportingFile("APIs.mustache", sourceFolder, "APIs.swift"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReservedWord(String word) {
|
||||
return word != null && reservedWords.contains(word); //don't lowercase as super does
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
return "_" + name; // add an underscore to the name
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + sourceFolder + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Property p) {
|
||||
if (p instanceof ArrayProperty) {
|
||||
ArrayProperty ap = (ArrayProperty) p;
|
||||
Property inner = ap.getItems();
|
||||
return "[" + getTypeDeclaration(inner) + "]";
|
||||
} else if (p instanceof MapProperty) {
|
||||
MapProperty mp = (MapProperty) p;
|
||||
Property inner = mp.getAdditionalProperties();
|
||||
return "[String:" + getTypeDeclaration(inner) + "]";
|
||||
}
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSwaggerType(Property p) {
|
||||
String swaggerType = super.getSwaggerType(p);
|
||||
String type;
|
||||
if (typeMapping.containsKey(swaggerType)) {
|
||||
type = typeMapping.get(swaggerType);
|
||||
if (languageSpecificPrimitives.contains(type) || defaultIncludes.contains(type))
|
||||
return type;
|
||||
} else
|
||||
type = swaggerType;
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataTypeBinary(final String dataType) {
|
||||
return dataType != null && dataType.equals("Data");
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the proper model name (capitalized)
|
||||
*
|
||||
* @param name the name of the model
|
||||
* @return capitalized model name
|
||||
*/
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix
|
||||
name = name + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix
|
||||
name = modelNamePrefix + "_" + name;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
name = camelize(name);
|
||||
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(name)) {
|
||||
String modelName = "Model" + name;
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
String modelName = "Model" + name; // e.g. 200Response => Model200Response (after camelize)
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the capitalized file name of the model
|
||||
*
|
||||
* @param name the model name
|
||||
* @return the file name of the model
|
||||
*/
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Property p) {
|
||||
// nil
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toInstantiationType(Property p) {
|
||||
if (p instanceof MapProperty) {
|
||||
MapProperty ap = (MapProperty) p;
|
||||
String inner = getSwaggerType(ap.getAdditionalProperties());
|
||||
return "[String:" + inner + "]";
|
||||
} else if (p instanceof ArrayProperty) {
|
||||
ArrayProperty ap = (ArrayProperty) p;
|
||||
String inner = getSwaggerType(ap.getItems());
|
||||
return "[" + inner + "]";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name.length() == 0)
|
||||
return "DefaultAPI";
|
||||
return initialCaps(name) + "API";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
operationId = camelize(sanitizeName(operationId), true);
|
||||
|
||||
// throw exception if method name is empty. This should not happen but keep the check just in case
|
||||
if (StringUtils.isEmpty(operationId)) {
|
||||
throw new RuntimeException("Empty method name (operationId) not allowed");
|
||||
}
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(operationId)) {
|
||||
String newOperationId = camelize(("call_" + operationId), true);
|
||||
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
|
||||
return newOperationId;
|
||||
}
|
||||
|
||||
return operationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// camelize the variable name
|
||||
// pet_id => petId
|
||||
name = camelize(name, true);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
name = name.replaceAll("-", "_");
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// camelize(lower) the variable name
|
||||
// pet_id => petId
|
||||
name = camelize(name, true);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
|
||||
path = normalizePath(path); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
List<Parameter> parameters = operation.getParameters();
|
||||
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable Parameter parameter) {
|
||||
return !(parameter instanceof HeaderParameter);
|
||||
}
|
||||
}));
|
||||
operation.setParameters(parameters);
|
||||
return super.fromOperation(path, httpMethod, operation, definitions, swagger);
|
||||
}
|
||||
|
||||
private static String normalizePath(String path) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
int cursor = 0;
|
||||
Matcher matcher = PATH_PARAM_PATTERN.matcher(path);
|
||||
boolean found = matcher.find();
|
||||
while (found) {
|
||||
String stringBeforeMatch = path.substring(cursor, matcher.start());
|
||||
builder.append(stringBeforeMatch);
|
||||
|
||||
String group = matcher.group().substring(1, matcher.group().length() - 1);
|
||||
group = camelize(group, true);
|
||||
builder
|
||||
.append("{")
|
||||
.append(group)
|
||||
.append("}");
|
||||
|
||||
cursor = matcher.end();
|
||||
found = matcher.find();
|
||||
}
|
||||
|
||||
String stringAfterMatch = path.substring(cursor);
|
||||
builder.append(stringAfterMatch);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setUnwrapRequired(boolean unwrapRequired) {
|
||||
this.unwrapRequired = unwrapRequired;
|
||||
}
|
||||
|
||||
public void setResponseAs(String[] responseAs) {
|
||||
this.responseAs = responseAs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumDefaultValue(String value, String datatype) {
|
||||
return datatype + "_" + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(name) != null) {
|
||||
return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase()), true);
|
||||
}
|
||||
|
||||
if ("Int".equals(datatype) || "Int32".equals(datatype) || "Int64".equals(datatype) ||
|
||||
"Float".equals(datatype) || "Double".equals(datatype)) {
|
||||
String varName = "number" + camelize(name);
|
||||
varName = varName.replaceAll("-", "minus");
|
||||
varName = varName.replaceAll("\\+", "plus");
|
||||
varName = varName.replaceAll("\\.", "dot");
|
||||
|
||||
return varName;
|
||||
}
|
||||
|
||||
// Prevent from breaking properly cased identifier
|
||||
if (name.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) {
|
||||
return camelize(name, true);
|
||||
}
|
||||
|
||||
char[] separators = {'-', '_', ' ', ':', '(', ')'};
|
||||
return camelize(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators).replaceAll("[-_ :\\(\\)]", ""), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
String enumName = toModelName(property.name);
|
||||
|
||||
// Ensure that the enum type doesn't match a reserved word or
|
||||
// the variable name doesn't match the generated enum type or the
|
||||
// Swift compiler will generate an error
|
||||
if (isReservedWord(property.datatypeWithEnum) || toVarName(property.name).equals(property.datatypeWithEnum)) {
|
||||
enumName = property.datatypeWithEnum + "Enum";
|
||||
}
|
||||
|
||||
// TODO: toModelName already does something for names starting with number, so this code is probably never called
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,6 +41,7 @@ io.swagger.codegen.languages.StaticHtml2Generator
|
||||
io.swagger.codegen.languages.SwaggerGenerator
|
||||
io.swagger.codegen.languages.SwaggerYamlGenerator
|
||||
io.swagger.codegen.languages.SwiftCodegen
|
||||
io.swagger.codegen.languages.Swift3Codegen
|
||||
io.swagger.codegen.languages.TizenClientCodegen
|
||||
io.swagger.codegen.languages.TypeScriptAngular2ClientCodegen
|
||||
io.swagger.codegen.languages.TypeScriptAngularClientCodegen
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// APIHelper.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class APIHelper {
|
||||
static func rejectNil(_ source: [String:Any?]) -> [String:Any]? {
|
||||
var destination = [String:Any]()
|
||||
for (key, nillableValue) in source {
|
||||
if let value: Any = nillableValue {
|
||||
destination[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
if destination.isEmpty {
|
||||
return nil
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
static func convertBoolToString(_ source: [String: Any]?) -> [String:Any]? {
|
||||
guard let source = source else {
|
||||
return nil
|
||||
}
|
||||
var destination = [String:Any]()
|
||||
let theTrue = NSNumber(value: true as Bool)
|
||||
let theFalse = NSNumber(value: false as Bool)
|
||||
for (key, value) in source {
|
||||
switch value {
|
||||
case let x where x as? NSNumber === theTrue || x as? NSNumber === theFalse:
|
||||
destination[key] = "\(value as! Bool)" as Any?
|
||||
default:
|
||||
destination[key] = value
|
||||
}
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// APIs.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class {{projectName}}API {
|
||||
open static var basePath = "{{basePath}}"
|
||||
open static var credential: URLCredential?
|
||||
open static var customHeaders: [String:String] = [:]
|
||||
static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory()
|
||||
}
|
||||
|
||||
open class APIBase {
|
||||
func toParameters(_ encodable: JSONEncodable?) -> [String: Any]? {
|
||||
let encoded: Any? = encodable?.encodeToJSON()
|
||||
|
||||
if encoded! is [Any] {
|
||||
var dictionary = [String:Any]()
|
||||
for (index, item) in (encoded as! [Any]).enumerated() {
|
||||
dictionary["\(index)"] = item
|
||||
}
|
||||
return dictionary
|
||||
} else {
|
||||
return encoded as? [String:Any]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class RequestBuilder<T> {
|
||||
var credential: URLCredential?
|
||||
var headers: [String:String] = [:]
|
||||
let parameters: [String:Any]?
|
||||
let isBody: Bool
|
||||
let method: String
|
||||
let URLString: String
|
||||
|
||||
/// Optional block to obtain a reference to the request's progress instance when available.
|
||||
public var onProgressReady: ((Progress) -> ())?
|
||||
|
||||
required public init(method: String, URLString: String, parameters: [String:Any]?, isBody: Bool) {
|
||||
self.method = method
|
||||
self.URLString = URLString
|
||||
self.parameters = parameters
|
||||
self.isBody = isBody
|
||||
|
||||
addHeaders({{projectName}}API.customHeaders)
|
||||
}
|
||||
|
||||
open func addHeaders(_ aHeaders:[String:String]) {
|
||||
for (header, value) in aHeaders {
|
||||
headers[header] = value
|
||||
}
|
||||
}
|
||||
|
||||
open func execute(_ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) { }
|
||||
|
||||
public func addHeader(name: String, value: String) -> Self {
|
||||
if !value.isEmpty {
|
||||
headers[name] = value
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
open func addCredential() -> Self {
|
||||
self.credential = {{projectName}}API.credential
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
public protocol RequestBuilderFactory {
|
||||
func getBuilder<T>() -> RequestBuilder<T>.Type
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// AlamofireImplementations.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
class AlamofireRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
return AlamofireRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
|
||||
// Store manager to retain its reference
|
||||
private var managerStore: [String: Alamofire.SessionManager] = [:]
|
||||
|
||||
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
required public init(method: String, URLString: String, parameters: [String : Any]?, isBody: Bool) {
|
||||
super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody)
|
||||
}
|
||||
|
||||
/**
|
||||
May be overridden by a subclass if you want to control the session
|
||||
configuration.
|
||||
*/
|
||||
open func createSessionManager() -> Alamofire.SessionManager {
|
||||
let configuration = URLSessionConfiguration.default
|
||||
configuration.httpAdditionalHeaders = buildHeaders()
|
||||
return Alamofire.SessionManager(configuration: configuration)
|
||||
}
|
||||
|
||||
override open func execute(_ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) {
|
||||
let managerId:String = UUID().uuidString
|
||||
// Create a new manager for each request to customize its request header
|
||||
let manager = createSessionManager()
|
||||
managerStore[managerId] = manager
|
||||
|
||||
let encoding:ParameterEncoding = isBody ? JSONEncoding() : URLEncoding()
|
||||
|
||||
let xMethod = Alamofire.HTTPMethod(rawValue: method)
|
||||
let fileKeys = parameters == nil ? [] : parameters!.filter { $1 is NSURL }
|
||||
.map { $0.0 }
|
||||
|
||||
if fileKeys.count > 0 {
|
||||
manager.upload(multipartFormData: { mpForm in
|
||||
for (k, v) in self.parameters! {
|
||||
switch v {
|
||||
case let fileURL as URL:
|
||||
mpForm.append(fileURL, withName: k)
|
||||
break
|
||||
case let string as String:
|
||||
mpForm.append(string.data(using: String.Encoding.utf8)!, withName: k)
|
||||
break
|
||||
case let number as NSNumber:
|
||||
mpForm.append(number.stringValue.data(using: String.Encoding.utf8)!, withName: k)
|
||||
break
|
||||
default:
|
||||
fatalError("Unprocessable value \(v) with key \(k)")
|
||||
break
|
||||
}
|
||||
}
|
||||
}, to: URLString, method: xMethod!, headers: nil, encodingCompletion: { encodingResult in
|
||||
switch encodingResult {
|
||||
case .success(let upload, _, _):
|
||||
if let onProgressReady = self.onProgressReady {
|
||||
onProgressReady(upload.progress)
|
||||
}
|
||||
self.processRequest(request: upload, managerId, completion)
|
||||
case .failure(let encodingError):
|
||||
completion(nil, ErrorResponse.Error(415, nil, encodingError))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let request = manager.request(URLString, method: xMethod!, parameters: parameters, encoding: encoding)
|
||||
if let onProgressReady = self.onProgressReady {
|
||||
onProgressReady(request.progress)
|
||||
}
|
||||
processRequest(request: request, managerId, completion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func processRequest(request: DataRequest, _ managerId: String, _ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) {
|
||||
if let credential = self.credential {
|
||||
request.authenticate(usingCredential: credential)
|
||||
}
|
||||
|
||||
let cleanupRequest = {
|
||||
_ = managerStore.removeValue(forKey: managerId)
|
||||
}
|
||||
|
||||
let validatedRequest = request.validate()
|
||||
|
||||
switch T.self {
|
||||
case is String.Type:
|
||||
validatedRequest.responseString(completionHandler: { (stringResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if stringResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: stringResponse.response!,
|
||||
body: ((stringResponse.result.value ?? "") as! T)
|
||||
),
|
||||
nil
|
||||
)
|
||||
})
|
||||
case is Void.Type:
|
||||
validatedRequest.responseData(completionHandler: { (voidResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if voidResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: voidResponse.response!,
|
||||
body: nil),
|
||||
nil
|
||||
)
|
||||
})
|
||||
case is Data.Type:
|
||||
validatedRequest.responseData(completionHandler: { (dataResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if (dataResponse.result.isFailure) {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: dataResponse.response!,
|
||||
body: (dataResponse.data as! T)
|
||||
),
|
||||
nil
|
||||
)
|
||||
})
|
||||
default:
|
||||
validatedRequest.responseJSON(options: .allowFragments) { response in
|
||||
cleanupRequest()
|
||||
|
||||
if response.result.isFailure {
|
||||
completion(nil, ErrorResponse.Error(response.response?.statusCode ?? 500, response.data, response.result.error!))
|
||||
return
|
||||
}
|
||||
|
||||
if () is T {
|
||||
completion(Response(response: response.response!, body: (() as! T)), nil)
|
||||
return
|
||||
}
|
||||
if let json: Any = response.result.value {
|
||||
let body = Decoders.decode(clazz: T.self, source: json as AnyObject)
|
||||
completion(Response(response: response.response!, body: body), nil)
|
||||
return
|
||||
} else if "" is T {
|
||||
// swagger-parser currently doesn't support void, which will be fixed in future swagger-parser release
|
||||
// https://github.com/swagger-api/swagger-parser/pull/34
|
||||
completion(Response(response: response.response!, body: ("" as! T)), nil)
|
||||
return
|
||||
}
|
||||
|
||||
completion(nil, ErrorResponse.Error(500, nil, NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func buildHeaders() -> [String: String] {
|
||||
var httpHeaders = SessionManager.defaultHTTPHeaders
|
||||
for (key, value) in self.headers {
|
||||
httpHeaders[key] = value
|
||||
}
|
||||
return httpHeaders
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
github "Alamofire/Alamofire" >= 3.1.0{{#usePromiseKit}}
|
||||
github "mxcl/PromiseKit" >=1.5.3{{/usePromiseKit}}{{#useRxSwift}}
|
||||
github "ReactiveX/RxSwift" ~> 2.0{{/useRxSwift}}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Extensions.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire{{#usePromiseKit}}
|
||||
import PromiseKit{{/usePromiseKit}}
|
||||
|
||||
extension Bool: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Float: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Int: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Int32: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return NSNumber(value: self as Int32) }
|
||||
}
|
||||
|
||||
extension Int64: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return NSNumber(value: self as Int64) }
|
||||
}
|
||||
|
||||
extension Double: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension String: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
private func encodeIfPossible<T>(_ object: T) -> Any {
|
||||
if let encodableObject = object as? JSONEncodable {
|
||||
return encodableObject.encodeToJSON()
|
||||
} else {
|
||||
return object as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension Array: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.map(encodeIfPossible)
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
var dictionary = [AnyHashable: Any]()
|
||||
for (key, value) in self {
|
||||
dictionary[key as! NSObject] = encodeIfPossible(value)
|
||||
}
|
||||
return dictionary as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension Data: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.base64EncodedString(options: Data.Base64EncodingOptions())
|
||||
}
|
||||
}
|
||||
|
||||
private let dateFormatter: DateFormatter = {
|
||||
let fmt = DateFormatter()
|
||||
fmt.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
|
||||
fmt.locale = Locale(identifier: "en_US_POSIX")
|
||||
return fmt
|
||||
}()
|
||||
|
||||
extension Date: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return dateFormatter.string(from: self) as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension UUID: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.uuidString
|
||||
}
|
||||
}
|
||||
|
||||
{{#usePromiseKit}}extension RequestBuilder {
|
||||
public func execute() -> Promise<Response<T>> {
|
||||
let deferred = Promise<Response<T>>.pending()
|
||||
self.execute { (response: Response<T>?, error: Error?) in
|
||||
if let response = response {
|
||||
deferred.fulfill(response)
|
||||
} else {
|
||||
deferred.reject(error!)
|
||||
}
|
||||
}
|
||||
return deferred.promise
|
||||
}
|
||||
}{{/usePromiseKit}}
|
||||
@@ -0,0 +1,199 @@
|
||||
// Models.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol JSONEncodable {
|
||||
func encodeToJSON() -> Any
|
||||
}
|
||||
|
||||
public enum ErrorResponse : Error {
|
||||
case Error(Int, Data?, Error)
|
||||
}
|
||||
|
||||
open class Response<T> {
|
||||
open let statusCode: Int
|
||||
open let header: [String: String]
|
||||
open let body: T?
|
||||
|
||||
public init(statusCode: Int, header: [String: String], body: T?) {
|
||||
self.statusCode = statusCode
|
||||
self.header = header
|
||||
self.body = body
|
||||
}
|
||||
|
||||
public convenience init(response: HTTPURLResponse, body: T?) {
|
||||
let rawHeader = response.allHeaderFields
|
||||
var header = [String:String]()
|
||||
for (key, value) in rawHeader {
|
||||
header[key as! String] = value as? String
|
||||
}
|
||||
self.init(statusCode: response.statusCode, header: header, body: body)
|
||||
}
|
||||
}
|
||||
|
||||
private var once = Int()
|
||||
class Decoders {
|
||||
static fileprivate var decoders = Dictionary<String, ((AnyObject) -> AnyObject)>()
|
||||
|
||||
static func addDecoder<T>(clazz: T.Type, decoder: @escaping ((AnyObject) -> T)) {
|
||||
let key = "\(T.self)"
|
||||
decoders[key] = { decoder($0) as AnyObject }
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: [T].Type, source: AnyObject) -> [T] {
|
||||
let array = source as! [AnyObject]
|
||||
return array.map { Decoders.decode(clazz: T.self, source: $0) }
|
||||
}
|
||||
|
||||
static func decode<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject) -> [Key:T] {
|
||||
let sourceDictionary = source as! [Key: AnyObject]
|
||||
var dictionary = [Key:T]()
|
||||
for (key, value) in sourceDictionary {
|
||||
dictionary[key] = Decoders.decode(clazz: T.self, source: value)
|
||||
}
|
||||
return dictionary
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: T.Type, source: AnyObject) -> T {
|
||||
initialize()
|
||||
if T.self is Int32.Type && source is NSNumber {
|
||||
return source.int32Value as! T;
|
||||
}
|
||||
if T.self is Int64.Type && source is NSNumber {
|
||||
return source.int64Value as! T;
|
||||
}
|
||||
if T.self is UUID.Type && source is String {
|
||||
return UUID(uuidString: source as! String) as! T
|
||||
}
|
||||
if source is T {
|
||||
return source as! T
|
||||
}
|
||||
if T.self is Data.Type && source is String {
|
||||
return Data(base64Encoded: source as! String) as! T
|
||||
}
|
||||
|
||||
let key = "\(T.self)"
|
||||
if let decoder = decoders[key] {
|
||||
return decoder(source) as! T
|
||||
} else {
|
||||
fatalError("Source \(source) is not convertible to type \(clazz): Maybe swagger file is insufficient")
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: T.Type, source: AnyObject?) -> T? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (source: AnyObject) -> T in
|
||||
Decoders.decode(clazz: clazz, source: source)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: [T].Type, source: AnyObject?) -> [T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject?) -> [Key:T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [Key:T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
}
|
||||
}
|
||||
|
||||
private static var __once: () = {
|
||||
let formatters = [
|
||||
"yyyy-MM-dd",
|
||||
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS"
|
||||
].map { (format: String) -> DateFormatter in
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = format
|
||||
return formatter
|
||||
}
|
||||
// Decoder for Date
|
||||
Decoders.addDecoder(clazz: Date.self) { (source: AnyObject) -> Date in
|
||||
if let sourceString = source as? String {
|
||||
for formatter in formatters {
|
||||
if let date = formatter.date(from: sourceString) {
|
||||
return date
|
||||
}
|
||||
}
|
||||
}
|
||||
if let sourceInt = source as? Int {
|
||||
// treat as a java date
|
||||
return Date(timeIntervalSince1970: Double(sourceInt / 1000) )
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
} {{#models}}{{#model}}
|
||||
|
||||
// Decoder for [{{{classname}}}]
|
||||
Decoders.addDecoder(clazz: [{{{classname}}}].self) { (source: AnyObject) -> [{{{classname}}}] in
|
||||
return Decoders.decode(clazz: [{{{classname}}}].self, source: source)
|
||||
}
|
||||
// Decoder for {{{classname}}}
|
||||
Decoders.addDecoder(clazz: {{{classname}}}.self) { (source: AnyObject) -> {{{classname}}} in
|
||||
{{#isArrayModel}}
|
||||
let sourceArray = source as! [AnyObject]
|
||||
return sourceArray.map({ Decoders.decode(clazz: {{{arrayModelType}}}.self, source: $0) })
|
||||
{{/isArrayModel}}
|
||||
{{^isArrayModel}}
|
||||
{{#isEnum}}
|
||||
if let source = source as? {{dataType}} {
|
||||
if let result = {{classname}}(rawValue: source) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
fatalError("Source \(source) is not convertible to enum type {{classname}}: Maybe swagger file is insufficient")
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#vars.isEmpty}}
|
||||
if let source = source as? {{dataType}} {
|
||||
return source
|
||||
}
|
||||
fatalError("Source \(source) is not convertible to typealias {{classname}}: Maybe swagger file is insufficient")
|
||||
{{/vars.isEmpty}}
|
||||
{{^vars.isEmpty}}
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
{{#unwrapRequired}}
|
||||
let instance = {{classname}}({{#requiredVars}}{{^-first}}, {{/-first}}{{#isEnum}}{{name}}: {{classname}}.{{datatypeWithEnum}}(rawValue: (sourceDictionary["{{baseName}}"] as! {{datatype}}))! {{/isEnum}}{{^isEnum}}{{name}}: Decoders.decode(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"]! as AnyObject){{/isEnum}}{{/requiredVars}})
|
||||
{{#optionalVars}}{{#isEnum}}
|
||||
if let {{name}} = sourceDictionary["{{baseName}}"] as? {{datatype}} { {{^isContainer}}
|
||||
instance.{{name}} = {{classname}}.{{datatypeWithEnum}}(rawValue: ({{name}})){{/isContainer}}{{#isListContainer}}
|
||||
instance.{{name}} = {{name}}.map ({ {{classname}}.{{enumName}}(rawValue: $0)! }){{/isListContainer}}
|
||||
}{{/isEnum}}{{^isEnum}}
|
||||
instance.{{name}} = Decoders.decodeOptional(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"] as AnyObject?){{/isEnum}}
|
||||
{{/optionalVars}}
|
||||
{{/unwrapRequired}}
|
||||
{{^unwrapRequired}}
|
||||
let instance = {{classname}}(){{#vars}}{{#isEnum}}
|
||||
if let {{name}} = sourceDictionary["{{baseName}}"] as? {{datatype}} { {{^isContainer}}
|
||||
instance.{{name}} = {{classname}}.{{datatypeWithEnum}}(rawValue: ({{name}})){{/isContainer}}{{#isListContainer}}
|
||||
instance.{{name}} = {{name}}.map ({ {{classname}}.{{enumName}}(rawValue: $0)! }){{/isListContainer}}{{#isMapContainer}}//TODO: handle enum map scenario{{/isMapContainer}}
|
||||
}{{/isEnum}}
|
||||
{{^isEnum}}instance.{{name}} = Decoders.decodeOptional(clazz: {{{baseType}}}.self, source: sourceDictionary["{{baseName}}"] as AnyObject?){{/isEnum}}{{/vars}}
|
||||
{{/unwrapRequired}}
|
||||
return instance
|
||||
{{/vars.isEmpty}}
|
||||
{{/isEnum}}
|
||||
{{/isArrayModel}}
|
||||
}{{/model}}
|
||||
{{/models}}
|
||||
}()
|
||||
|
||||
static fileprivate func initialize() {
|
||||
_ = Decoders.__once
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = '{{projectName}}'{{#projectDescription}}
|
||||
s.summary = '{{projectDescription}}'{{/projectDescription}}
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.osx.deployment_target = '10.11'
|
||||
s.version = '{{#podVersion}}{{podVersion}}{{/podVersion}}{{^podVersion}}0.0.1{{/podVersion}}'
|
||||
s.source = {{#podSource}}{{& podSource}}{{/podSource}}{{^podSource}}{ :git => 'git@github.com:swagger-api/swagger-mustache.git', :tag => 'v1.0.0' }{{/podSource}}{{#podAuthors}}
|
||||
s.authors = '{{podAuthors}}'{{/podAuthors}}{{#podSocialMediaURL}}
|
||||
s.social_media_url = '{{podSocialMediaURL}}'{{/podSocialMediaURL}}{{#podDocsetURL}}
|
||||
s.docset_url = '{{podDocsetURL}}'{{/podDocsetURL}}
|
||||
s.license = {{#podLicense}}{{& podLicense}}{{/podLicense}}{{^podLicense}}'Apache License, Version 2.0'{{/podLicense}}{{#podHomepage}}
|
||||
s.homepage = '{{podHomepage}}'{{/podHomepage}}{{#podSummary}}
|
||||
s.summary = '{{podSummary}}'{{/podSummary}}{{#podDescription}}
|
||||
s.description = '{{podDescription}}'{{/podDescription}}{{#podScreenshots}}
|
||||
s.screenshots = {{& podScreenshots}}{{/podScreenshots}}{{#podDocumentationURL}}
|
||||
s.documentation_url = '{{podDocumentationURL}}'{{/podDocumentationURL}}
|
||||
s.source_files = '{{projectName}}/Classes/Swaggers/**/*.swift'{{#usePromiseKit}}
|
||||
s.dependency 'PromiseKit', '~> 4.0'{{/usePromiseKit}}{{#useRxSwift}}
|
||||
s.dependency 'RxSwift', '~> 3.0.0-beta.1'{{/useRxSwift}}
|
||||
s.dependency 'Alamofire', '~> 4.0'
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
"{{baseName}}": {{paramName}}{{#isInteger}}{{^required}}?{{/required}}.encodeToJSON(){{/isInteger}}{{#isLong}}{{^required}}?{{/required}}.encodeToJSON(){{/isLong}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}.rawValue{{/isContainer}}{{/isEnum}}{{#isDate}}{{^required}}?{{/required}}.encodeToJSON(){{/isDate}}{{#isDateTime}}{{^required}}?{{/required}}.encodeToJSON(){{/isDateTime}}
|
||||
132
modules/swagger-codegen/src/main/resources/swift3/api.mustache
Normal file
132
modules/swagger-codegen/src/main/resources/swift3/api.mustache
Normal file
@@ -0,0 +1,132 @@
|
||||
{{#operations}}//
|
||||
// {{classname}}.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire{{#usePromiseKit}}
|
||||
import PromiseKit{{/usePromiseKit}}{{#useRxSwift}}
|
||||
import RxSwift{{/useRxSwift}}
|
||||
|
||||
{{#swiftUseApiNamespace}}
|
||||
extension {{projectName}}API {
|
||||
{{/swiftUseApiNamespace}}
|
||||
|
||||
{{#description}}
|
||||
/** {{description}} */{{/description}}
|
||||
open class {{classname}}: APIBase {
|
||||
{{#operation}}
|
||||
{{#allParams}}
|
||||
{{#isEnum}}
|
||||
/**
|
||||
* enum for parameter {{paramName}}
|
||||
*/
|
||||
public enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}} { {{#allowableValues}}{{#enumVars}}
|
||||
case {{name}} = {{#isContainer}}"{{/isContainer}}{{#isString}}"{{/isString}}{{{value}}}{{#isString}}"{{/isString}}{{#isContainer}}"{{/isContainer}}{{/enumVars}}{{/allowableValues}}
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/allParams}}
|
||||
/**
|
||||
{{#summary}}
|
||||
{{{summary}}}
|
||||
{{/summary}}{{#allParams}}
|
||||
- parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#hasParams}}, {{/hasParams}}completion: @escaping ((_ {{#returnType}}data: {{{returnType}}}?,_ {{/returnType}}error: Error?) -> Void)) {
|
||||
{{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).execute { (response, error) -> Void in
|
||||
completion({{#returnType}}response?.body, {{/returnType}}error);
|
||||
}
|
||||
}
|
||||
|
||||
{{#usePromiseKit}}
|
||||
/**
|
||||
{{#summary}}
|
||||
{{{summary}}}
|
||||
{{/summary}}{{#allParams}}
|
||||
- parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}
|
||||
- returns: Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>
|
||||
*/
|
||||
open class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {
|
||||
let deferred = Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.pending()
|
||||
{{operationId}}({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { {{#returnType}}data, {{/returnType}}error in
|
||||
if let error = error {
|
||||
deferred.reject(error)
|
||||
} else {
|
||||
deferred.fulfill({{#returnType}}data!{{/returnType}})
|
||||
}
|
||||
}
|
||||
return deferred.promise
|
||||
}
|
||||
{{/usePromiseKit}}
|
||||
{{#useRxSwift}}
|
||||
/**
|
||||
{{#summary}}
|
||||
{{{summary}}}
|
||||
{{/summary}}{{#allParams}}
|
||||
- parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}
|
||||
- returns: Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>
|
||||
*/
|
||||
open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {
|
||||
return Observable.create { observer -> Disposable in
|
||||
{{operationId}}({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { {{#returnType}}data, {{/returnType}}error in
|
||||
if let error = error {
|
||||
observer.on(.error(error as Error))
|
||||
} else {
|
||||
observer.on(.next({{#returnType}}data!{{/returnType}}))
|
||||
}
|
||||
observer.on(.completed)
|
||||
}
|
||||
return NopDisposable.instance
|
||||
}
|
||||
}
|
||||
{{/useRxSwift}}
|
||||
|
||||
/**
|
||||
{{#summary}}
|
||||
{{{summary}}}
|
||||
{{/summary}}
|
||||
- {{httpMethod}} {{path}}{{#notes}}
|
||||
- {{{notes}}}{{/notes}}{{#subresourceOperation}}
|
||||
- subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}}
|
||||
- defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}}
|
||||
- {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}:
|
||||
- type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}}
|
||||
- name: {{name}}{{/authMethods}}{{#responseHeaders}}
|
||||
- responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}}
|
||||
- examples: {{{examples}}}{{/examples}}{{#externalDocs}}
|
||||
- externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}}
|
||||
{{/hasParams}}{{#allParams}}
|
||||
- parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}
|
||||
|
||||
- returns: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{description}}
|
||||
*/
|
||||
open class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {
|
||||
{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{^secondaryParam}}var{{/secondaryParam}}{{/pathParams}} path = "{{path}}"{{#pathParams}}
|
||||
path = path.replacingOccurrences(of: "{{=<% %>=}}{<%paramName%>}<%={{ }}=%>", with: "\({{paramName}}{{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}})", options: .literal, range: nil){{/pathParams}}
|
||||
let URLString = {{projectName}}API.basePath + path
|
||||
{{#bodyParam}}
|
||||
let parameters = {{paramName}}{{^required}}?{{/required}}.encodeToJSON() as? [String:AnyObject]{{/bodyParam}}{{^bodyParam}}
|
||||
let nillableParameters: [String:Any?] = {{^queryParams}}{{^formParams}}[:]{{/formParams}}{{#formParams}}{{^secondaryParam}}[{{/secondaryParam}}
|
||||
{{> _param}}{{#hasMore}},{{/hasMore}}{{^hasMore}}
|
||||
]{{/hasMore}}{{/formParams}}{{/queryParams}}{{#queryParams}}{{^secondaryParam}}[{{/secondaryParam}}
|
||||
{{> _param}}{{#hasMore}},{{/hasMore}}{{^hasMore}}
|
||||
]{{/hasMore}}{{/queryParams}}
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters){{/bodyParam}}
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "{{httpMethod}}", URLString: URLString, parameters: convertedParameters, isBody: {{^queryParams}}{{^formParams}}true{{/formParams}}{{/queryParams}}{{#queryParams}}{{^formParams}}{{^secondaryParam}}false{{/secondaryParam}}{{/formParams}}{{/queryParams}}{{#formParams}}{{^secondaryParam}}false{{/secondaryParam}}{{/formParams}})
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
{{#swiftUseApiNamespace}}
|
||||
}
|
||||
{{/swiftUseApiNamespace}}
|
||||
{{/operations}}
|
||||
52
modules/swagger-codegen/src/main/resources/swift3/git_push.sh.mustache
Executable file
52
modules/swagger-codegen/src/main/resources/swift3/git_push.sh.mustache
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||
#
|
||||
# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update"
|
||||
|
||||
git_user_id=$1
|
||||
git_repo_id=$2
|
||||
release_note=$3
|
||||
|
||||
if [ "$git_user_id" = "" ]; then
|
||||
git_user_id="{{{gitUserId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||
fi
|
||||
|
||||
if [ "$git_repo_id" = "" ]; then
|
||||
git_repo_id="{{{gitRepoId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||
fi
|
||||
|
||||
if [ "$release_note" = "" ]; then
|
||||
release_note="{{{releaseNote}}}"
|
||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||
fi
|
||||
|
||||
# Initialize the local directory as a Git repository
|
||||
git init
|
||||
|
||||
# Adds the files in the local repository and stages them for commit.
|
||||
git add .
|
||||
|
||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||
git commit -m "$release_note"
|
||||
|
||||
# Sets the new remote
|
||||
git_remote=`git remote`
|
||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||
|
||||
if [ "$GIT_TOKEN" = "" ]; then
|
||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git crediential in your environment."
|
||||
git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git
|
||||
else
|
||||
git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
git pull origin master
|
||||
|
||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||
echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git"
|
||||
git push origin master 2>&1 | grep -v 'To https'
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/screenshots
|
||||
@@ -0,0 +1,77 @@
|
||||
{{#models}}{{#model}}//
|
||||
// {{classname}}.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
{{#description}}
|
||||
|
||||
/** {{description}} */{{/description}}
|
||||
{{#isArrayModel}}
|
||||
public typealias {{classname}} = [{{arrayModelType}}]
|
||||
{{/isArrayModel}}
|
||||
{{^isArrayModel}}
|
||||
{{#isEnum}}
|
||||
public enum {{classname}}: {{dataType}} {
|
||||
{{#allowableValues}}{{#enumVars}} case {{name}} = "{{{value}}}"
|
||||
{{/enumVars}}{{/allowableValues}}
|
||||
func encodeToJSON() -> Any { return self.rawValue }
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#vars.isEmpty}}
|
||||
public typealias {{classname}} = {{dataType}}
|
||||
{{/vars.isEmpty}}
|
||||
{{^vars.isEmpty}}
|
||||
open class {{classname}}: JSONEncodable {
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
public enum {{enumName}}: {{^isContainer}}{{datatype}}{{/isContainer}}{{#isContainer}}String{{/isContainer}} { {{#allowableValues}}{{#enumVars}}
|
||||
case {{name}} = {{#isContainer}}"{{/isContainer}}{{#isString}}"{{/isString}}{{{value}}}{{#isString}}"{{/isString}}{{#isContainer}}"{{/isContainer}}{{/enumVars}}{{/allowableValues}}
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
{{#description}}/** {{description}} */
|
||||
{{/description}}public var {{name}}: {{{datatypeWithEnum}}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/** {{description}} */
|
||||
{{/description}}public var {{name}}: {{{datatype}}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
|
||||
{{^unwrapRequired}}
|
||||
public init() {}
|
||||
{{/unwrapRequired}}
|
||||
{{#unwrapRequired}}
|
||||
public init({{#allVars}}{{^-first}}, {{/-first}}{{name}}: {{#isEnum}}{{datatypeWithEnum}}{{/isEnum}}{{^isEnum}}{{datatype}}{{/isEnum}}{{^required}}?=nil{{/required}}{{/allVars}}) {
|
||||
{{#allVars}}
|
||||
self.{{name}} = {{name}}
|
||||
{{/allVars}}
|
||||
}
|
||||
{{/unwrapRequired}}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?](){{#vars}}{{#isNotContainer}}{{#isPrimitiveType}}{{^isEnum}}{{#isInteger}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.encodeToJSON(){{/isInteger}}{{#isLong}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.encodeToJSON(){{/isLong}}{{^isLong}}{{^isInteger}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{/isInteger}}{{/isLong}}{{/isEnum}}{{/isPrimitiveType}}{{#isEnum}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.rawValue{{/isEnum}}{{^isPrimitiveType}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.encodeToJSON(){{/isPrimitiveType}}{{/isNotContainer}}{{#isContainer}}{{^isEnum}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.encodeToJSON(){{/isEnum}}{{#isEnum}}{{#isListContainer}}
|
||||
nillableDictionary["{{baseName}}"] = self.{{name}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}.map({$0.rawValue}).encodeToJSON(){{/isListContainer}}{{#isMapContainer}}//TODO: handle enum map scenario{{/isMapContainer}}{{/isEnum}}{{/isContainer}}{{/vars}}
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
{{/vars.isEmpty}}
|
||||
{{/isEnum}}
|
||||
{{/isArrayModel}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
@@ -0,0 +1,63 @@
|
||||
package io.swagger.codegen.options;
|
||||
|
||||
import io.swagger.codegen.CodegenConstants;
|
||||
import io.swagger.codegen.languages.Swift3Codegen;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Swift3OptionsProvider implements OptionsProvider {
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
|
||||
public static final String PROJECT_NAME_VALUE = "Swagger";
|
||||
public static final String RESPONSE_AS_VALUE = "test";
|
||||
public static final String UNWRAP_REQUIRED_VALUE = "true";
|
||||
public static final String POD_SOURCE_VALUE = "{ :git => 'git@github.com:swagger-api/swagger-mustache.git'," +
|
||||
" :tag => 'v1.0.0-SNAPSHOT' }";
|
||||
public static final String POD_VERSION_VALUE = "v1.0.0-SNAPSHOT";
|
||||
public static final String POD_AUTHORS_VALUE = "podAuthors";
|
||||
public static final String POD_SOCIAL_MEDIA_URL_VALUE = "podSocialMediaURL";
|
||||
public static final String POD_DOCSET_URL_VALUE = "podDocsetURL";
|
||||
public static final String POD_LICENSE_VALUE = "'Apache License, Version 2.0'";
|
||||
public static final String POD_HOMEPAGE_VALUE = "podHomepage";
|
||||
public static final String POD_SUMMARY_VALUE = "podSummary";
|
||||
public static final String POD_DESCRIPTION_VALUE = "podDescription";
|
||||
public static final String POD_SCREENSHOTS_VALUE = "podScreenshots";
|
||||
public static final String POD_DOCUMENTATION_URL_VALUE = "podDocumentationURL";
|
||||
public static final String SWIFT_USE_API_NAMESPACE_VALUE = "swiftUseApiNamespace";
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "swift";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> createOptions() {
|
||||
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
|
||||
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
|
||||
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
|
||||
.put(Swift3Codegen.PROJECT_NAME, PROJECT_NAME_VALUE)
|
||||
.put(Swift3Codegen.RESPONSE_AS, RESPONSE_AS_VALUE)
|
||||
.put(Swift3Codegen.UNWRAP_REQUIRED, UNWRAP_REQUIRED_VALUE)
|
||||
.put(Swift3Codegen.POD_SOURCE, POD_SOURCE_VALUE)
|
||||
.put(CodegenConstants.POD_VERSION, POD_VERSION_VALUE)
|
||||
.put(Swift3Codegen.POD_AUTHORS, POD_AUTHORS_VALUE)
|
||||
.put(Swift3Codegen.POD_SOCIAL_MEDIA_URL, POD_SOCIAL_MEDIA_URL_VALUE)
|
||||
.put(Swift3Codegen.POD_DOCSET_URL, POD_DOCSET_URL_VALUE)
|
||||
.put(Swift3Codegen.POD_LICENSE, POD_LICENSE_VALUE)
|
||||
.put(Swift3Codegen.POD_HOMEPAGE, POD_HOMEPAGE_VALUE)
|
||||
.put(Swift3Codegen.POD_SUMMARY, POD_SUMMARY_VALUE)
|
||||
.put(Swift3Codegen.POD_DESCRIPTION, POD_DESCRIPTION_VALUE)
|
||||
.put(Swift3Codegen.POD_SCREENSHOTS, POD_SCREENSHOTS_VALUE)
|
||||
.put(Swift3Codegen.POD_DOCUMENTATION_URL, POD_DOCUMENTATION_URL_VALUE)
|
||||
.put(Swift3Codegen.SWIFT_USE_API_NAMESPACE, SWIFT_USE_API_NAMESPACE_VALUE)
|
||||
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package io.swagger.codegen.swift3;
|
||||
|
||||
import io.swagger.codegen.CodegenOperation;
|
||||
import io.swagger.codegen.DefaultCodegen;
|
||||
import io.swagger.codegen.languages.Swift3Codegen;
|
||||
import io.swagger.models.Operation;
|
||||
import io.swagger.models.Swagger;
|
||||
import io.swagger.parser.SwaggerParser;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class Swift3CodegenTest {
|
||||
|
||||
Swift3Codegen swiftCodegen = new Swift3Codegen();
|
||||
|
||||
@Test
|
||||
public void shouldNotBreakCorrectName() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("EntryName", null), "entryName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleWordAllCaps() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("VALUE", null), "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleWordLowercase() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("value", null), "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCapitalsWithUnderscore() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("ENTRY_NAME", null), "entryName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCapitalsWithDash() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("ENTRY-NAME", null), "entryName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCapitalsWithSpace() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("ENTRY NAME", null), "entryName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowercaseWithUnderscore() throws Exception {
|
||||
Assert.assertEquals(swiftCodegen.toEnumVarName("entry_name", null), "entryName");
|
||||
}
|
||||
|
||||
@Test(description = "returns NSData when response format is binary")
|
||||
public void binaryDataTest() {
|
||||
final Swagger model = new SwaggerParser().read("src/test/resources/2_0/binaryDataTest.json");
|
||||
final DefaultCodegen codegen = new Swift3Codegen();
|
||||
final String path = "/tests/binaryResponse";
|
||||
final Operation p = model.getPaths().get(path).getPost();
|
||||
final CodegenOperation op = codegen.fromOperation(path, "post", p, model.getDefinitions());
|
||||
|
||||
Assert.assertEquals(op.returnType, "Data");
|
||||
Assert.assertEquals(op.bodyParam.dataType, "Data");
|
||||
Assert.assertTrue(op.bodyParam.isBinary);
|
||||
Assert.assertTrue(op.responses.get(0).isBinary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultPodAuthors() throws Exception {
|
||||
// Given
|
||||
|
||||
// When
|
||||
swiftCodegen.processOpts();
|
||||
|
||||
// Then
|
||||
final String podAuthors = (String) swiftCodegen.additionalProperties().get(Swift3Codegen.POD_AUTHORS);
|
||||
Assert.assertEquals(podAuthors, Swift3Codegen.DEFAULT_POD_AUTHORS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPodAuthors() throws Exception {
|
||||
// Given
|
||||
final String swaggerDevs = "Swagger Devs";
|
||||
swiftCodegen.additionalProperties().put(Swift3Codegen.POD_AUTHORS, swaggerDevs);
|
||||
|
||||
// When
|
||||
swiftCodegen.processOpts();
|
||||
|
||||
// Then
|
||||
final String podAuthors = (String) swiftCodegen.additionalProperties().get(Swift3Codegen.POD_AUTHORS);
|
||||
Assert.assertEquals(podAuthors, swaggerDevs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package io.swagger.codegen.swift3;
|
||||
|
||||
import io.swagger.codegen.CodegenModel;
|
||||
import io.swagger.codegen.CodegenProperty;
|
||||
import io.swagger.codegen.DefaultCodegen;
|
||||
import io.swagger.codegen.languages.Swift3Codegen;
|
||||
import io.swagger.models.Model;
|
||||
import io.swagger.models.ModelImpl;
|
||||
import io.swagger.models.properties.*;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public class Swift3ModelTest {
|
||||
|
||||
@Test(description = "convert a simple java model")
|
||||
public void simpleModelTest() {
|
||||
final Model model = new ModelImpl()
|
||||
.description("a sample model")
|
||||
.property("id", new LongProperty())
|
||||
.property("name", new StringProperty())
|
||||
.property("createdAt", new DateTimeProperty())
|
||||
.property("binary", new BinaryProperty())
|
||||
.property("byte", new ByteArrayProperty())
|
||||
.property("uuid", new UUIDProperty())
|
||||
.required("id")
|
||||
.required("name")
|
||||
.discriminator("test");
|
||||
final DefaultCodegen codegen = new Swift3Codegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 6);
|
||||
Assert.assertEquals(cm.discriminator,"test");
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "id");
|
||||
Assert.assertEquals(property1.datatype, "Int64");
|
||||
Assert.assertEquals(property1.name, "id");
|
||||
Assert.assertNull(property1.defaultValue);
|
||||
Assert.assertEquals(property1.baseType, "Int64");
|
||||
Assert.assertTrue(property1.hasMore);
|
||||
Assert.assertTrue(property1.required);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
|
||||
final CodegenProperty property2 = cm.vars.get(1);
|
||||
Assert.assertEquals(property2.baseName, "name");
|
||||
Assert.assertEquals(property2.datatype, "String");
|
||||
Assert.assertEquals(property2.name, "name");
|
||||
Assert.assertNull(property2.defaultValue);
|
||||
Assert.assertEquals(property2.baseType, "String");
|
||||
Assert.assertTrue(property2.hasMore);
|
||||
Assert.assertTrue(property2.required);
|
||||
Assert.assertTrue(property2.isPrimitiveType);
|
||||
Assert.assertTrue(property2.isNotContainer);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.datatype, "Date");
|
||||
Assert.assertEquals(property3.name, "createdAt");
|
||||
Assert.assertNull(property3.defaultValue);
|
||||
Assert.assertEquals(property3.baseType, "Date");
|
||||
Assert.assertTrue(property3.hasMore);
|
||||
Assert.assertNull(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
|
||||
final CodegenProperty property4 = cm.vars.get(3);
|
||||
Assert.assertEquals(property4.baseName, "binary");
|
||||
Assert.assertEquals(property4.datatype, "Data");
|
||||
Assert.assertEquals(property4.name, "binary");
|
||||
Assert.assertNull(property4.defaultValue);
|
||||
Assert.assertEquals(property4.baseType, "Data");
|
||||
Assert.assertTrue(property4.hasMore);
|
||||
Assert.assertNull(property4.required);
|
||||
Assert.assertTrue(property4.isNotContainer);
|
||||
|
||||
final CodegenProperty property5 = cm.vars.get(4);
|
||||
Assert.assertEquals(property5.baseName, "byte");
|
||||
Assert.assertEquals(property5.datatype, "Data");
|
||||
Assert.assertEquals(property5.name, "byte");
|
||||
Assert.assertNull(property5.defaultValue);
|
||||
Assert.assertEquals(property5.baseType, "Data");
|
||||
Assert.assertTrue(property5.hasMore);
|
||||
Assert.assertNull(property5.required);
|
||||
Assert.assertTrue(property5.isNotContainer);
|
||||
|
||||
final CodegenProperty property6 = cm.vars.get(5);
|
||||
Assert.assertEquals(property6.baseName, "uuid");
|
||||
Assert.assertEquals(property6.datatype, "UUID");
|
||||
Assert.assertEquals(property6.name, "uuid");
|
||||
Assert.assertNull(property6.defaultValue);
|
||||
Assert.assertEquals(property6.baseType, "UUID");
|
||||
Assert.assertNull(property6.hasMore);
|
||||
Assert.assertNull(property6.required);
|
||||
Assert.assertTrue(property6.isNotContainer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.swagger.codegen.swift3;
|
||||
|
||||
import io.swagger.codegen.AbstractOptionsTest;
|
||||
import io.swagger.codegen.CodegenConfig;
|
||||
import io.swagger.codegen.languages.Swift3Codegen;
|
||||
import io.swagger.codegen.options.Swift3OptionsProvider;
|
||||
import mockit.Expectations;
|
||||
import mockit.Tested;
|
||||
|
||||
public class Swift3OptionsTest extends AbstractOptionsTest {
|
||||
|
||||
@Tested
|
||||
private Swift3Codegen clientCodegen;
|
||||
|
||||
public Swift3OptionsTest() {
|
||||
super(new Swift3OptionsProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CodegenConfig getCodegenConfig() {
|
||||
return clientCodegen;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void setExpectations() {
|
||||
new Expectations(clientCodegen) {{
|
||||
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(Swift3OptionsProvider.SORT_PARAMS_VALUE));
|
||||
times = 1;
|
||||
clientCodegen.setProjectName(Swift3OptionsProvider.PROJECT_NAME_VALUE);
|
||||
times = 1;
|
||||
clientCodegen.setResponseAs(Swift3OptionsProvider.RESPONSE_AS_VALUE.split(","));
|
||||
times = 1;
|
||||
clientCodegen.setUnwrapRequired(Boolean.valueOf(Swift3OptionsProvider.UNWRAP_REQUIRED_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
}
|
||||
}
|
||||
63
samples/client/petstore/swift3/.gitignore
vendored
Normal file
63
samples/client/petstore/swift3/.gitignore
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/screenshots
|
||||
23
samples/client/petstore/swift3/.swagger-codegen-ignore
Normal file
23
samples/client/petstore/swift3/.swagger-codegen-ignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# Swagger Codegen Ignore
|
||||
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
63
samples/client/petstore/swift3/default/.gitignore
vendored
Normal file
63
samples/client/petstore/swift3/default/.gitignore
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
# Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/screenshots
|
||||
@@ -0,0 +1,23 @@
|
||||
# Swagger Codegen Ignore
|
||||
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
1
samples/client/petstore/swift3/default/Cartfile
Normal file
1
samples/client/petstore/swift3/default/Cartfile
Normal file
@@ -0,0 +1 @@
|
||||
github "Alamofire/Alamofire" >= 3.1.0
|
||||
201
samples/client/petstore/swift3/default/LICENSE
Normal file
201
samples/client/petstore/swift3/default/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,13 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'PetstoreClient'
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.osx.deployment_target = '10.11'
|
||||
s.version = '0.0.1'
|
||||
s.source = { :git => 'git@github.com:swagger-api/swagger-mustache.git', :tag => 'v1.0.0' }
|
||||
s.authors = ''
|
||||
s.license = 'Apache License, Version 2.0'
|
||||
s.homepage = 'https://github.com/swagger-api/swagger-codegen'
|
||||
s.summary = 'PetstoreClient'
|
||||
s.source_files = 'PetstoreClient/Classes/Swaggers/**/*.swift'
|
||||
s.dependency 'Alamofire', '~> 4.0'
|
||||
end
|
||||
@@ -0,0 +1,42 @@
|
||||
// APIHelper.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class APIHelper {
|
||||
static func rejectNil(_ source: [String:Any?]) -> [String:Any]? {
|
||||
var destination = [String:Any]()
|
||||
for (key, nillableValue) in source {
|
||||
if let value: Any = nillableValue {
|
||||
destination[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
if destination.isEmpty {
|
||||
return nil
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
static func convertBoolToString(_ source: [String: Any]?) -> [String:Any]? {
|
||||
guard let source = source else {
|
||||
return nil
|
||||
}
|
||||
var destination = [String:Any]()
|
||||
let theTrue = NSNumber(value: true as Bool)
|
||||
let theFalse = NSNumber(value: false as Bool)
|
||||
for (key, value) in source {
|
||||
switch value {
|
||||
case let x where x as? NSNumber === theTrue || x as? NSNumber === theFalse:
|
||||
destination[key] = "\(value as! Bool)" as Any?
|
||||
default:
|
||||
destination[key] = value
|
||||
}
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// APIs.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class PetstoreClientAPI {
|
||||
open static var basePath = "http://petstore.swagger.io/v2"
|
||||
open static var credential: URLCredential?
|
||||
open static var customHeaders: [String:String] = [:]
|
||||
static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory()
|
||||
}
|
||||
|
||||
open class APIBase {
|
||||
func toParameters(_ encodable: JSONEncodable?) -> [String: Any]? {
|
||||
let encoded: Any? = encodable?.encodeToJSON()
|
||||
|
||||
if encoded! is [Any] {
|
||||
var dictionary = [String:Any]()
|
||||
for (index, item) in (encoded as! [Any]).enumerated() {
|
||||
dictionary["\(index)"] = item
|
||||
}
|
||||
return dictionary
|
||||
} else {
|
||||
return encoded as? [String:Any]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class RequestBuilder<T> {
|
||||
var credential: URLCredential?
|
||||
var headers: [String:String] = [:]
|
||||
let parameters: [String:Any]?
|
||||
let isBody: Bool
|
||||
let method: String
|
||||
let URLString: String
|
||||
|
||||
/// Optional block to obtain a reference to the request's progress instance when available.
|
||||
public var onProgressReady: ((Progress) -> ())?
|
||||
|
||||
required public init(method: String, URLString: String, parameters: [String:Any]?, isBody: Bool) {
|
||||
self.method = method
|
||||
self.URLString = URLString
|
||||
self.parameters = parameters
|
||||
self.isBody = isBody
|
||||
|
||||
addHeaders(PetstoreClientAPI.customHeaders)
|
||||
}
|
||||
|
||||
open func addHeaders(_ aHeaders:[String:String]) {
|
||||
for (header, value) in aHeaders {
|
||||
headers[header] = value
|
||||
}
|
||||
}
|
||||
|
||||
open func execute(_ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) { }
|
||||
|
||||
public func addHeader(name: String, value: String) -> Self {
|
||||
if !value.isEmpty {
|
||||
headers[name] = value
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
open func addCredential() -> Self {
|
||||
self.credential = PetstoreClientAPI.credential
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
public protocol RequestBuilderFactory {
|
||||
func getBuilder<T>() -> RequestBuilder<T>.Type
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
//
|
||||
// FakeAPI.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
|
||||
|
||||
open class FakeAPI: APIBase {
|
||||
/**
|
||||
To test \"client\" model
|
||||
|
||||
- parameter body: (body) client model
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func testClientModel(body: Client, completion: @escaping ((_ data: Client?,_ error: Error?) -> Void)) {
|
||||
testClientModelWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
To test \"client\" model
|
||||
- PATCH /fake
|
||||
- examples: [{contentType=application/json, example={
|
||||
"client" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter body: (body) client model
|
||||
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
open class func testClientModelWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
|
||||
let path = "/fake"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Client>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "PATCH", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
|
||||
|
||||
- parameter number: (form) None
|
||||
- parameter double: (form) None
|
||||
- parameter patternWithoutDelimiter: (form) None
|
||||
- parameter byte: (form) None
|
||||
- parameter integer: (form) None (optional)
|
||||
- parameter int32: (form) None (optional)
|
||||
- parameter int64: (form) None (optional)
|
||||
- parameter float: (form) None (optional)
|
||||
- parameter string: (form) None (optional)
|
||||
- parameter binary: (form) None (optional)
|
||||
- parameter date: (form) None (optional)
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func testEndpointParameters(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int32? = nil, int32: Int32? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
testEndpointParametersWithRequestBuilder(number: number, double: double, patternWithoutDelimiter: patternWithoutDelimiter, byte: byte, integer: integer, int32: int32, int64: int64, float: float, string: string, binary: binary, date: date, dateTime: dateTime, password: password, callback: callback).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
|
||||
- POST /fake
|
||||
- Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
|
||||
- BASIC:
|
||||
- type: basic
|
||||
- name: http_basic_test
|
||||
|
||||
- parameter number: (form) None
|
||||
- parameter double: (form) None
|
||||
- parameter patternWithoutDelimiter: (form) None
|
||||
- parameter byte: (form) None
|
||||
- parameter integer: (form) None (optional)
|
||||
- parameter int32: (form) None (optional)
|
||||
- parameter int64: (form) None (optional)
|
||||
- parameter float: (form) None (optional)
|
||||
- parameter string: (form) None (optional)
|
||||
- parameter binary: (form) None (optional)
|
||||
- parameter date: (form) None (optional)
|
||||
- parameter dateTime: (form) None (optional)
|
||||
- parameter password: (form) None (optional)
|
||||
- parameter callback: (form) None (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func testEndpointParametersWithRequestBuilder(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int32? = nil, int32: Int32? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil) -> RequestBuilder<Void> {
|
||||
let path = "/fake"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"integer": integer?.encodeToJSON(),
|
||||
"int32": int32?.encodeToJSON(),
|
||||
"int64": int64?.encodeToJSON(),
|
||||
"number": number,
|
||||
"float": float,
|
||||
"double": double,
|
||||
"string": string,
|
||||
"pattern_without_delimiter": patternWithoutDelimiter,
|
||||
"byte": byte,
|
||||
"binary": binary,
|
||||
"date": date?.encodeToJSON(),
|
||||
"dateTime": dateTime?.encodeToJSON(),
|
||||
"password": password,
|
||||
"callback": callback
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
/**
|
||||
* enum for parameter enumFormStringArray
|
||||
*/
|
||||
public enum EnumFormStringArray_testEnumParameters: String {
|
||||
case greaterThan = ">"
|
||||
case dollar = "$"
|
||||
}
|
||||
|
||||
/**
|
||||
* enum for parameter enumFormString
|
||||
*/
|
||||
public enum EnumFormString_testEnumParameters: String {
|
||||
case abc = "_abc"
|
||||
case efg = "-efg"
|
||||
case xyz = "(xyz)"
|
||||
}
|
||||
|
||||
/**
|
||||
* enum for parameter enumQueryStringArray
|
||||
*/
|
||||
public enum EnumQueryStringArray_testEnumParameters: String {
|
||||
case greaterThan = ">"
|
||||
case dollar = "$"
|
||||
}
|
||||
|
||||
/**
|
||||
* enum for parameter enumQueryString
|
||||
*/
|
||||
public enum EnumQueryString_testEnumParameters: String {
|
||||
case abc = "_abc"
|
||||
case efg = "-efg"
|
||||
case xyz = "(xyz)"
|
||||
}
|
||||
|
||||
/**
|
||||
To test enum parameters
|
||||
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to -efg)
|
||||
- parameter enumQueryStringArray: (query) Query parameter enum test (string array) (optional)
|
||||
- parameter enumQueryString: (query) Query parameter enum test (string) (optional, default to -efg)
|
||||
- parameter enumQueryInteger: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumQueryDouble: (form) Query parameter enum test (double) (optional)
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func testEnumParameters(enumFormStringArray: [String]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, enumQueryStringArray: [String]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: Double? = nil, enumQueryDouble: Double? = nil, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
testEnumParametersWithRequestBuilder(enumFormStringArray: enumFormStringArray, enumFormString: enumFormString, enumQueryStringArray: enumQueryStringArray, enumQueryString: enumQueryString, enumQueryInteger: enumQueryInteger, enumQueryDouble: enumQueryDouble).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
To test enum parameters
|
||||
- GET /fake
|
||||
|
||||
- parameter enumFormStringArray: (form) Form parameter enum test (string array) (optional)
|
||||
- parameter enumFormString: (form) Form parameter enum test (string) (optional, default to -efg)
|
||||
- parameter enumQueryStringArray: (query) Query parameter enum test (string array) (optional)
|
||||
- parameter enumQueryString: (query) Query parameter enum test (string) (optional, default to -efg)
|
||||
- parameter enumQueryInteger: (query) Query parameter enum test (double) (optional)
|
||||
- parameter enumQueryDouble: (form) Query parameter enum test (double) (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func testEnumParametersWithRequestBuilder(enumFormStringArray: [String]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, enumQueryStringArray: [String]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: Double? = nil, enumQueryDouble: Double? = nil) -> RequestBuilder<Void> {
|
||||
let path = "/fake"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"enum_query_string_array": enumQueryStringArray,
|
||||
"enum_query_string": enumQueryString?.rawValue,
|
||||
"enum_query_integer": enumQueryInteger
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// FakeclassnametagsAPI.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
|
||||
|
||||
open class FakeclassnametagsAPI: APIBase {
|
||||
/**
|
||||
To test class name in snake case
|
||||
|
||||
- parameter body: (body) client model
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func testClassname(body: Client, completion: @escaping ((_ data: Client?,_ error: Error?) -> Void)) {
|
||||
testClassnameWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
To test class name in snake case
|
||||
- PATCH /fake_classname_test
|
||||
- examples: [{contentType=application/json, example={
|
||||
"client" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter body: (body) client model
|
||||
|
||||
- returns: RequestBuilder<Client>
|
||||
*/
|
||||
open class func testClassnameWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
|
||||
let path = "/fake_classname_test"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Client>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "PATCH", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
//
|
||||
// PetAPI.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
|
||||
|
||||
open class PetAPI: APIBase {
|
||||
/**
|
||||
Add a new pet to the store
|
||||
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func addPet(body: Pet, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
addPetWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add a new pet to the store
|
||||
- POST /pet
|
||||
-
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func addPetWithRequestBuilder(body: Pet) -> RequestBuilder<Void> {
|
||||
let path = "/pet"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Deletes a pet
|
||||
|
||||
- parameter petId: (path) Pet id to delete
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func deletePet(petId: Int64, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
deletePetWithRequestBuilder(petId: petId).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Deletes a pet
|
||||
- DELETE /pet/{petId}
|
||||
-
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
|
||||
- parameter petId: (path) Pet id to delete
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func deletePetWithRequestBuilder(petId: Int64) -> RequestBuilder<Void> {
|
||||
var path = "/pet/{petId}"
|
||||
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "DELETE", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
* enum for parameter status
|
||||
*/
|
||||
public enum Status_findPetsByStatus: String {
|
||||
case available = "available"
|
||||
case pending = "pending"
|
||||
case sold = "sold"
|
||||
}
|
||||
|
||||
/**
|
||||
Finds Pets by status
|
||||
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func findPetsByStatus(status: [String], completion: @escaping ((_ data: [Pet]?,_ error: Error?) -> Void)) {
|
||||
findPetsByStatusWithRequestBuilder(status: status).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Finds Pets by status
|
||||
- GET /pet/findByStatus
|
||||
- Multiple status values can be provided with comma separated strings
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example=[ {
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
} ]}]
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example=[ {
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
} ]}]
|
||||
|
||||
- parameter status: (query) Status values that need to be considered for filter
|
||||
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
open class func findPetsByStatusWithRequestBuilder(status: [String]) -> RequestBuilder<[Pet]> {
|
||||
let path = "/pet/findByStatus"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"status": status
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<[Pet]>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Finds Pets by tags
|
||||
|
||||
- parameter tags: (query) Tags to filter by
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func findPetsByTags(tags: [String], completion: @escaping ((_ data: [Pet]?,_ error: Error?) -> Void)) {
|
||||
findPetsByTagsWithRequestBuilder(tags: tags).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Finds Pets by tags
|
||||
- GET /pet/findByTags
|
||||
- Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example=[ {
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
} ]}]
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example=[ {
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
} ]}]
|
||||
|
||||
- parameter tags: (query) Tags to filter by
|
||||
|
||||
- returns: RequestBuilder<[Pet]>
|
||||
*/
|
||||
open class func findPetsByTagsWithRequestBuilder(tags: [String]) -> RequestBuilder<[Pet]> {
|
||||
let path = "/pet/findByTags"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"tags": tags
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<[Pet]>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Find pet by ID
|
||||
|
||||
- parameter petId: (path) ID of pet to return
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func getPetById(petId: Int64, completion: @escaping ((_ data: Pet?,_ error: Error?) -> Void)) {
|
||||
getPetByIdWithRequestBuilder(petId: petId).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find pet by ID
|
||||
- GET /pet/{petId}
|
||||
- Returns a single pet
|
||||
- API Key:
|
||||
- type: apiKey api_key
|
||||
- name: api_key
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example={
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
- examples: [{contentType=application/xml, example=<Pet>
|
||||
<id>123456</id>
|
||||
<name>doggie</name>
|
||||
<photoUrls>
|
||||
<photoUrls>string</photoUrls>
|
||||
</photoUrls>
|
||||
<tags>
|
||||
</tags>
|
||||
<status>string</status>
|
||||
</Pet>}, {contentType=application/json, example={
|
||||
"photoUrls" : [ "aeiou" ],
|
||||
"name" : "doggie",
|
||||
"id" : 123456789,
|
||||
"category" : {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
},
|
||||
"tags" : [ {
|
||||
"name" : "aeiou",
|
||||
"id" : 123456789
|
||||
} ],
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter petId: (path) ID of pet to return
|
||||
|
||||
- returns: RequestBuilder<Pet>
|
||||
*/
|
||||
open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder<Pet> {
|
||||
var path = "/pet/{petId}"
|
||||
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Pet>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Update an existing pet
|
||||
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func updatePet(body: Pet, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
updatePetWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Update an existing pet
|
||||
- PUT /pet
|
||||
-
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
|
||||
- parameter body: (body) Pet object that needs to be added to the store
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func updatePetWithRequestBuilder(body: Pet) -> RequestBuilder<Void> {
|
||||
let path = "/pet"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "PUT", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Updates a pet in the store with form data
|
||||
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
updatePetWithFormWithRequestBuilder(petId: petId, name: name, status: status).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Updates a pet in the store with form data
|
||||
- POST /pet/{petId}
|
||||
-
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
|
||||
- parameter petId: (path) ID of pet that needs to be updated
|
||||
- parameter name: (form) Updated name of the pet (optional)
|
||||
- parameter status: (form) Updated status of the pet (optional)
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder<Void> {
|
||||
var path = "/pet/{petId}"
|
||||
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"name": name,
|
||||
"status": status
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
/**
|
||||
uploads an image
|
||||
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: URL? = nil, completion: @escaping ((_ data: ApiResponse?,_ error: Error?) -> Void)) {
|
||||
uploadFileWithRequestBuilder(petId: petId, additionalMetadata: additionalMetadata, file: file).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
uploads an image
|
||||
- POST /pet/{petId}/uploadImage
|
||||
-
|
||||
- OAuth:
|
||||
- type: oauth2
|
||||
- name: petstore_auth
|
||||
- examples: [{contentType=application/json, example={
|
||||
"code" : 123,
|
||||
"type" : "aeiou",
|
||||
"message" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter petId: (path) ID of pet to update
|
||||
- parameter additionalMetadata: (form) Additional data to pass to server (optional)
|
||||
- parameter file: (form) file to upload (optional)
|
||||
|
||||
- returns: RequestBuilder<ApiResponse>
|
||||
*/
|
||||
open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: URL? = nil) -> RequestBuilder<ApiResponse> {
|
||||
var path = "/pet/{petId}/uploadImage"
|
||||
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"additionalMetadata": additionalMetadata,
|
||||
"file": file
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<ApiResponse>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
//
|
||||
// StoreAPI.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
|
||||
|
||||
open class StoreAPI: APIBase {
|
||||
/**
|
||||
Delete purchase order by ID
|
||||
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func deleteOrder(orderId: String, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
deleteOrderWithRequestBuilder(orderId: orderId).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Delete purchase order by ID
|
||||
- DELETE /store/order/{orderId}
|
||||
- For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||
|
||||
- parameter orderId: (path) ID of the order that needs to be deleted
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder<Void> {
|
||||
var path = "/store/order/{orderId}"
|
||||
path = path.replacingOccurrences(of: "{orderId}", with: "\(orderId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "DELETE", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns pet inventories by status
|
||||
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func getInventory(completion: @escaping ((_ data: [String:Int32]?,_ error: Error?) -> Void)) {
|
||||
getInventoryWithRequestBuilder().execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Returns pet inventories by status
|
||||
- GET /store/inventory
|
||||
- Returns a map of status codes to quantities
|
||||
- API Key:
|
||||
- type: apiKey api_key
|
||||
- name: api_key
|
||||
- examples: [{contentType=application/json, example={
|
||||
"key" : 123
|
||||
}}]
|
||||
|
||||
- returns: RequestBuilder<[String:Int32]>
|
||||
*/
|
||||
open class func getInventoryWithRequestBuilder() -> RequestBuilder<[String:Int32]> {
|
||||
let path = "/store/inventory"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<[String:Int32]>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Find purchase order by ID
|
||||
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func getOrderById(orderId: Int64, completion: @escaping ((_ data: Order?,_ error: Error?) -> Void)) {
|
||||
getOrderByIdWithRequestBuilder(orderId: orderId).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find purchase order by ID
|
||||
- GET /store/order/{orderId}
|
||||
- For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
|
||||
- examples: [{contentType=application/xml, example=<Order>
|
||||
<id>123456</id>
|
||||
<petId>123456</petId>
|
||||
<quantity>0</quantity>
|
||||
<shipDate>2000-01-23T04:56:07.000Z</shipDate>
|
||||
<status>string</status>
|
||||
<complete>true</complete>
|
||||
</Order>}, {contentType=application/json, example={
|
||||
"petId" : 123456789,
|
||||
"quantity" : 123,
|
||||
"id" : 123456789,
|
||||
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||
"complete" : true,
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
- examples: [{contentType=application/xml, example=<Order>
|
||||
<id>123456</id>
|
||||
<petId>123456</petId>
|
||||
<quantity>0</quantity>
|
||||
<shipDate>2000-01-23T04:56:07.000Z</shipDate>
|
||||
<status>string</status>
|
||||
<complete>true</complete>
|
||||
</Order>}, {contentType=application/json, example={
|
||||
"petId" : 123456789,
|
||||
"quantity" : 123,
|
||||
"id" : 123456789,
|
||||
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||
"complete" : true,
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter orderId: (path) ID of pet that needs to be fetched
|
||||
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder<Order> {
|
||||
var path = "/store/order/{orderId}"
|
||||
path = path.replacingOccurrences(of: "{orderId}", with: "\(orderId)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Order>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Place an order for a pet
|
||||
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func placeOrder(body: Order, completion: @escaping ((_ data: Order?,_ error: Error?) -> Void)) {
|
||||
placeOrderWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Place an order for a pet
|
||||
- POST /store/order
|
||||
-
|
||||
- examples: [{contentType=application/xml, example=<Order>
|
||||
<id>123456</id>
|
||||
<petId>123456</petId>
|
||||
<quantity>0</quantity>
|
||||
<shipDate>2000-01-23T04:56:07.000Z</shipDate>
|
||||
<status>string</status>
|
||||
<complete>true</complete>
|
||||
</Order>}, {contentType=application/json, example={
|
||||
"petId" : 123456789,
|
||||
"quantity" : 123,
|
||||
"id" : 123456789,
|
||||
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||
"complete" : true,
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
- examples: [{contentType=application/xml, example=<Order>
|
||||
<id>123456</id>
|
||||
<petId>123456</petId>
|
||||
<quantity>0</quantity>
|
||||
<shipDate>2000-01-23T04:56:07.000Z</shipDate>
|
||||
<status>string</status>
|
||||
<complete>true</complete>
|
||||
</Order>}, {contentType=application/json, example={
|
||||
"petId" : 123456789,
|
||||
"quantity" : 123,
|
||||
"id" : 123456789,
|
||||
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||
"complete" : true,
|
||||
"status" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter body: (body) order placed for purchasing the pet
|
||||
|
||||
- returns: RequestBuilder<Order>
|
||||
*/
|
||||
open class func placeOrderWithRequestBuilder(body: Order) -> RequestBuilder<Order> {
|
||||
let path = "/store/order"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Order>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
//
|
||||
// UserAPI.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
|
||||
|
||||
open class UserAPI: APIBase {
|
||||
/**
|
||||
Create user
|
||||
|
||||
- parameter body: (body) Created user object
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func createUser(body: User, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
createUserWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create user
|
||||
- POST /user
|
||||
- This can only be done by the logged in user.
|
||||
|
||||
- parameter body: (body) Created user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func createUserWithRequestBuilder(body: User) -> RequestBuilder<Void> {
|
||||
let path = "/user"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates list of users with given input array
|
||||
|
||||
- parameter body: (body) List of user object
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func createUsersWithArrayInput(body: [User], completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
createUsersWithArrayInputWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithArray
|
||||
-
|
||||
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func createUsersWithArrayInputWithRequestBuilder(body: [User]) -> RequestBuilder<Void> {
|
||||
let path = "/user/createWithArray"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates list of users with given input array
|
||||
|
||||
- parameter body: (body) List of user object
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func createUsersWithListInput(body: [User], completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
createUsersWithListInputWithRequestBuilder(body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates list of users with given input array
|
||||
- POST /user/createWithList
|
||||
-
|
||||
|
||||
- parameter body: (body) List of user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func createUsersWithListInputWithRequestBuilder(body: [User]) -> RequestBuilder<Void> {
|
||||
let path = "/user/createWithList"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "POST", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Delete user
|
||||
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func deleteUser(username: String, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
deleteUserWithRequestBuilder(username: username).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Delete user
|
||||
- DELETE /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
|
||||
- parameter username: (path) The name that needs to be deleted
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder<Void> {
|
||||
var path = "/user/{username}"
|
||||
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "DELETE", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Get user by user name
|
||||
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func getUserByName(username: String, completion: @escaping ((_ data: User?,_ error: Error?) -> Void)) {
|
||||
getUserByNameWithRequestBuilder(username: username).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get user by user name
|
||||
- GET /user/{username}
|
||||
-
|
||||
- examples: [{contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
<password>string</password>
|
||||
<phone>string</phone>
|
||||
<userStatus>0</userStatus>
|
||||
</User>}, {contentType=application/json, example={
|
||||
"firstName" : "aeiou",
|
||||
"lastName" : "aeiou",
|
||||
"password" : "aeiou",
|
||||
"userStatus" : 123,
|
||||
"phone" : "aeiou",
|
||||
"id" : 123456789,
|
||||
"email" : "aeiou",
|
||||
"username" : "aeiou"
|
||||
}}]
|
||||
- examples: [{contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
<password>string</password>
|
||||
<phone>string</phone>
|
||||
<userStatus>0</userStatus>
|
||||
</User>}, {contentType=application/json, example={
|
||||
"firstName" : "aeiou",
|
||||
"lastName" : "aeiou",
|
||||
"password" : "aeiou",
|
||||
"userStatus" : 123,
|
||||
"phone" : "aeiou",
|
||||
"id" : 123456789,
|
||||
"email" : "aeiou",
|
||||
"username" : "aeiou"
|
||||
}}]
|
||||
|
||||
- parameter username: (path) The name that needs to be fetched. Use user1 for testing.
|
||||
|
||||
- returns: RequestBuilder<User>
|
||||
*/
|
||||
open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder<User> {
|
||||
var path = "/user/{username}"
|
||||
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<User>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Logs user into the system
|
||||
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func loginUser(username: String, password: String, completion: @escaping ((_ data: String?,_ error: Error?) -> Void)) {
|
||||
loginUserWithRequestBuilder(username: username, password: password).execute { (response, error) -> Void in
|
||||
completion(response?.body, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Logs user into the system
|
||||
- GET /user/login
|
||||
-
|
||||
- responseHeaders: [X-Rate-Limit(Int32), X-Expires-After(Date)]
|
||||
- responseHeaders: [X-Rate-Limit(Int32), X-Expires-After(Date)]
|
||||
- examples: [{contentType=application/xml, example=string}, {contentType=application/json, example="aeiou"}]
|
||||
- examples: [{contentType=application/xml, example=string}, {contentType=application/json, example="aeiou"}]
|
||||
|
||||
- parameter username: (query) The user name for login
|
||||
- parameter password: (query) The password for login in clear text
|
||||
|
||||
- returns: RequestBuilder<String>
|
||||
*/
|
||||
open class func loginUserWithRequestBuilder(username: String, password: String) -> RequestBuilder<String> {
|
||||
let path = "/user/login"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [
|
||||
"username": username,
|
||||
"password": password
|
||||
]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<String>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: false)
|
||||
}
|
||||
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func logoutUser(completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
logoutUserWithRequestBuilder().execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Logs out current logged in user session
|
||||
- GET /user/logout
|
||||
-
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func logoutUserWithRequestBuilder() -> RequestBuilder<Void> {
|
||||
let path = "/user/logout"
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
|
||||
let nillableParameters: [String:Any?] = [:]
|
||||
|
||||
let parameters = APIHelper.rejectNil(nillableParameters)
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "GET", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
/**
|
||||
Updated user
|
||||
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
- parameter completion: completion handler to receive the data and the error objects
|
||||
*/
|
||||
open class func updateUser(username: String, body: User, completion: @escaping ((_ error: Error?) -> Void)) {
|
||||
updateUserWithRequestBuilder(username: username, body: body).execute { (response, error) -> Void in
|
||||
completion(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Updated user
|
||||
- PUT /user/{username}
|
||||
- This can only be done by the logged in user.
|
||||
|
||||
- parameter username: (path) name that need to be deleted
|
||||
- parameter body: (body) Updated user object
|
||||
|
||||
- returns: RequestBuilder<Void>
|
||||
*/
|
||||
open class func updateUserWithRequestBuilder(username: String, body: User) -> RequestBuilder<Void> {
|
||||
var path = "/user/{username}"
|
||||
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
|
||||
let URLString = PetstoreClientAPI.basePath + path
|
||||
let parameters = body.encodeToJSON() as? [String:AnyObject]
|
||||
|
||||
let convertedParameters = APIHelper.convertBoolToString(parameters)
|
||||
|
||||
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getBuilder()
|
||||
|
||||
return requestBuilder.init(method: "PUT", URLString: URLString, parameters: convertedParameters, isBody: true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// AlamofireImplementations.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
class AlamofireRequestBuilderFactory: RequestBuilderFactory {
|
||||
func getBuilder<T>() -> RequestBuilder<T>.Type {
|
||||
return AlamofireRequestBuilder<T>.self
|
||||
}
|
||||
}
|
||||
|
||||
// Store manager to retain its reference
|
||||
private var managerStore: [String: Alamofire.SessionManager] = [:]
|
||||
|
||||
open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
|
||||
required public init(method: String, URLString: String, parameters: [String : Any]?, isBody: Bool) {
|
||||
super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody)
|
||||
}
|
||||
|
||||
/**
|
||||
May be overridden by a subclass if you want to control the session
|
||||
configuration.
|
||||
*/
|
||||
open func createSessionManager() -> Alamofire.SessionManager {
|
||||
let configuration = URLSessionConfiguration.default
|
||||
configuration.httpAdditionalHeaders = buildHeaders()
|
||||
return Alamofire.SessionManager(configuration: configuration)
|
||||
}
|
||||
|
||||
override open func execute(_ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) {
|
||||
let managerId:String = UUID().uuidString
|
||||
// Create a new manager for each request to customize its request header
|
||||
let manager = createSessionManager()
|
||||
managerStore[managerId] = manager
|
||||
|
||||
let encoding:ParameterEncoding = isBody ? JSONEncoding() : URLEncoding()
|
||||
|
||||
let xMethod = Alamofire.HTTPMethod(rawValue: method)
|
||||
let fileKeys = parameters == nil ? [] : parameters!.filter { $1 is NSURL }
|
||||
.map { $0.0 }
|
||||
|
||||
if fileKeys.count > 0 {
|
||||
manager.upload(multipartFormData: { mpForm in
|
||||
for (k, v) in self.parameters! {
|
||||
switch v {
|
||||
case let fileURL as URL:
|
||||
mpForm.append(fileURL, withName: k)
|
||||
break
|
||||
case let string as String:
|
||||
mpForm.append(string.data(using: String.Encoding.utf8)!, withName: k)
|
||||
break
|
||||
case let number as NSNumber:
|
||||
mpForm.append(number.stringValue.data(using: String.Encoding.utf8)!, withName: k)
|
||||
break
|
||||
default:
|
||||
fatalError("Unprocessable value \(v) with key \(k)")
|
||||
break
|
||||
}
|
||||
}
|
||||
}, to: URLString, method: xMethod!, headers: nil, encodingCompletion: { encodingResult in
|
||||
switch encodingResult {
|
||||
case .success(let upload, _, _):
|
||||
if let onProgressReady = self.onProgressReady {
|
||||
onProgressReady(upload.progress)
|
||||
}
|
||||
self.processRequest(request: upload, managerId, completion)
|
||||
case .failure(let encodingError):
|
||||
completion(nil, ErrorResponse.Error(415, nil, encodingError))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let request = manager.request(URLString, method: xMethod!, parameters: parameters, encoding: encoding)
|
||||
if let onProgressReady = self.onProgressReady {
|
||||
onProgressReady(request.progress)
|
||||
}
|
||||
processRequest(request: request, managerId, completion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func processRequest(request: DataRequest, _ managerId: String, _ completion: @escaping (_ response: Response<T>?, _ error: Error?) -> Void) {
|
||||
if let credential = self.credential {
|
||||
request.authenticate(usingCredential: credential)
|
||||
}
|
||||
|
||||
let cleanupRequest = {
|
||||
_ = managerStore.removeValue(forKey: managerId)
|
||||
}
|
||||
|
||||
let validatedRequest = request.validate()
|
||||
|
||||
switch T.self {
|
||||
case is String.Type:
|
||||
validatedRequest.responseString(completionHandler: { (stringResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if stringResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: stringResponse.response!,
|
||||
body: ((stringResponse.result.value ?? "") as! T)
|
||||
),
|
||||
nil
|
||||
)
|
||||
})
|
||||
case is Void.Type:
|
||||
validatedRequest.responseData(completionHandler: { (voidResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if voidResponse.result.isFailure {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: voidResponse.response!,
|
||||
body: nil),
|
||||
nil
|
||||
)
|
||||
})
|
||||
case is Data.Type:
|
||||
validatedRequest.responseData(completionHandler: { (dataResponse) in
|
||||
cleanupRequest()
|
||||
|
||||
if (dataResponse.result.isFailure) {
|
||||
completion(
|
||||
nil,
|
||||
ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
completion(
|
||||
Response(
|
||||
response: dataResponse.response!,
|
||||
body: (dataResponse.data as! T)
|
||||
),
|
||||
nil
|
||||
)
|
||||
})
|
||||
default:
|
||||
validatedRequest.responseJSON(options: .allowFragments) { response in
|
||||
cleanupRequest()
|
||||
|
||||
if response.result.isFailure {
|
||||
completion(nil, ErrorResponse.Error(response.response?.statusCode ?? 500, response.data, response.result.error!))
|
||||
return
|
||||
}
|
||||
|
||||
if () is T {
|
||||
completion(Response(response: response.response!, body: (() as! T)), nil)
|
||||
return
|
||||
}
|
||||
if let json: Any = response.result.value {
|
||||
let body = Decoders.decode(clazz: T.self, source: json as AnyObject)
|
||||
completion(Response(response: response.response!, body: body), nil)
|
||||
return
|
||||
} else if "" is T {
|
||||
// swagger-parser currently doesn't support void, which will be fixed in future swagger-parser release
|
||||
// https://github.com/swagger-api/swagger-parser/pull/34
|
||||
completion(Response(response: response.response!, body: ("" as! T)), nil)
|
||||
return
|
||||
}
|
||||
|
||||
completion(nil, ErrorResponse.Error(500, nil, NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func buildHeaders() -> [String: String] {
|
||||
var httpHeaders = SessionManager.defaultHTTPHeaders
|
||||
for (key, value) in self.headers {
|
||||
httpHeaders[key] = value
|
||||
}
|
||||
return httpHeaders
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Extensions.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Alamofire
|
||||
|
||||
extension Bool: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Float: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Int: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension Int32: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return NSNumber(value: self as Int32) }
|
||||
}
|
||||
|
||||
extension Int64: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return NSNumber(value: self as Int64) }
|
||||
}
|
||||
|
||||
extension Double: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
extension String: JSONEncodable {
|
||||
func encodeToJSON() -> Any { return self as Any }
|
||||
}
|
||||
|
||||
private func encodeIfPossible<T>(_ object: T) -> Any {
|
||||
if let encodableObject = object as? JSONEncodable {
|
||||
return encodableObject.encodeToJSON()
|
||||
} else {
|
||||
return object as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension Array: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.map(encodeIfPossible)
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
var dictionary = [AnyHashable: Any]()
|
||||
for (key, value) in self {
|
||||
dictionary[key as! NSObject] = encodeIfPossible(value)
|
||||
}
|
||||
return dictionary as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension Data: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.base64EncodedString(options: Data.Base64EncodingOptions())
|
||||
}
|
||||
}
|
||||
|
||||
private let dateFormatter: DateFormatter = {
|
||||
let fmt = DateFormatter()
|
||||
fmt.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
|
||||
fmt.locale = Locale(identifier: "en_US_POSIX")
|
||||
return fmt
|
||||
}()
|
||||
|
||||
extension Date: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return dateFormatter.string(from: self) as Any
|
||||
}
|
||||
}
|
||||
|
||||
extension UUID: JSONEncodable {
|
||||
func encodeToJSON() -> Any {
|
||||
return self.uuidString
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,598 @@
|
||||
// Models.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol JSONEncodable {
|
||||
func encodeToJSON() -> Any
|
||||
}
|
||||
|
||||
public enum ErrorResponse : Error {
|
||||
case Error(Int, Data?, Error)
|
||||
}
|
||||
|
||||
open class Response<T> {
|
||||
open let statusCode: Int
|
||||
open let header: [String: String]
|
||||
open let body: T?
|
||||
|
||||
public init(statusCode: Int, header: [String: String], body: T?) {
|
||||
self.statusCode = statusCode
|
||||
self.header = header
|
||||
self.body = body
|
||||
}
|
||||
|
||||
public convenience init(response: HTTPURLResponse, body: T?) {
|
||||
let rawHeader = response.allHeaderFields
|
||||
var header = [String:String]()
|
||||
for (key, value) in rawHeader {
|
||||
header[key as! String] = value as? String
|
||||
}
|
||||
self.init(statusCode: response.statusCode, header: header, body: body)
|
||||
}
|
||||
}
|
||||
|
||||
private var once = Int()
|
||||
class Decoders {
|
||||
static fileprivate var decoders = Dictionary<String, ((AnyObject) -> AnyObject)>()
|
||||
|
||||
static func addDecoder<T>(clazz: T.Type, decoder: @escaping ((AnyObject) -> T)) {
|
||||
let key = "\(T.self)"
|
||||
decoders[key] = { decoder($0) as AnyObject }
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: [T].Type, source: AnyObject) -> [T] {
|
||||
let array = source as! [AnyObject]
|
||||
return array.map { Decoders.decode(clazz: T.self, source: $0) }
|
||||
}
|
||||
|
||||
static func decode<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject) -> [Key:T] {
|
||||
let sourceDictionary = source as! [Key: AnyObject]
|
||||
var dictionary = [Key:T]()
|
||||
for (key, value) in sourceDictionary {
|
||||
dictionary[key] = Decoders.decode(clazz: T.self, source: value)
|
||||
}
|
||||
return dictionary
|
||||
}
|
||||
|
||||
static func decode<T>(clazz: T.Type, source: AnyObject) -> T {
|
||||
initialize()
|
||||
if T.self is Int32.Type && source is NSNumber {
|
||||
return source.int32Value as! T;
|
||||
}
|
||||
if T.self is Int64.Type && source is NSNumber {
|
||||
return source.int64Value as! T;
|
||||
}
|
||||
if T.self is UUID.Type && source is String {
|
||||
return UUID(uuidString: source as! String) as! T
|
||||
}
|
||||
if source is T {
|
||||
return source as! T
|
||||
}
|
||||
if T.self is Data.Type && source is String {
|
||||
return Data(base64Encoded: source as! String) as! T
|
||||
}
|
||||
|
||||
let key = "\(T.self)"
|
||||
if let decoder = decoders[key] {
|
||||
return decoder(source) as! T
|
||||
} else {
|
||||
fatalError("Source \(source) is not convertible to type \(clazz): Maybe swagger file is insufficient")
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: T.Type, source: AnyObject?) -> T? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (source: AnyObject) -> T in
|
||||
Decoders.decode(clazz: clazz, source: source)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T>(clazz: [T].Type, source: AnyObject?) -> [T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
}
|
||||
}
|
||||
|
||||
static func decodeOptional<T, Key: Hashable>(clazz: [Key:T].Type, source: AnyObject?) -> [Key:T]? {
|
||||
if source is NSNull {
|
||||
return nil
|
||||
}
|
||||
return source.map { (someSource: AnyObject) -> [Key:T] in
|
||||
Decoders.decode(clazz: clazz, source: someSource)
|
||||
}
|
||||
}
|
||||
|
||||
private static var __once: () = {
|
||||
let formatters = [
|
||||
"yyyy-MM-dd",
|
||||
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS"
|
||||
].map { (format: String) -> DateFormatter in
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = format
|
||||
return formatter
|
||||
}
|
||||
// Decoder for Date
|
||||
Decoders.addDecoder(clazz: Date.self) { (source: AnyObject) -> Date in
|
||||
if let sourceString = source as? String {
|
||||
for formatter in formatters {
|
||||
if let date = formatter.date(from: sourceString) {
|
||||
return date
|
||||
}
|
||||
}
|
||||
}
|
||||
if let sourceInt = source as? Int {
|
||||
// treat as a java date
|
||||
return Date(timeIntervalSince1970: Double(sourceInt / 1000) )
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}
|
||||
|
||||
// Decoder for [AdditionalPropertiesClass]
|
||||
Decoders.addDecoder(clazz: [AdditionalPropertiesClass].self) { (source: AnyObject) -> [AdditionalPropertiesClass] in
|
||||
return Decoders.decode(clazz: [AdditionalPropertiesClass].self, source: source)
|
||||
}
|
||||
// Decoder for AdditionalPropertiesClass
|
||||
Decoders.addDecoder(clazz: AdditionalPropertiesClass.self) { (source: AnyObject) -> AdditionalPropertiesClass in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = AdditionalPropertiesClass()
|
||||
instance.mapProperty = Decoders.decodeOptional(clazz: Dictionary.self, source: sourceDictionary["map_property"] as AnyObject?)
|
||||
instance.mapOfMapProperty = Decoders.decodeOptional(clazz: Dictionary.self, source: sourceDictionary["map_of_map_property"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Animal]
|
||||
Decoders.addDecoder(clazz: [Animal].self) { (source: AnyObject) -> [Animal] in
|
||||
return Decoders.decode(clazz: [Animal].self, source: source)
|
||||
}
|
||||
// Decoder for Animal
|
||||
Decoders.addDecoder(clazz: Animal.self) { (source: AnyObject) -> Animal in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Animal()
|
||||
instance.className = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["className"] as AnyObject?)
|
||||
instance.color = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["color"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [AnimalFarm]
|
||||
Decoders.addDecoder(clazz: [AnimalFarm].self) { (source: AnyObject) -> [AnimalFarm] in
|
||||
return Decoders.decode(clazz: [AnimalFarm].self, source: source)
|
||||
}
|
||||
// Decoder for AnimalFarm
|
||||
Decoders.addDecoder(clazz: AnimalFarm.self) { (source: AnyObject) -> AnimalFarm in
|
||||
let sourceArray = source as! [AnyObject]
|
||||
return sourceArray.map({ Decoders.decode(clazz: Animal.self, source: $0) })
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [ApiResponse]
|
||||
Decoders.addDecoder(clazz: [ApiResponse].self) { (source: AnyObject) -> [ApiResponse] in
|
||||
return Decoders.decode(clazz: [ApiResponse].self, source: source)
|
||||
}
|
||||
// Decoder for ApiResponse
|
||||
Decoders.addDecoder(clazz: ApiResponse.self) { (source: AnyObject) -> ApiResponse in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = ApiResponse()
|
||||
instance.code = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["code"] as AnyObject?)
|
||||
instance.type = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["type"] as AnyObject?)
|
||||
instance.message = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["message"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [ArrayOfArrayOfNumberOnly]
|
||||
Decoders.addDecoder(clazz: [ArrayOfArrayOfNumberOnly].self) { (source: AnyObject) -> [ArrayOfArrayOfNumberOnly] in
|
||||
return Decoders.decode(clazz: [ArrayOfArrayOfNumberOnly].self, source: source)
|
||||
}
|
||||
// Decoder for ArrayOfArrayOfNumberOnly
|
||||
Decoders.addDecoder(clazz: ArrayOfArrayOfNumberOnly.self) { (source: AnyObject) -> ArrayOfArrayOfNumberOnly in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = ArrayOfArrayOfNumberOnly()
|
||||
instance.arrayArrayNumber = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["ArrayArrayNumber"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [ArrayOfNumberOnly]
|
||||
Decoders.addDecoder(clazz: [ArrayOfNumberOnly].self) { (source: AnyObject) -> [ArrayOfNumberOnly] in
|
||||
return Decoders.decode(clazz: [ArrayOfNumberOnly].self, source: source)
|
||||
}
|
||||
// Decoder for ArrayOfNumberOnly
|
||||
Decoders.addDecoder(clazz: ArrayOfNumberOnly.self) { (source: AnyObject) -> ArrayOfNumberOnly in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = ArrayOfNumberOnly()
|
||||
instance.arrayNumber = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["ArrayNumber"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [ArrayTest]
|
||||
Decoders.addDecoder(clazz: [ArrayTest].self) { (source: AnyObject) -> [ArrayTest] in
|
||||
return Decoders.decode(clazz: [ArrayTest].self, source: source)
|
||||
}
|
||||
// Decoder for ArrayTest
|
||||
Decoders.addDecoder(clazz: ArrayTest.self) { (source: AnyObject) -> ArrayTest in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = ArrayTest()
|
||||
instance.arrayOfString = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["array_of_string"] as AnyObject?)
|
||||
instance.arrayArrayOfInteger = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["array_array_of_integer"] as AnyObject?)
|
||||
instance.arrayArrayOfModel = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["array_array_of_model"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Cat]
|
||||
Decoders.addDecoder(clazz: [Cat].self) { (source: AnyObject) -> [Cat] in
|
||||
return Decoders.decode(clazz: [Cat].self, source: source)
|
||||
}
|
||||
// Decoder for Cat
|
||||
Decoders.addDecoder(clazz: Cat.self) { (source: AnyObject) -> Cat in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Cat()
|
||||
instance.className = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["className"] as AnyObject?)
|
||||
instance.color = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["color"] as AnyObject?)
|
||||
instance.declawed = Decoders.decodeOptional(clazz: Bool.self, source: sourceDictionary["declawed"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Category]
|
||||
Decoders.addDecoder(clazz: [Category].self) { (source: AnyObject) -> [Category] in
|
||||
return Decoders.decode(clazz: [Category].self, source: source)
|
||||
}
|
||||
// Decoder for Category
|
||||
Decoders.addDecoder(clazz: Category.self) { (source: AnyObject) -> Category in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Category()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"] as AnyObject?)
|
||||
instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Client]
|
||||
Decoders.addDecoder(clazz: [Client].self) { (source: AnyObject) -> [Client] in
|
||||
return Decoders.decode(clazz: [Client].self, source: source)
|
||||
}
|
||||
// Decoder for Client
|
||||
Decoders.addDecoder(clazz: Client.self) { (source: AnyObject) -> Client in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Client()
|
||||
instance.client = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["client"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Dog]
|
||||
Decoders.addDecoder(clazz: [Dog].self) { (source: AnyObject) -> [Dog] in
|
||||
return Decoders.decode(clazz: [Dog].self, source: source)
|
||||
}
|
||||
// Decoder for Dog
|
||||
Decoders.addDecoder(clazz: Dog.self) { (source: AnyObject) -> Dog in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Dog()
|
||||
instance.className = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["className"] as AnyObject?)
|
||||
instance.color = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["color"] as AnyObject?)
|
||||
instance.breed = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["breed"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [EnumArrays]
|
||||
Decoders.addDecoder(clazz: [EnumArrays].self) { (source: AnyObject) -> [EnumArrays] in
|
||||
return Decoders.decode(clazz: [EnumArrays].self, source: source)
|
||||
}
|
||||
// Decoder for EnumArrays
|
||||
Decoders.addDecoder(clazz: EnumArrays.self) { (source: AnyObject) -> EnumArrays in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = EnumArrays()
|
||||
if let justSymbol = sourceDictionary["just_symbol"] as? String {
|
||||
instance.justSymbol = EnumArrays.JustSymbol(rawValue: (justSymbol))
|
||||
}
|
||||
|
||||
if let arrayEnum = sourceDictionary["array_enum"] as? [String] {
|
||||
instance.arrayEnum = arrayEnum.map ({ EnumArrays.ArrayEnum(rawValue: $0)! })
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [EnumClass]
|
||||
Decoders.addDecoder(clazz: [EnumClass].self) { (source: AnyObject) -> [EnumClass] in
|
||||
return Decoders.decode(clazz: [EnumClass].self, source: source)
|
||||
}
|
||||
// Decoder for EnumClass
|
||||
Decoders.addDecoder(clazz: EnumClass.self) { (source: AnyObject) -> EnumClass in
|
||||
if let source = source as? String {
|
||||
if let result = EnumClass(rawValue: source) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
fatalError("Source \(source) is not convertible to enum type EnumClass: Maybe swagger file is insufficient")
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [EnumTest]
|
||||
Decoders.addDecoder(clazz: [EnumTest].self) { (source: AnyObject) -> [EnumTest] in
|
||||
return Decoders.decode(clazz: [EnumTest].self, source: source)
|
||||
}
|
||||
// Decoder for EnumTest
|
||||
Decoders.addDecoder(clazz: EnumTest.self) { (source: AnyObject) -> EnumTest in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = EnumTest()
|
||||
if let enumString = sourceDictionary["enum_string"] as? String {
|
||||
instance.enumString = EnumTest.EnumString(rawValue: (enumString))
|
||||
}
|
||||
|
||||
if let enumInteger = sourceDictionary["enum_integer"] as? Int32 {
|
||||
instance.enumInteger = EnumTest.EnumInteger(rawValue: (enumInteger))
|
||||
}
|
||||
|
||||
if let enumNumber = sourceDictionary["enum_number"] as? Double {
|
||||
instance.enumNumber = EnumTest.EnumNumber(rawValue: (enumNumber))
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [FormatTest]
|
||||
Decoders.addDecoder(clazz: [FormatTest].self) { (source: AnyObject) -> [FormatTest] in
|
||||
return Decoders.decode(clazz: [FormatTest].self, source: source)
|
||||
}
|
||||
// Decoder for FormatTest
|
||||
Decoders.addDecoder(clazz: FormatTest.self) { (source: AnyObject) -> FormatTest in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = FormatTest()
|
||||
instance.integer = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["integer"] as AnyObject?)
|
||||
instance.int32 = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["int32"] as AnyObject?)
|
||||
instance.int64 = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["int64"] as AnyObject?)
|
||||
instance.number = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["number"] as AnyObject?)
|
||||
instance.float = Decoders.decodeOptional(clazz: Float.self, source: sourceDictionary["float"] as AnyObject?)
|
||||
instance.double = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["double"] as AnyObject?)
|
||||
instance.string = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["string"] as AnyObject?)
|
||||
instance.byte = Decoders.decodeOptional(clazz: Data.self, source: sourceDictionary["byte"] as AnyObject?)
|
||||
instance.binary = Decoders.decodeOptional(clazz: Data.self, source: sourceDictionary["binary"] as AnyObject?)
|
||||
instance.date = Decoders.decodeOptional(clazz: Date.self, source: sourceDictionary["date"] as AnyObject?)
|
||||
instance.dateTime = Decoders.decodeOptional(clazz: Date.self, source: sourceDictionary["dateTime"] as AnyObject?)
|
||||
instance.uuid = Decoders.decodeOptional(clazz: UUID.self, source: sourceDictionary["uuid"] as AnyObject?)
|
||||
instance.password = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["password"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [HasOnlyReadOnly]
|
||||
Decoders.addDecoder(clazz: [HasOnlyReadOnly].self) { (source: AnyObject) -> [HasOnlyReadOnly] in
|
||||
return Decoders.decode(clazz: [HasOnlyReadOnly].self, source: source)
|
||||
}
|
||||
// Decoder for HasOnlyReadOnly
|
||||
Decoders.addDecoder(clazz: HasOnlyReadOnly.self) { (source: AnyObject) -> HasOnlyReadOnly in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = HasOnlyReadOnly()
|
||||
instance.bar = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["bar"] as AnyObject?)
|
||||
instance.foo = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["foo"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [List]
|
||||
Decoders.addDecoder(clazz: [List].self) { (source: AnyObject) -> [List] in
|
||||
return Decoders.decode(clazz: [List].self, source: source)
|
||||
}
|
||||
// Decoder for List
|
||||
Decoders.addDecoder(clazz: List.self) { (source: AnyObject) -> List in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = List()
|
||||
instance._123List = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["123-list"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [MapTest]
|
||||
Decoders.addDecoder(clazz: [MapTest].self) { (source: AnyObject) -> [MapTest] in
|
||||
return Decoders.decode(clazz: [MapTest].self, source: source)
|
||||
}
|
||||
// Decoder for MapTest
|
||||
Decoders.addDecoder(clazz: MapTest.self) { (source: AnyObject) -> MapTest in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = MapTest()
|
||||
instance.mapMapOfString = Decoders.decodeOptional(clazz: Dictionary.self, source: sourceDictionary["map_map_of_string"] as AnyObject?)
|
||||
if let mapOfEnumString = sourceDictionary["map_of_enum_string"] as? [String:String] { //TODO: handle enum map scenario
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [MixedPropertiesAndAdditionalPropertiesClass]
|
||||
Decoders.addDecoder(clazz: [MixedPropertiesAndAdditionalPropertiesClass].self) { (source: AnyObject) -> [MixedPropertiesAndAdditionalPropertiesClass] in
|
||||
return Decoders.decode(clazz: [MixedPropertiesAndAdditionalPropertiesClass].self, source: source)
|
||||
}
|
||||
// Decoder for MixedPropertiesAndAdditionalPropertiesClass
|
||||
Decoders.addDecoder(clazz: MixedPropertiesAndAdditionalPropertiesClass.self) { (source: AnyObject) -> MixedPropertiesAndAdditionalPropertiesClass in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = MixedPropertiesAndAdditionalPropertiesClass()
|
||||
instance.uuid = Decoders.decodeOptional(clazz: UUID.self, source: sourceDictionary["uuid"] as AnyObject?)
|
||||
instance.dateTime = Decoders.decodeOptional(clazz: Date.self, source: sourceDictionary["dateTime"] as AnyObject?)
|
||||
instance.map = Decoders.decodeOptional(clazz: Dictionary.self, source: sourceDictionary["map"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Model200Response]
|
||||
Decoders.addDecoder(clazz: [Model200Response].self) { (source: AnyObject) -> [Model200Response] in
|
||||
return Decoders.decode(clazz: [Model200Response].self, source: source)
|
||||
}
|
||||
// Decoder for Model200Response
|
||||
Decoders.addDecoder(clazz: Model200Response.self) { (source: AnyObject) -> Model200Response in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Model200Response()
|
||||
instance.name = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["name"] as AnyObject?)
|
||||
instance._class = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["class"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Name]
|
||||
Decoders.addDecoder(clazz: [Name].self) { (source: AnyObject) -> [Name] in
|
||||
return Decoders.decode(clazz: [Name].self, source: source)
|
||||
}
|
||||
// Decoder for Name
|
||||
Decoders.addDecoder(clazz: Name.self) { (source: AnyObject) -> Name in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Name()
|
||||
instance.name = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["name"] as AnyObject?)
|
||||
instance.snakeCase = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["snake_case"] as AnyObject?)
|
||||
instance.property = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["property"] as AnyObject?)
|
||||
instance._123Number = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["123Number"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [NumberOnly]
|
||||
Decoders.addDecoder(clazz: [NumberOnly].self) { (source: AnyObject) -> [NumberOnly] in
|
||||
return Decoders.decode(clazz: [NumberOnly].self, source: source)
|
||||
}
|
||||
// Decoder for NumberOnly
|
||||
Decoders.addDecoder(clazz: NumberOnly.self) { (source: AnyObject) -> NumberOnly in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = NumberOnly()
|
||||
instance.justNumber = Decoders.decodeOptional(clazz: Double.self, source: sourceDictionary["JustNumber"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Order]
|
||||
Decoders.addDecoder(clazz: [Order].self) { (source: AnyObject) -> [Order] in
|
||||
return Decoders.decode(clazz: [Order].self, source: source)
|
||||
}
|
||||
// Decoder for Order
|
||||
Decoders.addDecoder(clazz: Order.self) { (source: AnyObject) -> Order in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Order()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"] as AnyObject?)
|
||||
instance.petId = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["petId"] as AnyObject?)
|
||||
instance.quantity = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["quantity"] as AnyObject?)
|
||||
instance.shipDate = Decoders.decodeOptional(clazz: Date.self, source: sourceDictionary["shipDate"] as AnyObject?)
|
||||
if let status = sourceDictionary["status"] as? String {
|
||||
instance.status = Order.Status(rawValue: (status))
|
||||
}
|
||||
|
||||
instance.complete = Decoders.decodeOptional(clazz: Bool.self, source: sourceDictionary["complete"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Pet]
|
||||
Decoders.addDecoder(clazz: [Pet].self) { (source: AnyObject) -> [Pet] in
|
||||
return Decoders.decode(clazz: [Pet].self, source: source)
|
||||
}
|
||||
// Decoder for Pet
|
||||
Decoders.addDecoder(clazz: Pet.self) { (source: AnyObject) -> Pet in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Pet()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"] as AnyObject?)
|
||||
instance.category = Decoders.decodeOptional(clazz: Category.self, source: sourceDictionary["category"] as AnyObject?)
|
||||
instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"] as AnyObject?)
|
||||
instance.photoUrls = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["photoUrls"] as AnyObject?)
|
||||
instance.tags = Decoders.decodeOptional(clazz: Array.self, source: sourceDictionary["tags"] as AnyObject?)
|
||||
if let status = sourceDictionary["status"] as? String {
|
||||
instance.status = Pet.Status(rawValue: (status))
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [ReadOnlyFirst]
|
||||
Decoders.addDecoder(clazz: [ReadOnlyFirst].self) { (source: AnyObject) -> [ReadOnlyFirst] in
|
||||
return Decoders.decode(clazz: [ReadOnlyFirst].self, source: source)
|
||||
}
|
||||
// Decoder for ReadOnlyFirst
|
||||
Decoders.addDecoder(clazz: ReadOnlyFirst.self) { (source: AnyObject) -> ReadOnlyFirst in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = ReadOnlyFirst()
|
||||
instance.bar = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["bar"] as AnyObject?)
|
||||
instance.baz = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["baz"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Return]
|
||||
Decoders.addDecoder(clazz: [Return].self) { (source: AnyObject) -> [Return] in
|
||||
return Decoders.decode(clazz: [Return].self, source: source)
|
||||
}
|
||||
// Decoder for Return
|
||||
Decoders.addDecoder(clazz: Return.self) { (source: AnyObject) -> Return in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Return()
|
||||
instance._return = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["return"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [SpecialModelName]
|
||||
Decoders.addDecoder(clazz: [SpecialModelName].self) { (source: AnyObject) -> [SpecialModelName] in
|
||||
return Decoders.decode(clazz: [SpecialModelName].self, source: source)
|
||||
}
|
||||
// Decoder for SpecialModelName
|
||||
Decoders.addDecoder(clazz: SpecialModelName.self) { (source: AnyObject) -> SpecialModelName in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = SpecialModelName()
|
||||
instance.specialPropertyName = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["$special[property.name]"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [Tag]
|
||||
Decoders.addDecoder(clazz: [Tag].self) { (source: AnyObject) -> [Tag] in
|
||||
return Decoders.decode(clazz: [Tag].self, source: source)
|
||||
}
|
||||
// Decoder for Tag
|
||||
Decoders.addDecoder(clazz: Tag.self) { (source: AnyObject) -> Tag in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = Tag()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"] as AnyObject?)
|
||||
instance.name = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["name"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
// Decoder for [User]
|
||||
Decoders.addDecoder(clazz: [User].self) { (source: AnyObject) -> [User] in
|
||||
return Decoders.decode(clazz: [User].self, source: source)
|
||||
}
|
||||
// Decoder for User
|
||||
Decoders.addDecoder(clazz: User.self) { (source: AnyObject) -> User in
|
||||
let sourceDictionary = source as! [AnyHashable: Any]
|
||||
let instance = User()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"] as AnyObject?)
|
||||
instance.username = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["username"] as AnyObject?)
|
||||
instance.firstName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["firstName"] as AnyObject?)
|
||||
instance.lastName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["lastName"] as AnyObject?)
|
||||
instance.email = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["email"] as AnyObject?)
|
||||
instance.password = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["password"] as AnyObject?)
|
||||
instance.phone = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["phone"] as AnyObject?)
|
||||
instance.userStatus = Decoders.decodeOptional(clazz: Int32.self, source: sourceDictionary["userStatus"] as AnyObject?)
|
||||
return instance
|
||||
}
|
||||
}()
|
||||
|
||||
static fileprivate func initialize() {
|
||||
_ = Decoders.__once
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// AdditionalPropertiesClass.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class AdditionalPropertiesClass: JSONEncodable {
|
||||
public var mapProperty: [String:String]?
|
||||
public var mapOfMapProperty: [String:[String:String]]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["map_property"] = self.mapProperty?.encodeToJSON()
|
||||
nillableDictionary["map_of_map_property"] = self.mapOfMapProperty?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Animal.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Animal: JSONEncodable {
|
||||
public var className: String?
|
||||
public var color: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["className"] = self.className
|
||||
nillableDictionary["color"] = self.color
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// AnimalFarm.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public typealias AnimalFarm = [Animal]
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// ApiResponse.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ApiResponse: JSONEncodable {
|
||||
public var code: Int32?
|
||||
public var type: String?
|
||||
public var message: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["code"] = self.code?.encodeToJSON()
|
||||
nillableDictionary["type"] = self.type
|
||||
nillableDictionary["message"] = self.message
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// ArrayOfArrayOfNumberOnly.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ArrayOfArrayOfNumberOnly: JSONEncodable {
|
||||
public var arrayArrayNumber: [[Double]]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["ArrayArrayNumber"] = self.arrayArrayNumber?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// ArrayOfNumberOnly.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ArrayOfNumberOnly: JSONEncodable {
|
||||
public var arrayNumber: [Double]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["ArrayNumber"] = self.arrayNumber?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// ArrayTest.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ArrayTest: JSONEncodable {
|
||||
public var arrayOfString: [String]?
|
||||
public var arrayArrayOfInteger: [[Int64]]?
|
||||
public var arrayArrayOfModel: [[ReadOnlyFirst]]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["array_of_string"] = self.arrayOfString?.encodeToJSON()
|
||||
nillableDictionary["array_array_of_integer"] = self.arrayArrayOfInteger?.encodeToJSON()
|
||||
nillableDictionary["array_array_of_model"] = self.arrayArrayOfModel?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Cat.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Cat: JSONEncodable {
|
||||
public var className: String?
|
||||
public var color: String?
|
||||
public var declawed: Bool?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["className"] = self.className
|
||||
nillableDictionary["color"] = self.color
|
||||
nillableDictionary["declawed"] = self.declawed
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Category.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Category: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var name: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["name"] = self.name
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Client.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Client: JSONEncodable {
|
||||
public var client: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["client"] = self.client
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Dog.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Dog: JSONEncodable {
|
||||
public var className: String?
|
||||
public var color: String?
|
||||
public var breed: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["className"] = self.className
|
||||
nillableDictionary["color"] = self.color
|
||||
nillableDictionary["breed"] = self.breed
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// EnumArrays.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class EnumArrays: JSONEncodable {
|
||||
public enum JustSymbol: String {
|
||||
case greaterThanOrEqualTo = ">="
|
||||
case dollar = "$"
|
||||
}
|
||||
public enum ArrayEnum: String {
|
||||
case fish = "fish"
|
||||
case crab = "crab"
|
||||
}
|
||||
public var justSymbol: JustSymbol?
|
||||
public var arrayEnum: [ArrayEnum]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["just_symbol"] = self.justSymbol?.rawValue
|
||||
nillableDictionary["array_enum"] = self.arrayEnum?.map({$0.rawValue}).encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// EnumClass.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public enum EnumClass: String {
|
||||
case abc = "_abc"
|
||||
case efg = "-efg"
|
||||
case xyz = "(xyz)"
|
||||
|
||||
func encodeToJSON() -> Any { return self.rawValue }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// EnumTest.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class EnumTest: JSONEncodable {
|
||||
public enum EnumString: String {
|
||||
case upper = "UPPER"
|
||||
case lower = "lower"
|
||||
}
|
||||
public enum EnumInteger: Int32 {
|
||||
case number1 = 1
|
||||
case numberminus1 = -1
|
||||
}
|
||||
public enum EnumNumber: Double {
|
||||
case number11 = 1.1
|
||||
case numberminus12 = -1.2
|
||||
}
|
||||
public var enumString: EnumString?
|
||||
public var enumInteger: EnumInteger?
|
||||
public var enumNumber: EnumNumber?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["enum_string"] = self.enumString?.rawValue
|
||||
nillableDictionary["enum_integer"] = self.enumInteger?.rawValue
|
||||
nillableDictionary["enum_number"] = self.enumNumber?.rawValue
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// FormatTest.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class FormatTest: JSONEncodable {
|
||||
public var integer: Int32?
|
||||
public var int32: Int32?
|
||||
public var int64: Int64?
|
||||
public var number: Double?
|
||||
public var float: Float?
|
||||
public var double: Double?
|
||||
public var string: String?
|
||||
public var byte: Data?
|
||||
public var binary: Data?
|
||||
public var date: Date?
|
||||
public var dateTime: Date?
|
||||
public var uuid: UUID?
|
||||
public var password: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["integer"] = self.integer?.encodeToJSON()
|
||||
nillableDictionary["int32"] = self.int32?.encodeToJSON()
|
||||
nillableDictionary["int64"] = self.int64?.encodeToJSON()
|
||||
nillableDictionary["number"] = self.number
|
||||
nillableDictionary["float"] = self.float
|
||||
nillableDictionary["double"] = self.double
|
||||
nillableDictionary["string"] = self.string
|
||||
nillableDictionary["byte"] = self.byte?.encodeToJSON()
|
||||
nillableDictionary["binary"] = self.binary?.encodeToJSON()
|
||||
nillableDictionary["date"] = self.date?.encodeToJSON()
|
||||
nillableDictionary["dateTime"] = self.dateTime?.encodeToJSON()
|
||||
nillableDictionary["uuid"] = self.uuid?.encodeToJSON()
|
||||
nillableDictionary["password"] = self.password
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// HasOnlyReadOnly.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class HasOnlyReadOnly: JSONEncodable {
|
||||
public var bar: String?
|
||||
public var foo: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["bar"] = self.bar
|
||||
nillableDictionary["foo"] = self.foo
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// List.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class List: JSONEncodable {
|
||||
public var _123List: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["123-list"] = self._123List
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// MapTest.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class MapTest: JSONEncodable {
|
||||
public enum MapOfEnumString: String {
|
||||
case upper = "UPPER"
|
||||
case lower = "lower"
|
||||
}
|
||||
public var mapMapOfString: [String:[String:String]]?
|
||||
public var mapOfEnumString: [String:String]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["map_map_of_string"] = self.mapMapOfString?.encodeToJSON()//TODO: handle enum map scenario
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// MixedPropertiesAndAdditionalPropertiesClass.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class MixedPropertiesAndAdditionalPropertiesClass: JSONEncodable {
|
||||
public var uuid: UUID?
|
||||
public var dateTime: Date?
|
||||
public var map: [String:Animal]?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["uuid"] = self.uuid?.encodeToJSON()
|
||||
nillableDictionary["dateTime"] = self.dateTime?.encodeToJSON()
|
||||
nillableDictionary["map"] = self.map?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Model200Response.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
/** Model for testing model name starting with number */
|
||||
open class Model200Response: JSONEncodable {
|
||||
public var name: Int32?
|
||||
public var _class: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["name"] = self.name?.encodeToJSON()
|
||||
nillableDictionary["class"] = self._class
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Name.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
/** Model for testing model name same as property name */
|
||||
open class Name: JSONEncodable {
|
||||
public var name: Int32?
|
||||
public var snakeCase: Int32?
|
||||
public var property: String?
|
||||
public var _123Number: Int32?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["name"] = self.name?.encodeToJSON()
|
||||
nillableDictionary["snake_case"] = self.snakeCase?.encodeToJSON()
|
||||
nillableDictionary["property"] = self.property
|
||||
nillableDictionary["123Number"] = self._123Number?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// NumberOnly.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class NumberOnly: JSONEncodable {
|
||||
public var justNumber: Double?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["JustNumber"] = self.justNumber
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Order.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Order: JSONEncodable {
|
||||
public enum Status: String {
|
||||
case placed = "placed"
|
||||
case approved = "approved"
|
||||
case delivered = "delivered"
|
||||
}
|
||||
public var id: Int64?
|
||||
public var petId: Int64?
|
||||
public var quantity: Int32?
|
||||
public var shipDate: Date?
|
||||
/** Order Status */
|
||||
public var status: Status?
|
||||
public var complete: Bool?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["petId"] = self.petId?.encodeToJSON()
|
||||
nillableDictionary["quantity"] = self.quantity?.encodeToJSON()
|
||||
nillableDictionary["shipDate"] = self.shipDate?.encodeToJSON()
|
||||
nillableDictionary["status"] = self.status?.rawValue
|
||||
nillableDictionary["complete"] = self.complete
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Pet.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Pet: JSONEncodable {
|
||||
public enum Status: String {
|
||||
case available = "available"
|
||||
case pending = "pending"
|
||||
case sold = "sold"
|
||||
}
|
||||
public var id: Int64?
|
||||
public var category: Category?
|
||||
public var name: String?
|
||||
public var photoUrls: [String]?
|
||||
public var tags: [Tag]?
|
||||
/** pet status in the store */
|
||||
public var status: Status?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["category"] = self.category?.encodeToJSON()
|
||||
nillableDictionary["name"] = self.name
|
||||
nillableDictionary["photoUrls"] = self.photoUrls?.encodeToJSON()
|
||||
nillableDictionary["tags"] = self.tags?.encodeToJSON()
|
||||
nillableDictionary["status"] = self.status?.rawValue
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// ReadOnlyFirst.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ReadOnlyFirst: JSONEncodable {
|
||||
public var bar: String?
|
||||
public var baz: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["bar"] = self.bar
|
||||
nillableDictionary["baz"] = self.baz
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Return.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
/** Model for testing reserved words */
|
||||
open class Return: JSONEncodable {
|
||||
public var _return: Int32?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["return"] = self._return?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// SpecialModelName.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class SpecialModelName: JSONEncodable {
|
||||
public var specialPropertyName: Int64?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["$special[property.name]"] = self.specialPropertyName?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Tag.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class Tag: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var name: String?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["name"] = self.name
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// User.swift
|
||||
//
|
||||
// Generated by swagger-codegen
|
||||
// https://github.com/swagger-api/swagger-codegen
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class User: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var username: String?
|
||||
public var firstName: String?
|
||||
public var lastName: String?
|
||||
public var email: String?
|
||||
public var password: String?
|
||||
public var phone: String?
|
||||
/** User Status */
|
||||
public var userStatus: Int32?
|
||||
|
||||
public init() {}
|
||||
|
||||
// MARK: JSONEncodable
|
||||
func encodeToJSON() -> Any {
|
||||
var nillableDictionary = [String:Any?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["username"] = self.username
|
||||
nillableDictionary["firstName"] = self.firstName
|
||||
nillableDictionary["lastName"] = self.lastName
|
||||
nillableDictionary["email"] = self.email
|
||||
nillableDictionary["password"] = self.password
|
||||
nillableDictionary["phone"] = self.phone
|
||||
nillableDictionary["userStatus"] = self.userStatus?.encodeToJSON()
|
||||
let dictionary: [String:Any] = APIHelper.rejectNil(nillableDictionary) ?? [:]
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use_frameworks!
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
|
||||
target 'SwaggerClient' do
|
||||
pod "PetstoreClient", :path => "../"
|
||||
|
||||
target 'SwaggerClientTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |configuration|
|
||||
configuration.build_settings['SWIFT_VERSION'] = "3.0"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
PODS:
|
||||
- Alamofire (4.0.0)
|
||||
- PetstoreClient (0.0.1):
|
||||
- Alamofire (~> 4.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- PetstoreClient (from `../`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
PetstoreClient:
|
||||
:path: ../
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: fef59f00388f267e52d9b432aa5d93dc97190f14
|
||||
PetstoreClient: bbde3383c51466fdda24ec28153ce2847ae5456f
|
||||
|
||||
PODFILE CHECKSUM: da9f5a7ad6086f2c7abb73cf2c35cefce04a9a30
|
||||
|
||||
COCOAPODS: 1.0.1
|
||||
19
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/LICENSE
generated
Normal file
19
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/LICENSE
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
1744
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/README.md
generated
Normal file
1744
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/README.md
generated
Normal file
File diff suppressed because it is too large
Load Diff
450
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/AFError.swift
generated
Normal file
450
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/AFError.swift
generated
Normal file
@@ -0,0 +1,450 @@
|
||||
//
|
||||
// AFError.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
|
||||
/// their own associated reasons.
|
||||
///
|
||||
/// - invalidURL: Returned when a `URLConvertible` type fails to create a valid `URL`.
|
||||
/// - parameterEncodingFailed: Returned when a parameter encoding object throws an error during the encoding process.
|
||||
/// - multipartEncodingFailed: Returned when some step in the multipart encoding process fails.
|
||||
/// - responseValidationFailed: Returned when a `validate()` call fails.
|
||||
/// - responseSerializationFailed: Returned when a response serializer encounters an error in the serialization process.
|
||||
public enum AFError: Error {
|
||||
/// The underlying reason the parameter encoding error occurred.
|
||||
///
|
||||
/// - missingURL: The URL request did not have a URL to encode.
|
||||
/// - jsonEncodingFailed: JSON serialization failed with an underlying system error during the
|
||||
/// encoding process.
|
||||
/// - propertyListEncodingFailed: Property list serialization failed with an underlying system error during
|
||||
/// encoding process.
|
||||
public enum ParameterEncodingFailureReason {
|
||||
case missingURL
|
||||
case jsonEncodingFailed(error: Error)
|
||||
case propertyListEncodingFailed(error: Error)
|
||||
}
|
||||
|
||||
/// The underlying reason the multipart encoding error occurred.
|
||||
///
|
||||
/// - bodyPartURLInvalid: The `fileURL` provided for reading an encodable body part isn't a
|
||||
/// file URL.
|
||||
/// - bodyPartFilenameInvalid: The filename of the `fileURL` provided has either an empty
|
||||
/// `lastPathComponent` or `pathExtension.
|
||||
/// - bodyPartFileNotReachable: The file at the `fileURL` provided was not reachable.
|
||||
/// - bodyPartFileNotReachableWithError: Attempting to check the reachability of the `fileURL` provided threw
|
||||
/// an error.
|
||||
/// - bodyPartFileIsDirectory: The file at the `fileURL` provided is actually a directory.
|
||||
/// - bodyPartFileSizeNotAvailable: The size of the file at the `fileURL` provided was not returned by
|
||||
/// the system.
|
||||
/// - bodyPartFileSizeQueryFailedWithError: The attempt to find the size of the file at the `fileURL` provided
|
||||
/// threw an error.
|
||||
/// - bodyPartInputStreamCreationFailed: An `InputStream` could not be created for the provided `fileURL`.
|
||||
/// - outputStreamCreationFailed: An `OutputStream` could not be created when attempting to write the
|
||||
/// encoded data to disk.
|
||||
/// - outputStreamFileAlreadyExists: The encoded body data could not be writtent disk because a file
|
||||
/// already exists at the provided `fileURL`.
|
||||
/// - outputStreamURLInvalid: The `fileURL` provided for writing the encoded body data to disk is
|
||||
/// not a file URL.
|
||||
/// - outputStreamWriteFailed: The attempt to write the encoded body data to disk failed with an
|
||||
/// underlying error.
|
||||
/// - inputStreamReadFailed: The attempt to read an encoded body part `InputStream` failed with
|
||||
/// underlying system error.
|
||||
public enum MultipartEncodingFailureReason {
|
||||
case bodyPartURLInvalid(url: URL)
|
||||
case bodyPartFilenameInvalid(in: URL)
|
||||
case bodyPartFileNotReachable(at: URL)
|
||||
case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
|
||||
case bodyPartFileIsDirectory(at: URL)
|
||||
case bodyPartFileSizeNotAvailable(at: URL)
|
||||
case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
|
||||
case bodyPartInputStreamCreationFailed(for: URL)
|
||||
|
||||
case outputStreamCreationFailed(for: URL)
|
||||
case outputStreamFileAlreadyExists(at: URL)
|
||||
case outputStreamURLInvalid(url: URL)
|
||||
case outputStreamWriteFailed(error: Error)
|
||||
|
||||
case inputStreamReadFailed(error: Error)
|
||||
}
|
||||
|
||||
/// The underlying reason the response validation error occurred.
|
||||
///
|
||||
/// - dataFileNil: The data file containing the server response did not exist.
|
||||
/// - dataFileReadFailed: The data file containing the server response could not be read.
|
||||
/// - missingContentType: The response did not contain a `Content-Type` and the `acceptableContentTypes`
|
||||
/// provided did not contain wildcard type.
|
||||
/// - unacceptableContentType: The response `Content-Type` did not match any type in the provided
|
||||
/// `acceptableContentTypes`.
|
||||
/// - unacceptableStatusCode: The response status code was not acceptable.
|
||||
public enum ResponseValidationFailureReason {
|
||||
case dataFileNil
|
||||
case dataFileReadFailed(at: URL)
|
||||
case missingContentType(acceptableContentTypes: [String])
|
||||
case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
|
||||
case unacceptableStatusCode(code: Int)
|
||||
}
|
||||
|
||||
/// The underlying reason the response serialization error occurred.
|
||||
///
|
||||
/// - inputDataNil: The server response contained no data.
|
||||
/// - inputDataNilOrZeroLength: The server response contained no data or the data was zero length.
|
||||
/// - inputFileNil: The file containing the server response did not exist.
|
||||
/// - inputFileReadFailed: The file containing the server response could not be read.
|
||||
/// - stringSerializationFailed: String serialization failed using the provided `String.Encoding`.
|
||||
/// - jsonSerializationFailed: JSON serialization failed with an underlying system error.
|
||||
/// - propertyListSerializationFailed: Property list serialization failed with an underlying system error.
|
||||
public enum ResponseSerializationFailureReason {
|
||||
case inputDataNil
|
||||
case inputDataNilOrZeroLength
|
||||
case inputFileNil
|
||||
case inputFileReadFailed(at: URL)
|
||||
case stringSerializationFailed(encoding: String.Encoding)
|
||||
case jsonSerializationFailed(error: Error)
|
||||
case propertyListSerializationFailed(error: Error)
|
||||
}
|
||||
|
||||
case invalidURL(url: URLConvertible)
|
||||
case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
|
||||
case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
|
||||
case responseValidationFailed(reason: ResponseValidationFailureReason)
|
||||
case responseSerializationFailed(reason: ResponseSerializationFailureReason)
|
||||
}
|
||||
|
||||
// MARK: - Error Booleans
|
||||
|
||||
extension AFError {
|
||||
/// Returns whether the AFError is an invalid URL error.
|
||||
public var isInvalidURLError: Bool {
|
||||
if case .invalidURL = self { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will
|
||||
/// contain the associated value.
|
||||
public var isParameterEncodingError: Bool {
|
||||
if case .multipartEncodingFailed = self { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns whether the AFError is a multipart encoding error. When `true`, the `url` and `underlyingError` properties
|
||||
/// will contain the associated values.
|
||||
public var isMultipartEncodingError: Bool {
|
||||
if case .multipartEncodingFailed = self { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`,
|
||||
/// `responseContentType`, and `responseCode` properties will contain the associated values.
|
||||
public var isResponseValidationError: Bool {
|
||||
if case .responseValidationFailed = self { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns whether the `AFError` is a response serialization error. When `true`, the `failedStringEncoding` and
|
||||
/// `underlyingError` properties will contain the associated values.
|
||||
public var isResponseSerializationError: Bool {
|
||||
if case .responseSerializationFailed = self { return true }
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Convenience Properties
|
||||
|
||||
extension AFError {
|
||||
/// The `URLConvertible` associated with the error.
|
||||
public var urlConvertible: URLConvertible? {
|
||||
switch self {
|
||||
case .invalidURL(let url):
|
||||
return url
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The `URL` associated with the error.
|
||||
public var url: URL? {
|
||||
switch self {
|
||||
case .multipartEncodingFailed(let reason):
|
||||
return reason.url
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`,
|
||||
/// `.multipartEncodingFailed` or `.responseSerializationFailed` error.
|
||||
public var underlyingError: Error? {
|
||||
switch self {
|
||||
case .parameterEncodingFailed(let reason):
|
||||
return reason.underlyingError
|
||||
case .multipartEncodingFailed(let reason):
|
||||
return reason.underlyingError
|
||||
case .responseSerializationFailed(let reason):
|
||||
return reason.underlyingError
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
|
||||
public var acceptableContentTypes: [String]? {
|
||||
switch self {
|
||||
case .responseValidationFailed(let reason):
|
||||
return reason.acceptableContentTypes
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The response `Content-Type` of a `.responseValidationFailed` error.
|
||||
public var responseContentType: String? {
|
||||
switch self {
|
||||
case .responseValidationFailed(let reason):
|
||||
return reason.responseContentType
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The response code of a `.responseValidationFailed` error.
|
||||
public var responseCode: Int? {
|
||||
switch self {
|
||||
case .responseValidationFailed(let reason):
|
||||
return reason.responseCode
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// The `String.Encoding` associated with a failed `.stringResponse()` call.
|
||||
public var failedStringEncoding: String.Encoding? {
|
||||
switch self {
|
||||
case .responseSerializationFailed(let reason):
|
||||
return reason.failedStringEncoding
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ParameterEncodingFailureReason {
|
||||
var underlyingError: Error? {
|
||||
switch self {
|
||||
case .jsonEncodingFailed(let error), .propertyListEncodingFailed(let error):
|
||||
return error
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.MultipartEncodingFailureReason {
|
||||
var url: URL? {
|
||||
switch self {
|
||||
case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url),
|
||||
.bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url),
|
||||
.bodyPartInputStreamCreationFailed(let url), .outputStreamCreationFailed(let url),
|
||||
.outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url),
|
||||
.bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _):
|
||||
return url
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var underlyingError: Error? {
|
||||
switch self {
|
||||
case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error),
|
||||
.outputStreamWriteFailed(let error), .inputStreamReadFailed(let error):
|
||||
return error
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ResponseValidationFailureReason {
|
||||
var acceptableContentTypes: [String]? {
|
||||
switch self {
|
||||
case .missingContentType(let types), .unacceptableContentType(let types, _):
|
||||
return types
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var responseContentType: String? {
|
||||
switch self {
|
||||
case .unacceptableContentType(_, let reponseType):
|
||||
return reponseType
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var responseCode: Int? {
|
||||
switch self {
|
||||
case .unacceptableStatusCode(let code):
|
||||
return code
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ResponseSerializationFailureReason {
|
||||
var failedStringEncoding: String.Encoding? {
|
||||
switch self {
|
||||
case .stringSerializationFailed(let encoding):
|
||||
return encoding
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var underlyingError: Error? {
|
||||
switch self {
|
||||
case .jsonSerializationFailed(let error), .propertyListSerializationFailed(let error):
|
||||
return error
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Error Descriptions
|
||||
|
||||
extension AFError: LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidURL(let url):
|
||||
return "URL is not valid: \(url)"
|
||||
case .parameterEncodingFailed(let reason):
|
||||
return reason.localizedDescription
|
||||
case .multipartEncodingFailed(let reason):
|
||||
return reason.localizedDescription
|
||||
case .responseValidationFailed(let reason):
|
||||
return reason.localizedDescription
|
||||
case .responseSerializationFailed(let reason):
|
||||
return reason.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ParameterEncodingFailureReason {
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .missingURL:
|
||||
return "URL request to encode was missing a URL"
|
||||
case .jsonEncodingFailed(let error):
|
||||
return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
|
||||
case .propertyListEncodingFailed(let error):
|
||||
return "PropertyList could not be encoded because of error:\n\(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.MultipartEncodingFailureReason {
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .bodyPartURLInvalid(let url):
|
||||
return "The URL provided is not a file URL: \(url)"
|
||||
case .bodyPartFilenameInvalid(let url):
|
||||
return "The URL provided does not have a valid filename: \(url)"
|
||||
case .bodyPartFileNotReachable(let url):
|
||||
return "The URL provided is not reachable: \(url)"
|
||||
case .bodyPartFileNotReachableWithError(let url, let error):
|
||||
return (
|
||||
"The system returned an error while checking the provided URL for " +
|
||||
"reachability.\nURL: \(url)\nError: \(error)"
|
||||
)
|
||||
case .bodyPartFileIsDirectory(let url):
|
||||
return "The URL provided is a directory: \(url)"
|
||||
case .bodyPartFileSizeNotAvailable(let url):
|
||||
return "Could not fetch the file size from the provided URL: \(url)"
|
||||
case .bodyPartFileSizeQueryFailedWithError(let url, let error):
|
||||
return (
|
||||
"The system returned an error while attempting to fetch the file size from the " +
|
||||
"provided URL.\nURL: \(url)\nError: \(error)"
|
||||
)
|
||||
case .bodyPartInputStreamCreationFailed(let url):
|
||||
return "Failed to create an InputStream for the provided URL: \(url)"
|
||||
case .outputStreamCreationFailed(let url):
|
||||
return "Failed to create an OutputStream for URL: \(url)"
|
||||
case .outputStreamFileAlreadyExists(let url):
|
||||
return "A file already exists at the provided URL: \(url)"
|
||||
case .outputStreamURLInvalid(let url):
|
||||
return "The provided OutputStream URL is invalid: \(url)"
|
||||
case .outputStreamWriteFailed(let error):
|
||||
return "OutputStream write failed with error: \(error)"
|
||||
case .inputStreamReadFailed(let error):
|
||||
return "InputStream read failed with error: \(error)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ResponseSerializationFailureReason {
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .inputDataNil:
|
||||
return "Response could not be serialized, input data was nil."
|
||||
case .inputDataNilOrZeroLength:
|
||||
return "Response could not be serialized, input data was nil or zero length."
|
||||
case .inputFileNil:
|
||||
return "Response could not be serialized, input file was nil."
|
||||
case .inputFileReadFailed(let url):
|
||||
return "Response could not be serialized, input file could not be read: \(url)."
|
||||
case .stringSerializationFailed(let encoding):
|
||||
return "String could not be serialized with encoding: \(encoding)."
|
||||
case .jsonSerializationFailed(let error):
|
||||
return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
|
||||
case .propertyListSerializationFailed(let error):
|
||||
return "PropertyList could not be serialized because of error:\n\(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AFError.ResponseValidationFailureReason {
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .dataFileNil:
|
||||
return "Response could not be validated, data file was nil."
|
||||
case .dataFileReadFailed(let url):
|
||||
return "Response could not be validated, data file could not be read: \(url)."
|
||||
case .missingContentType(let types):
|
||||
return (
|
||||
"Response Content-Type was missing and acceptable content types " +
|
||||
"(\(types.joined(separator: ","))) do not match \"*/*\"."
|
||||
)
|
||||
case .unacceptableContentType(let acceptableTypes, let responseType):
|
||||
return (
|
||||
"Response Content-Type \"\(responseType)\" does not match any acceptable types: " +
|
||||
"\(acceptableTypes.joined(separator: ","))."
|
||||
)
|
||||
case .unacceptableStatusCode(let code):
|
||||
return "Response status code was unacceptable: \(code)."
|
||||
}
|
||||
}
|
||||
}
|
||||
456
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Alamofire.swift
generated
Normal file
456
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Alamofire.swift
generated
Normal file
@@ -0,0 +1,456 @@
|
||||
//
|
||||
// Alamofire.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Types adopting the `URLConvertible` protocol can be used to construct URLs, which are then used to construct
|
||||
/// URL requests.
|
||||
public protocol URLConvertible {
|
||||
/// Returns a URL that conforms to RFC 2396 or throws an `Error`.
|
||||
///
|
||||
/// - throws: An `Error` if the type cannot be converted to a `URL`.
|
||||
///
|
||||
/// - returns: A URL or throws an `Error`.
|
||||
func asURL() throws -> URL
|
||||
}
|
||||
|
||||
extension String: URLConvertible {
|
||||
/// Returns a URL if `self` represents a valid URL string that conforms to RFC 2396 or throws an `AFError`.
|
||||
///
|
||||
/// - throws: An `AFError.invalidURL` if `self` is not a valid URL string.
|
||||
///
|
||||
/// - returns: A URL or throws an `AFError`.
|
||||
public func asURL() throws -> URL {
|
||||
guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
extension URL: URLConvertible {
|
||||
/// Returns self.
|
||||
public func asURL() throws -> URL { return self }
|
||||
}
|
||||
|
||||
extension URLComponents: URLConvertible {
|
||||
/// Returns a URL if `url` is not nil, otherise throws an `Error`.
|
||||
///
|
||||
/// - throws: An `AFError.invalidURL` if `url` is `nil`.
|
||||
///
|
||||
/// - returns: A URL or throws an `AFError`.
|
||||
public func asURL() throws -> URL {
|
||||
guard let url = url else { throw AFError.invalidURL(url: self) }
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests.
|
||||
public protocol URLRequestConvertible {
|
||||
/// Returns a URL request or throws if an `Error` was encountered.
|
||||
///
|
||||
/// - throws: An `Error` if the underlying `URLRequest` is `nil`.
|
||||
///
|
||||
/// - returns: A URL request.
|
||||
func asURLRequest() throws -> URLRequest
|
||||
}
|
||||
|
||||
extension URLRequestConvertible {
|
||||
/// The URL request.
|
||||
public var urlRequest: URLRequest? { return try? asURLRequest() }
|
||||
}
|
||||
|
||||
extension URLRequest: URLRequestConvertible {
|
||||
/// Returns a URL request or throws if an `Error` was encountered.
|
||||
public func asURLRequest() throws -> URLRequest { return self }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension URLRequest {
|
||||
/// Creates an instance with the specified `method`, `urlString` and `headers`.
|
||||
///
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The new `URLRequest` instance.
|
||||
public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
|
||||
let url = try url.asURL()
|
||||
|
||||
self.init(url: url)
|
||||
|
||||
httpMethod = method.rawValue
|
||||
|
||||
if let headers = headers {
|
||||
for (headerField, headerValue) in headers {
|
||||
setValue(headerValue, forHTTPHeaderField: headerField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func adapt(using adapter: RequestAdapter?) throws -> URLRequest {
|
||||
guard let adapter = adapter else { return self }
|
||||
return try adapter.adapt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Data Request
|
||||
|
||||
/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of the specified `url`,
|
||||
/// `method`, `parameters`, `encoding` and `headers`.
|
||||
///
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.get` by default.
|
||||
/// - parameter parameters: The parameters. `nil` by default.
|
||||
/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DataRequest`.
|
||||
@discardableResult
|
||||
public func request(
|
||||
_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> DataRequest
|
||||
{
|
||||
return SessionManager.default.request(
|
||||
url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoding: encoding,
|
||||
headers: headers
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of a URL based on the
|
||||
/// specified `urlRequest`.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request
|
||||
///
|
||||
/// - returns: The created `DataRequest`.
|
||||
@discardableResult
|
||||
public func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
|
||||
return SessionManager.default.request(urlRequest)
|
||||
}
|
||||
|
||||
// MARK: - Download Request
|
||||
|
||||
// MARK: URL Request
|
||||
|
||||
/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of the specified `url`,
|
||||
/// `method`, `parameters`, `encoding`, `headers` and save them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.get` by default.
|
||||
/// - parameter parameters: The parameters. `nil` by default.
|
||||
/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
public func download(
|
||||
_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
return SessionManager.default.download(
|
||||
url,
|
||||
method: method,
|
||||
parameters: parameters,
|
||||
encoding: encoding,
|
||||
headers: headers,
|
||||
to: destination
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of a URL based on the
|
||||
/// specified `urlRequest` and save them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request.
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
public func download(
|
||||
_ urlRequest: URLRequestConvertible,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
return SessionManager.default.download(urlRequest, to: destination)
|
||||
}
|
||||
|
||||
// MARK: Resume Data
|
||||
|
||||
/// Creates a `DownloadRequest` using the default `SessionManager` from the `resumeData` produced from a
|
||||
/// previous request cancellation to retrieve the contents of the original request and save them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
|
||||
/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for additional
|
||||
/// information.
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
public func download(
|
||||
resumingWith resumeData: Data,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
return SessionManager.default.download(resumingWith: resumeData, to: destination)
|
||||
}
|
||||
|
||||
// MARK: - Upload Request
|
||||
|
||||
// MARK: File
|
||||
|
||||
/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
|
||||
/// for uploading the `file`.
|
||||
///
|
||||
/// - parameter file: The file to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(
|
||||
_ fileURL: URL,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
return SessionManager.default.upload(fileURL, to: url, method: method, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
|
||||
/// uploading the `file`.
|
||||
///
|
||||
/// - parameter file: The file to upload.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
return SessionManager.default.upload(fileURL, with: urlRequest)
|
||||
}
|
||||
|
||||
// MARK: Data
|
||||
|
||||
/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
|
||||
/// for uploading the `data`.
|
||||
///
|
||||
/// - parameter data: The data to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(
|
||||
_ data: Data,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
return SessionManager.default.upload(data, to: url, method: method, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
|
||||
/// uploading the `data`.
|
||||
///
|
||||
/// - parameter data: The data to upload.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
return SessionManager.default.upload(data, with: urlRequest)
|
||||
}
|
||||
|
||||
// MARK: InputStream
|
||||
|
||||
/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
|
||||
/// for uploading the `stream`.
|
||||
///
|
||||
/// - parameter stream: The stream to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(
|
||||
_ stream: InputStream,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
return SessionManager.default.upload(stream, to: url, method: method, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
|
||||
/// uploading the `stream`.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request.
|
||||
/// - parameter stream: The stream to upload.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
public func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
return SessionManager.default.upload(stream, with: urlRequest)
|
||||
}
|
||||
|
||||
// MARK: MultipartFormData
|
||||
|
||||
/// Encodes `multipartFormData` using `encodingMemoryThreshold` with the default `SessionManager` and calls
|
||||
/// `encodingCompletion` with new `UploadRequest` using the `url`, `method` and `headers`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
|
||||
/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
|
||||
/// `multipartFormDataEncodingMemoryThreshold` by default.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
|
||||
public func upload(
|
||||
multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)
|
||||
{
|
||||
return SessionManager.default.upload(
|
||||
multipartFormData: multipartFormData,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
to: url,
|
||||
method: method,
|
||||
headers: headers,
|
||||
encodingCompletion: encodingCompletion
|
||||
)
|
||||
}
|
||||
|
||||
/// Encodes `multipartFormData` using `encodingMemoryThreshold` and the default `SessionManager` and
|
||||
/// calls `encodingCompletion` with new `UploadRequest` using the `urlRequest`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
|
||||
/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
|
||||
/// `multipartFormDataEncodingMemoryThreshold` by default.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
|
||||
public func upload(
|
||||
multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
|
||||
with urlRequest: URLRequestConvertible,
|
||||
encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)
|
||||
{
|
||||
return SessionManager.default.upload(
|
||||
multipartFormData: multipartFormData,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
with: urlRequest,
|
||||
encodingCompletion: encodingCompletion
|
||||
)
|
||||
}
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
// MARK: - Stream Request
|
||||
|
||||
// MARK: Hostname and Port
|
||||
|
||||
/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `hostname`
|
||||
/// and `port`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter hostName: The hostname of the server to connect to.
|
||||
/// - parameter port: The port of the server to connect to.
|
||||
///
|
||||
/// - returns: The created `StreamRequest`.
|
||||
@discardableResult
|
||||
public func stream(withHostName hostName: String, port: Int) -> StreamRequest {
|
||||
return SessionManager.default.stream(withHostName: hostName, port: port)
|
||||
}
|
||||
|
||||
// MARK: NetService
|
||||
|
||||
/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `netService`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter netService: The net service used to identify the endpoint.
|
||||
///
|
||||
/// - returns: The created `StreamRequest`.
|
||||
@discardableResult
|
||||
public func stream(with netService: NetService) -> StreamRequest {
|
||||
return SessionManager.default.stream(with: netService)
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// DispatchQueue+Alamofire.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Dispatch
|
||||
|
||||
extension DispatchQueue {
|
||||
static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) }
|
||||
static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) }
|
||||
static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) }
|
||||
static var background: DispatchQueue { return DispatchQueue.global(qos: .background) }
|
||||
|
||||
func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
|
||||
asyncAfter(deadline: .now() + delay, execute: closure)
|
||||
}
|
||||
|
||||
func syncResult<T>(_ closure: () -> T) -> T {
|
||||
var result: T!
|
||||
sync { result = closure() }
|
||||
return result
|
||||
}
|
||||
}
|
||||
581
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/MultipartFormData.swift
generated
Normal file
581
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/MultipartFormData.swift
generated
Normal file
@@ -0,0 +1,581 @@
|
||||
//
|
||||
// MultipartFormData.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(iOS) || os(watchOS) || os(tvOS)
|
||||
import MobileCoreServices
|
||||
#elseif os(OSX)
|
||||
import CoreServices
|
||||
#endif
|
||||
|
||||
/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode
|
||||
/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead
|
||||
/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the
|
||||
/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for
|
||||
/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
|
||||
///
|
||||
/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
|
||||
/// and the w3 form documentation.
|
||||
///
|
||||
/// - https://www.ietf.org/rfc/rfc2388.txt
|
||||
/// - https://www.ietf.org/rfc/rfc2045.txt
|
||||
/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
|
||||
open class MultipartFormData {
|
||||
|
||||
// MARK: - Helper Types
|
||||
|
||||
struct EncodingCharacters {
|
||||
static let crlf = "\r\n"
|
||||
}
|
||||
|
||||
struct BoundaryGenerator {
|
||||
enum BoundaryType {
|
||||
case initial, encapsulated, final
|
||||
}
|
||||
|
||||
static func randomBoundary() -> String {
|
||||
return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
|
||||
}
|
||||
|
||||
static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
|
||||
let boundaryText: String
|
||||
|
||||
switch boundaryType {
|
||||
case .initial:
|
||||
boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
|
||||
case .encapsulated:
|
||||
boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
|
||||
case .final:
|
||||
boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
|
||||
}
|
||||
|
||||
return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
|
||||
}
|
||||
}
|
||||
|
||||
class BodyPart {
|
||||
let headers: HTTPHeaders
|
||||
let bodyStream: InputStream
|
||||
let bodyContentLength: UInt64
|
||||
var hasInitialBoundary = false
|
||||
var hasFinalBoundary = false
|
||||
|
||||
init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
|
||||
self.headers = headers
|
||||
self.bodyStream = bodyStream
|
||||
self.bodyContentLength = bodyContentLength
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
|
||||
open var contentType: String { return "multipart/form-data; boundary=\(boundary)" }
|
||||
|
||||
/// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
|
||||
public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
|
||||
|
||||
/// The boundary used to separate the body parts in the encoded form data.
|
||||
public let boundary: String
|
||||
|
||||
private var bodyParts: [BodyPart]
|
||||
private var bodyPartError: AFError?
|
||||
private let streamBufferSize: Int
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
/// Creates a multipart form data object.
|
||||
///
|
||||
/// - returns: The multipart form data object.
|
||||
public init() {
|
||||
self.boundary = BoundaryGenerator.randomBoundary()
|
||||
self.bodyParts = []
|
||||
|
||||
///
|
||||
/// The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more
|
||||
/// information, please refer to the following article:
|
||||
/// - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
|
||||
///
|
||||
|
||||
self.streamBufferSize = 1024
|
||||
}
|
||||
|
||||
// MARK: - Body Parts
|
||||
|
||||
/// Creates a body part from the data and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
|
||||
/// - Encoded data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter data: The data to encode into the multipart form data.
|
||||
/// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header.
|
||||
public func append(_ data: Data, withName name: String) {
|
||||
let headers = contentHeaders(withName: name)
|
||||
let stream = InputStream(data: data)
|
||||
let length = UInt64(data.count)
|
||||
|
||||
append(stream, withLength: length, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a body part from the data and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
|
||||
/// - `Content-Type: #{generated mimeType}` (HTTP Header)
|
||||
/// - Encoded data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter data: The data to encode into the multipart form data.
|
||||
/// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header.
|
||||
/// - parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header.
|
||||
public func append(_ data: Data, withName name: String, mimeType: String) {
|
||||
let headers = contentHeaders(withName: name, mimeType: mimeType)
|
||||
let stream = InputStream(data: data)
|
||||
let length = UInt64(data.count)
|
||||
|
||||
append(stream, withLength: length, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a body part from the data and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
|
||||
/// - `Content-Type: #{mimeType}` (HTTP Header)
|
||||
/// - Encoded file data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter data: The data to encode into the multipart form data.
|
||||
/// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header.
|
||||
/// - parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header.
|
||||
/// - parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header.
|
||||
public func append(_ data: Data, withName name: String, fileName: String, mimeType: String) {
|
||||
let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
|
||||
let stream = InputStream(data: data)
|
||||
let length = UInt64(data.count)
|
||||
|
||||
append(stream, withLength: length, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a body part from the file and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
|
||||
/// - `Content-Type: #{generated mimeType}` (HTTP Header)
|
||||
/// - Encoded file data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
|
||||
/// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
|
||||
/// system associated MIME type.
|
||||
///
|
||||
/// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data.
|
||||
/// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header.
|
||||
public func append(_ fileURL: URL, withName name: String) {
|
||||
let fileName = fileURL.lastPathComponent
|
||||
let pathExtension = fileURL.pathExtension
|
||||
|
||||
if !fileName.isEmpty && !pathExtension.isEmpty {
|
||||
let mime = mimeType(forPathExtension: pathExtension)
|
||||
append(fileURL, withName: name, fileName: fileName, mimeType: mime)
|
||||
} else {
|
||||
setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a body part from the file and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
|
||||
/// - Content-Type: #{mimeType} (HTTP Header)
|
||||
/// - Encoded file data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data.
|
||||
/// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header.
|
||||
/// - parameter fileName: The filename to associate with the file content in the `Content-Disposition` HTTP header.
|
||||
/// - parameter mimeType: The MIME type to associate with the file content in the `Content-Type` HTTP header.
|
||||
public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) {
|
||||
let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
|
||||
|
||||
//============================================================
|
||||
// Check 1 - is file URL?
|
||||
//============================================================
|
||||
|
||||
guard fileURL.isFileURL else {
|
||||
setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL))
|
||||
return
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// Check 2 - is file URL reachable?
|
||||
//============================================================
|
||||
|
||||
do {
|
||||
let isReachable = try fileURL.checkPromisedItemIsReachable()
|
||||
guard isReachable else {
|
||||
setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL))
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error))
|
||||
return
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// Check 3 - is file URL a directory?
|
||||
//============================================================
|
||||
|
||||
var isDirectory: ObjCBool = false
|
||||
let path = fileURL.path
|
||||
|
||||
guard FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else
|
||||
{
|
||||
setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL))
|
||||
return
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// Check 4 - can the file size be extracted?
|
||||
//============================================================
|
||||
|
||||
let bodyContentLength: UInt64
|
||||
|
||||
do {
|
||||
guard let fileSize = try FileManager.default.attributesOfItem(atPath: path)[.size] as? NSNumber else {
|
||||
setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL))
|
||||
return
|
||||
}
|
||||
|
||||
bodyContentLength = fileSize.uint64Value
|
||||
}
|
||||
catch {
|
||||
setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error))
|
||||
return
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// Check 5 - can a stream be created from file URL?
|
||||
//============================================================
|
||||
|
||||
guard let stream = InputStream(url: fileURL) else {
|
||||
setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL))
|
||||
return
|
||||
}
|
||||
|
||||
append(stream, withLength: bodyContentLength, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a body part from the stream and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
|
||||
/// - `Content-Type: #{mimeType}` (HTTP Header)
|
||||
/// - Encoded stream data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter stream: The input stream to encode in the multipart form data.
|
||||
/// - parameter length: The content length of the stream.
|
||||
/// - parameter name: The name to associate with the stream content in the `Content-Disposition` HTTP header.
|
||||
/// - parameter fileName: The filename to associate with the stream content in the `Content-Disposition` HTTP header.
|
||||
/// - parameter mimeType: The MIME type to associate with the stream content in the `Content-Type` HTTP header.
|
||||
public func append(
|
||||
_ stream: InputStream,
|
||||
withLength length: UInt64,
|
||||
name: String,
|
||||
fileName: String,
|
||||
mimeType: String)
|
||||
{
|
||||
let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
|
||||
append(stream, withLength: length, headers: headers)
|
||||
}
|
||||
|
||||
/// Creates a body part with the headers, stream and length and appends it to the multipart form data object.
|
||||
///
|
||||
/// The body part data will be encoded using the following format:
|
||||
///
|
||||
/// - HTTP headers
|
||||
/// - Encoded stream data
|
||||
/// - Multipart form boundary
|
||||
///
|
||||
/// - parameter stream: The input stream to encode in the multipart form data.
|
||||
/// - parameter length: The content length of the stream.
|
||||
/// - parameter headers: The HTTP headers for the body part.
|
||||
public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
|
||||
let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
|
||||
bodyParts.append(bodyPart)
|
||||
}
|
||||
|
||||
// MARK: - Data Encoding
|
||||
|
||||
/// Encodes all the appended body parts into a single `Data` value.
|
||||
///
|
||||
/// It is important to note that this method will load all the appended body parts into memory all at the same
|
||||
/// time. This method should only be used when the encoded data will have a small memory footprint. For large data
|
||||
/// cases, please use the `writeEncodedDataToDisk(fileURL:completionHandler:)` method.
|
||||
///
|
||||
/// - throws: An `AFError` if encoding encounters an error.
|
||||
///
|
||||
/// - returns: The encoded `Data` if encoding is successful.
|
||||
public func encode() throws -> Data {
|
||||
if let bodyPartError = bodyPartError {
|
||||
throw bodyPartError
|
||||
}
|
||||
|
||||
var encoded = Data()
|
||||
|
||||
bodyParts.first?.hasInitialBoundary = true
|
||||
bodyParts.last?.hasFinalBoundary = true
|
||||
|
||||
for bodyPart in bodyParts {
|
||||
let encodedData = try encode(bodyPart)
|
||||
encoded.append(encodedData)
|
||||
}
|
||||
|
||||
return encoded
|
||||
}
|
||||
|
||||
/// Writes the appended body parts into the given file URL.
|
||||
///
|
||||
/// This process is facilitated by reading and writing with input and output streams, respectively. Thus,
|
||||
/// this approach is very memory efficient and should be used for large body part data.
|
||||
///
|
||||
/// - parameter fileURL: The file URL to write the multipart form data into.
|
||||
///
|
||||
/// - throws: An `AFError` if encoding encounters an error.
|
||||
public func writeEncodedData(to fileURL: URL) throws {
|
||||
if let bodyPartError = bodyPartError {
|
||||
throw bodyPartError
|
||||
}
|
||||
|
||||
if FileManager.default.fileExists(atPath: fileURL.path) {
|
||||
throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL))
|
||||
} else if !fileURL.isFileURL {
|
||||
throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL))
|
||||
}
|
||||
|
||||
guard let outputStream = OutputStream(url: fileURL, append: false) else {
|
||||
throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL))
|
||||
}
|
||||
|
||||
outputStream.open()
|
||||
defer { outputStream.close() }
|
||||
|
||||
self.bodyParts.first?.hasInitialBoundary = true
|
||||
self.bodyParts.last?.hasFinalBoundary = true
|
||||
|
||||
for bodyPart in self.bodyParts {
|
||||
try write(bodyPart, to: outputStream)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private - Body Part Encoding
|
||||
|
||||
private func encode(_ bodyPart: BodyPart) throws -> Data {
|
||||
var encoded = Data()
|
||||
|
||||
let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
|
||||
encoded.append(initialData)
|
||||
|
||||
let headerData = encodeHeaders(for: bodyPart)
|
||||
encoded.append(headerData)
|
||||
|
||||
let bodyStreamData = try encodeBodyStream(for: bodyPart)
|
||||
encoded.append(bodyStreamData)
|
||||
|
||||
if bodyPart.hasFinalBoundary {
|
||||
encoded.append(finalBoundaryData())
|
||||
}
|
||||
|
||||
return encoded
|
||||
}
|
||||
|
||||
private func encodeHeaders(for bodyPart: BodyPart) -> Data {
|
||||
var headerText = ""
|
||||
|
||||
for (key, value) in bodyPart.headers {
|
||||
headerText += "\(key): \(value)\(EncodingCharacters.crlf)"
|
||||
}
|
||||
headerText += EncodingCharacters.crlf
|
||||
|
||||
return headerText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
|
||||
}
|
||||
|
||||
private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data {
|
||||
let inputStream = bodyPart.bodyStream
|
||||
inputStream.open()
|
||||
defer { inputStream.close() }
|
||||
|
||||
var encoded = Data()
|
||||
|
||||
while inputStream.hasBytesAvailable {
|
||||
var buffer = [UInt8](repeating: 0, count: streamBufferSize)
|
||||
let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
|
||||
|
||||
if let error = inputStream.streamError {
|
||||
throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error))
|
||||
}
|
||||
|
||||
if bytesRead > 0 {
|
||||
encoded.append(buffer, count: bytesRead)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return encoded
|
||||
}
|
||||
|
||||
// MARK: - Private - Writing Body Part to Output Stream
|
||||
|
||||
private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws {
|
||||
try writeInitialBoundaryData(for: bodyPart, to: outputStream)
|
||||
try writeHeaderData(for: bodyPart, to: outputStream)
|
||||
try writeBodyStream(for: bodyPart, to: outputStream)
|
||||
try writeFinalBoundaryData(for: bodyPart, to: outputStream)
|
||||
}
|
||||
|
||||
private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
|
||||
let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
|
||||
return try write(initialData, to: outputStream)
|
||||
}
|
||||
|
||||
private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
|
||||
let headerData = encodeHeaders(for: bodyPart)
|
||||
return try write(headerData, to: outputStream)
|
||||
}
|
||||
|
||||
private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
|
||||
let inputStream = bodyPart.bodyStream
|
||||
|
||||
inputStream.open()
|
||||
defer { inputStream.close() }
|
||||
|
||||
while inputStream.hasBytesAvailable {
|
||||
var buffer = [UInt8](repeating: 0, count: streamBufferSize)
|
||||
let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
|
||||
|
||||
if let streamError = inputStream.streamError {
|
||||
throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
|
||||
}
|
||||
|
||||
if bytesRead > 0 {
|
||||
if buffer.count != bytesRead {
|
||||
buffer = Array(buffer[0..<bytesRead])
|
||||
}
|
||||
|
||||
try write(&buffer, to: outputStream)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func writeFinalBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
|
||||
if bodyPart.hasFinalBoundary {
|
||||
return try write(finalBoundaryData(), to: outputStream)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private - Writing Buffered Data to Output Stream
|
||||
|
||||
private func write(_ data: Data, to outputStream: OutputStream) throws {
|
||||
var buffer = [UInt8](repeating: 0, count: data.count)
|
||||
data.copyBytes(to: &buffer, count: data.count)
|
||||
|
||||
return try write(&buffer, to: outputStream)
|
||||
}
|
||||
|
||||
private func write(_ buffer: inout [UInt8], to outputStream: OutputStream) throws {
|
||||
var bytesToWrite = buffer.count
|
||||
|
||||
while bytesToWrite > 0, outputStream.hasSpaceAvailable {
|
||||
let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
|
||||
|
||||
if let error = outputStream.streamError {
|
||||
throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error))
|
||||
}
|
||||
|
||||
bytesToWrite -= bytesWritten
|
||||
|
||||
if bytesToWrite > 0 {
|
||||
buffer = Array(buffer[bytesWritten..<buffer.count])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private - Mime Type
|
||||
|
||||
private func mimeType(forPathExtension pathExtension: String) -> String {
|
||||
if
|
||||
let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
|
||||
let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue()
|
||||
{
|
||||
return contentType as String
|
||||
}
|
||||
|
||||
return "application/octet-stream"
|
||||
}
|
||||
|
||||
// MARK: - Private - Content Headers
|
||||
|
||||
private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> [String: String] {
|
||||
var disposition = "form-data; name=\"\(name)\""
|
||||
if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
|
||||
|
||||
var headers = ["Content-Disposition": disposition]
|
||||
if let mimeType = mimeType { headers["Content-Type"] = mimeType }
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
// MARK: - Private - Boundary Encoding
|
||||
|
||||
private func initialBoundaryData() -> Data {
|
||||
return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary)
|
||||
}
|
||||
|
||||
private func encapsulatedBoundaryData() -> Data {
|
||||
return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary)
|
||||
}
|
||||
|
||||
private func finalBoundaryData() -> Data {
|
||||
return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary)
|
||||
}
|
||||
|
||||
// MARK: - Private - Errors
|
||||
|
||||
private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) {
|
||||
guard bodyPartError == nil else { return }
|
||||
bodyPartError = AFError.multipartEncodingFailed(reason: reason)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// NetworkReachabilityManager.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
import Foundation
|
||||
import SystemConfiguration
|
||||
|
||||
/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
|
||||
/// WiFi network interfaces.
|
||||
///
|
||||
/// Reachability can be used to determine background information about why a network operation failed, or to retry
|
||||
/// network requests when a connection is established. It should not be used to prevent a user from initiating a network
|
||||
/// request, as it's possible that an initial request may be required to establish reachability.
|
||||
open class NetworkReachabilityManager {
|
||||
/**
|
||||
Defines the various states of network reachability.
|
||||
|
||||
- Unknown: It is unknown whether the network is reachable.
|
||||
- NotReachable: The network is not reachable.
|
||||
- ReachableOnWWAN: The network is reachable over the WWAN connection.
|
||||
- ReachableOnWiFi: The network is reachable over the WiFi connection.
|
||||
*/
|
||||
|
||||
|
||||
/// Defines the various states of network reachability.
|
||||
///
|
||||
/// - unknown: It is unknown whether the network is reachable.
|
||||
/// - notReachable: The network is not reachable.
|
||||
/// - reachable: The network is reachable.
|
||||
public enum NetworkReachabilityStatus {
|
||||
case unknown
|
||||
case notReachable
|
||||
case reachable(ConnectionType)
|
||||
}
|
||||
|
||||
/// Defines the various connection types detected by reachability flags.
|
||||
///
|
||||
/// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi.
|
||||
/// - wwan: The connection type is a WWAN connection.
|
||||
public enum ConnectionType {
|
||||
case ethernetOrWiFi
|
||||
case wwan
|
||||
}
|
||||
|
||||
/// A closure executed when the network reachability status changes. The closure takes a single argument: the
|
||||
/// network reachability status.
|
||||
public typealias Listener = (NetworkReachabilityStatus) -> Void
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// Whether the network is currently reachable.
|
||||
open var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }
|
||||
|
||||
/// Whether the network is currently reachable over the WWAN interface.
|
||||
open var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) }
|
||||
|
||||
/// Whether the network is currently reachable over Ethernet or WiFi interface.
|
||||
open var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) }
|
||||
|
||||
/// The current network reachability status.
|
||||
open var networkReachabilityStatus: NetworkReachabilityStatus {
|
||||
guard let flags = self.flags else { return .unknown }
|
||||
return networkReachabilityStatusForFlags(flags)
|
||||
}
|
||||
|
||||
/// The dispatch queue to execute the `listener` closure on.
|
||||
open var listenerQueue: DispatchQueue = DispatchQueue.main
|
||||
|
||||
/// A closure executed when the network reachability status changes.
|
||||
open var listener: Listener?
|
||||
|
||||
private var flags: SCNetworkReachabilityFlags? {
|
||||
var flags = SCNetworkReachabilityFlags()
|
||||
|
||||
if SCNetworkReachabilityGetFlags(reachability, &flags) {
|
||||
return flags
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private let reachability: SCNetworkReachability
|
||||
private var previousFlags: SCNetworkReachabilityFlags
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
/// Creates a `NetworkReachabilityManager` instance with the specified host.
|
||||
///
|
||||
/// - parameter host: The host used to evaluate network reachability.
|
||||
///
|
||||
/// - returns: The new `NetworkReachabilityManager` instance.
|
||||
public convenience init?(host: String) {
|
||||
guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
|
||||
self.init(reachability: reachability)
|
||||
}
|
||||
|
||||
/// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0.
|
||||
///
|
||||
/// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing
|
||||
/// status of the device, both IPv4 and IPv6.
|
||||
///
|
||||
/// - returns: The new `NetworkReachabilityManager` instance.
|
||||
public convenience init?() {
|
||||
var address = sockaddr_in()
|
||||
address.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
|
||||
address.sin_family = sa_family_t(AF_INET)
|
||||
|
||||
guard let reachability = withUnsafePointer(to: &address, { pointer in
|
||||
return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size) {
|
||||
return SCNetworkReachabilityCreateWithAddress(nil, $0)
|
||||
}
|
||||
}) else { return nil }
|
||||
|
||||
self.init(reachability: reachability)
|
||||
}
|
||||
|
||||
private init(reachability: SCNetworkReachability) {
|
||||
self.reachability = reachability
|
||||
self.previousFlags = SCNetworkReachabilityFlags()
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopListening()
|
||||
}
|
||||
|
||||
// MARK: - Listening
|
||||
|
||||
/// Starts listening for changes in network reachability status.
|
||||
///
|
||||
/// - returns: `true` if listening was started successfully, `false` otherwise.
|
||||
@discardableResult
|
||||
open func startListening() -> Bool {
|
||||
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
|
||||
context.info = Unmanaged.passUnretained(self).toOpaque()
|
||||
|
||||
let callbackEnabled = SCNetworkReachabilitySetCallback(
|
||||
reachability,
|
||||
{ (_, flags, info) in
|
||||
let reachability = Unmanaged<NetworkReachabilityManager>.fromOpaque(info!).takeUnretainedValue()
|
||||
reachability.notifyListener(flags)
|
||||
},
|
||||
&context
|
||||
)
|
||||
|
||||
let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)
|
||||
|
||||
listenerQueue.async {
|
||||
self.previousFlags = SCNetworkReachabilityFlags()
|
||||
self.notifyListener(self.flags ?? SCNetworkReachabilityFlags())
|
||||
}
|
||||
|
||||
return callbackEnabled && queueEnabled
|
||||
}
|
||||
|
||||
/// Stops listening for changes in network reachability status.
|
||||
open func stopListening() {
|
||||
SCNetworkReachabilitySetCallback(reachability, nil, nil)
|
||||
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
|
||||
}
|
||||
|
||||
// MARK: - Internal - Listener Notification
|
||||
|
||||
func notifyListener(_ flags: SCNetworkReachabilityFlags) {
|
||||
guard previousFlags != flags else { return }
|
||||
previousFlags = flags
|
||||
|
||||
listener?(networkReachabilityStatusForFlags(flags))
|
||||
}
|
||||
|
||||
// MARK: - Internal - Network Reachability Status
|
||||
|
||||
func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {
|
||||
guard flags.contains(.reachable) else { return .notReachable }
|
||||
|
||||
var networkStatus: NetworkReachabilityStatus = .notReachable
|
||||
|
||||
if !flags.contains(.connectionRequired) { networkStatus = .reachable(.ethernetOrWiFi) }
|
||||
|
||||
if flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) {
|
||||
if !flags.contains(.interventionRequired) { networkStatus = .reachable(.ethernetOrWiFi) }
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) }
|
||||
#endif
|
||||
|
||||
return networkStatus
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
|
||||
|
||||
/// Returns whether the two network reachability status values are equal.
|
||||
///
|
||||
/// - parameter lhs: The left-hand side value to compare.
|
||||
/// - parameter rhs: The right-hand side value to compare.
|
||||
///
|
||||
/// - returns: `true` if the two values are equal, `false` otherwise.
|
||||
public func ==(
|
||||
lhs: NetworkReachabilityManager.NetworkReachabilityStatus,
|
||||
rhs: NetworkReachabilityManager.NetworkReachabilityStatus)
|
||||
-> Bool
|
||||
{
|
||||
switch (lhs, rhs) {
|
||||
case (.unknown, .unknown):
|
||||
return true
|
||||
case (.notReachable, .notReachable):
|
||||
return true
|
||||
case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)):
|
||||
return lhsConnectionType == rhsConnectionType
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
52
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Notifications.swift
generated
Normal file
52
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Notifications.swift
generated
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// Notifications.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Notification.Name {
|
||||
/// Used as a namespace for all `URLSessionTask` related notifications.
|
||||
public struct Task {
|
||||
/// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`.
|
||||
public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume")
|
||||
|
||||
/// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`.
|
||||
public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend")
|
||||
|
||||
/// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`.
|
||||
public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel")
|
||||
|
||||
/// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`.
|
||||
public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension Notification {
|
||||
/// Used as a namespace for all `Notification` user info dictionary keys.
|
||||
public struct Key {
|
||||
/// User info dictionary key representing the `URLSessionTask` associated with the notification.
|
||||
public static let Task = "org.alamofire.notification.key.task"
|
||||
}
|
||||
}
|
||||
373
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/ParameterEncoding.swift
generated
Normal file
373
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/ParameterEncoding.swift
generated
Normal file
@@ -0,0 +1,373 @@
|
||||
//
|
||||
// ParameterEncoding.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// HTTP method definitions.
|
||||
///
|
||||
/// See https://tools.ietf.org/html/rfc7231#section-4.3
|
||||
public enum HTTPMethod: String {
|
||||
case options = "OPTIONS"
|
||||
case get = "GET"
|
||||
case head = "HEAD"
|
||||
case post = "POST"
|
||||
case put = "PUT"
|
||||
case patch = "PATCH"
|
||||
case delete = "DELETE"
|
||||
case trace = "TRACE"
|
||||
case connect = "CONNECT"
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// A dictionary of parameters to apply to a `URLRequest`.
|
||||
public typealias Parameters = [String: Any]
|
||||
|
||||
/// A type used to define how a set of parameters are applied to a `URLRequest`.
|
||||
public protocol ParameterEncoding {
|
||||
/// Creates a URL request by encoding parameters and applying them onto an existing request.
|
||||
///
|
||||
/// - parameter urlRequest: The request to have parameters applied.
|
||||
/// - parameter parameters: The parameters to apply.
|
||||
///
|
||||
/// - throws: An `AFError.parameterEncodingFailed` error if encoding fails.
|
||||
///
|
||||
/// - returns: The encoded request.
|
||||
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
|
||||
/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
|
||||
/// the HTTP body depends on the destination of the encoding.
|
||||
///
|
||||
/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
|
||||
/// `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification for how to encode
|
||||
/// collection types, the convention of appending `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending
|
||||
/// the key surrounded by square brackets for nested dictionary values (`foo[bar]=baz`).
|
||||
public struct URLEncoding: ParameterEncoding {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
/// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
|
||||
/// resulting URL request.
|
||||
///
|
||||
/// - methodDependent: Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE`
|
||||
/// requests and sets as the HTTP body for requests with any other HTTP method.
|
||||
/// - queryString: Sets or appends encoded query string result to existing query string.
|
||||
/// - httpBody: Sets encoded query string result as the HTTP body of the URL request.
|
||||
public enum Destination {
|
||||
case methodDependent, queryString, httpBody
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// Returns a default `URLEncoding` instance.
|
||||
public static var `default`: URLEncoding { return URLEncoding() }
|
||||
|
||||
/// Returns a `URLEncoding` instance with a `.methodDependent` destination.
|
||||
public static var methodDependent: URLEncoding { return URLEncoding() }
|
||||
|
||||
/// Returns a `URLEncoding` instance with a `.queryString` destination.
|
||||
public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
|
||||
|
||||
/// Returns a `URLEncoding` instance with an `.httpBody` destination.
|
||||
public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
|
||||
|
||||
/// The destination defining where the encoded query string is to be applied to the URL request.
|
||||
public let destination: Destination
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Creates a `URLEncoding` instance using the specified destination.
|
||||
///
|
||||
/// - parameter destination: The destination defining where the encoded query string is to be applied.
|
||||
///
|
||||
/// - returns: The new `URLEncoding` instance.
|
||||
public init(destination: Destination = .methodDependent) {
|
||||
self.destination = destination
|
||||
}
|
||||
|
||||
// MARK: Encoding
|
||||
|
||||
/// Creates a URL request by encoding parameters and applying them onto an existing request.
|
||||
///
|
||||
/// - parameter urlRequest: The request to have parameters applied.
|
||||
/// - parameter parameters: The parameters to apply.
|
||||
///
|
||||
/// - throws: An `Error` if the encoding process encounters an error.
|
||||
///
|
||||
/// - returns: The encoded request.
|
||||
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
|
||||
var urlRequest = try urlRequest.asURLRequest()
|
||||
|
||||
guard let parameters = parameters else { return urlRequest }
|
||||
|
||||
if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
|
||||
guard let url = urlRequest.url else {
|
||||
throw AFError.parameterEncodingFailed(reason: .missingURL)
|
||||
}
|
||||
|
||||
if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
|
||||
let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
|
||||
urlComponents.percentEncodedQuery = percentEncodedQuery
|
||||
urlRequest.url = urlComponents.url
|
||||
}
|
||||
} else {
|
||||
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
|
||||
urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||
}
|
||||
|
||||
urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
|
||||
}
|
||||
|
||||
return urlRequest
|
||||
}
|
||||
|
||||
/// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion.
|
||||
///
|
||||
/// - parameter key: The key of the query component.
|
||||
/// - parameter value: The value of the query component.
|
||||
///
|
||||
/// - returns: The percent-escaped, URL encoded query string components.
|
||||
public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
|
||||
var components: [(String, String)] = []
|
||||
|
||||
if let dictionary = value as? [String: Any] {
|
||||
for (nestedKey, value) in dictionary {
|
||||
components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
|
||||
}
|
||||
} else if let array = value as? [Any] {
|
||||
for value in array {
|
||||
components += queryComponents(fromKey: "\(key)[]", value: value)
|
||||
}
|
||||
} else if let value = value as? NSNumber {
|
||||
if value.isBool {
|
||||
components.append((escape(key), escape((value.boolValue ? "1" : "0"))))
|
||||
} else {
|
||||
components.append((escape(key), escape("\(value)")))
|
||||
}
|
||||
} else if let bool = value as? Bool {
|
||||
components.append((escape(key), escape((bool ? "1" : "0"))))
|
||||
} else {
|
||||
components.append((escape(key), escape("\(value)")))
|
||||
}
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
/// Returns a percent-escaped string following RFC 3986 for a query string key or value.
|
||||
///
|
||||
/// RFC 3986 states that the following characters are "reserved" characters.
|
||||
///
|
||||
/// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
|
||||
/// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
|
||||
///
|
||||
/// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
|
||||
/// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
|
||||
/// should be percent-escaped in the query string.
|
||||
///
|
||||
/// - parameter string: The string to be percent-escaped.
|
||||
///
|
||||
/// - returns: The percent-escaped string.
|
||||
public func escape(_ string: String) -> String {
|
||||
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
|
||||
let subDelimitersToEncode = "!$&'()*+,;="
|
||||
|
||||
var allowedCharacterSet = CharacterSet.urlQueryAllowed
|
||||
allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
|
||||
|
||||
return string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
|
||||
}
|
||||
|
||||
private func query(_ parameters: [String: Any]) -> String {
|
||||
var components: [(String, String)] = []
|
||||
|
||||
for key in parameters.keys.sorted(by: <) {
|
||||
let value = parameters[key]!
|
||||
components += queryComponents(fromKey: key, value: value)
|
||||
}
|
||||
|
||||
return components.map { "\($0)=\($1)" }.joined(separator: "&")
|
||||
}
|
||||
|
||||
private func encodesParametersInURL(with method: HTTPMethod) -> Bool {
|
||||
switch destination {
|
||||
case .queryString:
|
||||
return true
|
||||
case .httpBody:
|
||||
return false
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
switch method {
|
||||
case .get, .head, .delete:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
|
||||
/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
|
||||
public struct JSONEncoding: ParameterEncoding {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// Returns a `JSONEncoding` instance with default writing options.
|
||||
public static var `default`: JSONEncoding { return JSONEncoding() }
|
||||
|
||||
/// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
|
||||
public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) }
|
||||
|
||||
/// The options for writing the parameters as JSON data.
|
||||
public let options: JSONSerialization.WritingOptions
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Creates a `JSONEncoding` instance using the specified options.
|
||||
///
|
||||
/// - parameter options: The options for writing the parameters as JSON data.
|
||||
///
|
||||
/// - returns: The new `JSONEncoding` instance.
|
||||
public init(options: JSONSerialization.WritingOptions = []) {
|
||||
self.options = options
|
||||
}
|
||||
|
||||
// MARK: Encoding
|
||||
|
||||
/// Creates a URL request by encoding parameters and applying them onto an existing request.
|
||||
///
|
||||
/// - parameter urlRequest: The request to have parameters applied.
|
||||
/// - parameter parameters: The parameters to apply.
|
||||
///
|
||||
/// - throws: An `Error` if the encoding process encounters an error.
|
||||
///
|
||||
/// - returns: The encoded request.
|
||||
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
|
||||
var urlRequest = try urlRequest.asURLRequest()
|
||||
|
||||
guard let parameters = parameters else { return urlRequest }
|
||||
|
||||
do {
|
||||
let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
|
||||
|
||||
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
|
||||
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
}
|
||||
|
||||
urlRequest.httpBody = data
|
||||
} catch {
|
||||
throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
|
||||
}
|
||||
|
||||
return urlRequest
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the
|
||||
/// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header
|
||||
/// field of an encoded request is set to `application/x-plist`.
|
||||
public struct PropertyListEncoding: ParameterEncoding {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// Returns a default `PropertyListEncoding` instance.
|
||||
public static var `default`: PropertyListEncoding { return PropertyListEncoding() }
|
||||
|
||||
/// Returns a `PropertyListEncoding` instance with xml formatting and default writing options.
|
||||
public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) }
|
||||
|
||||
/// Returns a `PropertyListEncoding` instance with binary formatting and default writing options.
|
||||
public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) }
|
||||
|
||||
/// The property list serialization format.
|
||||
public let format: PropertyListSerialization.PropertyListFormat
|
||||
|
||||
/// The options for writing the parameters as plist data.
|
||||
public let options: PropertyListSerialization.WriteOptions
|
||||
|
||||
// MARK: Initialization
|
||||
|
||||
/// Creates a `PropertyListEncoding` instance using the specified format and options.
|
||||
///
|
||||
/// - parameter format: The property list serialization format.
|
||||
/// - parameter options: The options for writing the parameters as plist data.
|
||||
///
|
||||
/// - returns: The new `PropertyListEncoding` instance.
|
||||
public init(
|
||||
format: PropertyListSerialization.PropertyListFormat = .xml,
|
||||
options: PropertyListSerialization.WriteOptions = 0)
|
||||
{
|
||||
self.format = format
|
||||
self.options = options
|
||||
}
|
||||
|
||||
// MARK: Encoding
|
||||
|
||||
/// Creates a URL request by encoding parameters and applying them onto an existing request.
|
||||
///
|
||||
/// - parameter urlRequest: The request to have parameters applied.
|
||||
/// - parameter parameters: The parameters to apply.
|
||||
///
|
||||
/// - throws: An `Error` if the encoding process encounters an error.
|
||||
///
|
||||
/// - returns: The encoded request.
|
||||
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
|
||||
var urlRequest = try urlRequest.asURLRequest()
|
||||
|
||||
guard let parameters = parameters else { return urlRequest }
|
||||
|
||||
do {
|
||||
let data = try PropertyListSerialization.data(
|
||||
fromPropertyList: parameters,
|
||||
format: format,
|
||||
options: options
|
||||
)
|
||||
|
||||
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
|
||||
urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
|
||||
}
|
||||
|
||||
urlRequest.httpBody = data
|
||||
} catch {
|
||||
throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error))
|
||||
}
|
||||
|
||||
return urlRequest
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension NSNumber {
|
||||
fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
|
||||
}
|
||||
600
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Request.swift
generated
Normal file
600
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Request.swift
generated
Normal file
@@ -0,0 +1,600 @@
|
||||
//
|
||||
// Request.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
|
||||
public protocol RequestAdapter {
|
||||
/// Inspects and adapts the specified `URLRequest` in some manner if necessary and returns the result.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request to adapt.
|
||||
///
|
||||
/// - throws: An `Error` if the adaptation encounters an error.
|
||||
///
|
||||
/// - returns: The adapted `URLRequest`.
|
||||
func adapt(_ urlRequest: URLRequest) throws -> URLRequest
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// A closure executed when the `RequestRetrier` determines whether a `Request` should be retried or not.
|
||||
public typealias RequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval) -> Void
|
||||
|
||||
/// A type that determines whether a request should be retried after being executed by the specified session manager
|
||||
/// and encountering an error.
|
||||
public protocol RequestRetrier {
|
||||
/// Determines whether the `Request` should be retried by calling the `completion` closure.
|
||||
///
|
||||
/// This operation is fully asychronous. Any amount of time can be taken to determine whether the request needs
|
||||
/// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
|
||||
/// cleaned up after.
|
||||
///
|
||||
/// - parameter manager: The session manager the request was executed on.
|
||||
/// - parameter request: The request that failed due to the encountered error.
|
||||
/// - parameter error: The error encountered when executing the request.
|
||||
/// - parameter completion: The completion closure to be executed when retry decision has been determined.
|
||||
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
protocol TaskConvertible {
|
||||
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask
|
||||
}
|
||||
|
||||
/// A dictionary of headers to apply to a `URLRequest`.
|
||||
public typealias HTTPHeaders = [String: String]
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Responsible for sending a request and receiving the response and associated data from the server, as well as
|
||||
/// managing its underlying `URLSessionTask`.
|
||||
open class Request {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
/// A closure executed when monitoring upload or download progress of a request.
|
||||
public typealias ProgressHandler = (Progress) -> Void
|
||||
|
||||
enum RequestTask {
|
||||
case data(TaskConvertible?, URLSessionTask?)
|
||||
case download(TaskConvertible?, URLSessionTask?)
|
||||
case upload(TaskConvertible?, URLSessionTask?)
|
||||
case stream(TaskConvertible?, URLSessionTask?)
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The delegate for the underlying task.
|
||||
open internal(set) var delegate: TaskDelegate {
|
||||
get {
|
||||
taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
|
||||
return taskDelegate
|
||||
}
|
||||
set {
|
||||
taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
|
||||
taskDelegate = newValue
|
||||
}
|
||||
}
|
||||
|
||||
/// The underlying task.
|
||||
open var task: URLSessionTask? { return delegate.task }
|
||||
|
||||
/// The session belonging to the underlying task.
|
||||
open let session: URLSession
|
||||
|
||||
/// The request sent or to be sent to the server.
|
||||
open var request: URLRequest? { return task?.originalRequest }
|
||||
|
||||
/// The response received from the server, if any.
|
||||
open var response: HTTPURLResponse? { return task?.response as? HTTPURLResponse }
|
||||
|
||||
let originalTask: TaskConvertible?
|
||||
|
||||
var startTime: CFAbsoluteTime?
|
||||
var endTime: CFAbsoluteTime?
|
||||
|
||||
var validations: [() -> Void] = []
|
||||
|
||||
private var taskDelegate: TaskDelegate
|
||||
private var taskDelegateLock = NSLock()
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
init(session: URLSession, requestTask: RequestTask, error: Error? = nil) {
|
||||
self.session = session
|
||||
|
||||
switch requestTask {
|
||||
case .data(let originalTask, let task):
|
||||
taskDelegate = DataTaskDelegate(task: task)
|
||||
self.originalTask = originalTask
|
||||
case .download(let originalTask, let task):
|
||||
taskDelegate = DownloadTaskDelegate(task: task)
|
||||
self.originalTask = originalTask
|
||||
case .upload(let originalTask, let task):
|
||||
taskDelegate = UploadTaskDelegate(task: task)
|
||||
self.originalTask = originalTask
|
||||
case .stream(let originalTask, let task):
|
||||
taskDelegate = TaskDelegate(task: task)
|
||||
self.originalTask = originalTask
|
||||
}
|
||||
|
||||
delegate.error = error
|
||||
delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() }
|
||||
}
|
||||
|
||||
// MARK: Authentication
|
||||
|
||||
/// Associates an HTTP Basic credential with the request.
|
||||
///
|
||||
/// - parameter user: The user.
|
||||
/// - parameter password: The password.
|
||||
/// - parameter persistence: The URL credential persistence. `.ForSession` by default.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func authenticate(
|
||||
user: String,
|
||||
password: String,
|
||||
persistence: URLCredential.Persistence = .forSession)
|
||||
-> Self
|
||||
{
|
||||
let credential = URLCredential(user: user, password: password, persistence: persistence)
|
||||
return authenticate(usingCredential: credential)
|
||||
}
|
||||
|
||||
/// Associates a specified credential with the request.
|
||||
///
|
||||
/// - parameter credential: The credential.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func authenticate(usingCredential credential: URLCredential) -> Self {
|
||||
delegate.credential = credential
|
||||
return self
|
||||
}
|
||||
|
||||
/// Returns a base64 encoded basic authentication credential as an authorization header tuple.
|
||||
///
|
||||
/// - parameter user: The user.
|
||||
/// - parameter password: The password.
|
||||
///
|
||||
/// - returns: A tuple with Authorization header and credential value if encoding succeeds, `nil` otherwise.
|
||||
open static func authorizationHeader(user: String, password: String) -> (key: String, value: String)? {
|
||||
guard let data = "\(user):\(password)".data(using: .utf8) else { return nil }
|
||||
|
||||
let credential = data.base64EncodedString(options: [])
|
||||
|
||||
return (key: "Authorization", value: "Basic \(credential)")
|
||||
}
|
||||
|
||||
// MARK: State
|
||||
|
||||
/// Resumes the request.
|
||||
open func resume() {
|
||||
guard let task = task else { delegate.queue.isSuspended = false ; return }
|
||||
|
||||
if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() }
|
||||
|
||||
task.resume()
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.Task.DidResume,
|
||||
object: self,
|
||||
userInfo: [Notification.Key.Task: task]
|
||||
)
|
||||
}
|
||||
|
||||
/// Suspends the request.
|
||||
open func suspend() {
|
||||
guard let task = task else { return }
|
||||
|
||||
task.suspend()
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.Task.DidSuspend,
|
||||
object: self,
|
||||
userInfo: [Notification.Key.Task: task]
|
||||
)
|
||||
}
|
||||
|
||||
/// Cancels the request.
|
||||
open func cancel() {
|
||||
guard let task = task else { return }
|
||||
|
||||
task.cancel()
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.Task.DidCancel,
|
||||
object: self,
|
||||
userInfo: [Notification.Key.Task: task]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomStringConvertible
|
||||
|
||||
extension Request: CustomStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes the HTTP method and URL, as
|
||||
/// well as the response status code if a response has been received.
|
||||
open var description: String {
|
||||
var components: [String] = []
|
||||
|
||||
if let HTTPMethod = request?.httpMethod {
|
||||
components.append(HTTPMethod)
|
||||
}
|
||||
|
||||
if let urlString = request?.url?.absoluteString {
|
||||
components.append(urlString)
|
||||
}
|
||||
|
||||
if let response = response {
|
||||
components.append("(\(response.statusCode))")
|
||||
}
|
||||
|
||||
return components.joined(separator: " ")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomDebugStringConvertible
|
||||
|
||||
extension Request: CustomDebugStringConvertible {
|
||||
/// The textual representation used when written to an output stream, in the form of a cURL command.
|
||||
open var debugDescription: String {
|
||||
return cURLRepresentation()
|
||||
}
|
||||
|
||||
func cURLRepresentation() -> String {
|
||||
var components = ["$ curl -i"]
|
||||
|
||||
guard let request = self.request,
|
||||
let url = request.url,
|
||||
let host = url.host
|
||||
else {
|
||||
return "$ curl command could not be created"
|
||||
}
|
||||
|
||||
if let httpMethod = request.httpMethod, httpMethod != "GET" {
|
||||
components.append("-X \(httpMethod)")
|
||||
}
|
||||
|
||||
if let credentialStorage = self.session.configuration.urlCredentialStorage {
|
||||
let protectionSpace = URLProtectionSpace(
|
||||
host: host,
|
||||
port: url.port ?? 0,
|
||||
protocol: url.scheme,
|
||||
realm: host,
|
||||
authenticationMethod: NSURLAuthenticationMethodHTTPBasic
|
||||
)
|
||||
|
||||
if let credentials = credentialStorage.credentials(for: protectionSpace)?.values {
|
||||
for credential in credentials {
|
||||
components.append("-u \(credential.user!):\(credential.password!)")
|
||||
}
|
||||
} else {
|
||||
if let credential = delegate.credential {
|
||||
components.append("-u \(credential.user!):\(credential.password!)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if session.configuration.httpShouldSetCookies {
|
||||
if
|
||||
let cookieStorage = session.configuration.httpCookieStorage,
|
||||
let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty
|
||||
{
|
||||
let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value);" }
|
||||
components.append("-b \"\(string.substring(to: string.characters.index(before: string.endIndex)))\"")
|
||||
}
|
||||
}
|
||||
|
||||
var headers: [AnyHashable: Any] = [:]
|
||||
|
||||
if let additionalHeaders = session.configuration.httpAdditionalHeaders {
|
||||
for (field, value) in additionalHeaders where field != AnyHashable("Cookie") {
|
||||
headers[field] = value
|
||||
}
|
||||
}
|
||||
|
||||
if let headerFields = request.allHTTPHeaderFields {
|
||||
for (field, value) in headerFields where field != "Cookie" {
|
||||
headers[field] = value
|
||||
}
|
||||
}
|
||||
|
||||
for (field, value) in headers {
|
||||
components.append("-H \"\(field): \(value)\"")
|
||||
}
|
||||
|
||||
if let httpBodyData = request.httpBody, let httpBody = String(data: httpBodyData, encoding: .utf8) {
|
||||
var escapedBody = httpBody.replacingOccurrences(of: "\\\"", with: "\\\\\"")
|
||||
escapedBody = escapedBody.replacingOccurrences(of: "\"", with: "\\\"")
|
||||
|
||||
components.append("-d \"\(escapedBody)\"")
|
||||
}
|
||||
|
||||
components.append("\"\(url.absoluteString)\"")
|
||||
|
||||
return components.joined(separator: " \\\n\t")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Specific type of `Request` that manages an underlying `URLSessionDataTask`.
|
||||
open class DataRequest: Request {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
struct Requestable: TaskConvertible {
|
||||
let urlRequest: URLRequest
|
||||
|
||||
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
|
||||
let urlRequest = try self.urlRequest.adapt(using: adapter)
|
||||
return queue.syncResult { session.dataTask(with: urlRequest) }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The progress of fetching the response data from the server for the request.
|
||||
open var progress: Progress { return dataDelegate.progress }
|
||||
|
||||
var dataDelegate: DataTaskDelegate { return delegate as! DataTaskDelegate }
|
||||
|
||||
// MARK: Stream
|
||||
|
||||
/// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server.
|
||||
///
|
||||
/// This closure returns the bytes most recently received from the server, not including data from previous calls.
|
||||
/// If this closure is set, data will only be available within this closure, and will not be saved elsewhere. It is
|
||||
/// also important to note that the server data in any `Response` object will be `nil`.
|
||||
///
|
||||
/// - parameter closure: The code to be executed periodically during the lifecycle of the request.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func stream(closure: ((Data) -> Void)? = nil) -> Self {
|
||||
dataDelegate.dataStream = closure
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Progress
|
||||
|
||||
/// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server.
|
||||
///
|
||||
/// - parameter queue: The dispatch queue to execute the closure on.
|
||||
/// - parameter closure: The code to be executed periodically as data is read from the server.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
|
||||
dataDelegate.progressHandler = (closure, queue)
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Specific type of `Request` that manages an underlying `URLSessionDownloadTask`.
|
||||
open class DownloadRequest: Request {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
/// A collection of options to be executed prior to moving a downloaded file from the temporary URL to the
|
||||
/// destination URL.
|
||||
public struct DownloadOptions: OptionSet {
|
||||
/// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol.
|
||||
public let rawValue: UInt
|
||||
|
||||
/// A `DownloadOptions` flag that creates intermediate directories for the destination URL if specified.
|
||||
public static let createIntermediateDirectories = DownloadOptions(rawValue: 1 << 0)
|
||||
|
||||
/// A `DownloadOptions` flag that removes a previous file from the destination URL if specified.
|
||||
public static let removePreviousFile = DownloadOptions(rawValue: 1 << 1)
|
||||
|
||||
/// Creates a `DownloadFileDestinationOptions` instance with the specified raw value.
|
||||
///
|
||||
/// - parameter rawValue: The raw bitmask value for the option.
|
||||
///
|
||||
/// - returns: A new log level instance.
|
||||
public init(rawValue: UInt) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
}
|
||||
|
||||
/// A closure executed once a download request has successfully completed in order to determine where to move the
|
||||
/// temporary file written to during the download process. The closure takes two arguments: the temporary file URL
|
||||
/// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and
|
||||
/// the options defining how the file should be moved.
|
||||
public typealias DownloadFileDestination = (
|
||||
_ temporaryURL: URL,
|
||||
_ response: HTTPURLResponse)
|
||||
-> (destinationURL: URL, options: DownloadOptions)
|
||||
|
||||
enum Downloadable: TaskConvertible {
|
||||
case request(URLRequest)
|
||||
case resumeData(Data)
|
||||
|
||||
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
|
||||
let task: URLSessionTask
|
||||
|
||||
switch self {
|
||||
case let .request(urlRequest):
|
||||
let urlRequest = try urlRequest.adapt(using: adapter)
|
||||
task = queue.syncResult { session.downloadTask(with: urlRequest) }
|
||||
case let .resumeData(resumeData):
|
||||
task = queue.syncResult { session.downloadTask(withResumeData: resumeData) }
|
||||
}
|
||||
|
||||
return task
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The resume data of the underlying download task if available after a failure.
|
||||
open var resumeData: Data? { return downloadDelegate.resumeData }
|
||||
|
||||
/// The progress of downloading the response data from the server for the request.
|
||||
open var progress: Progress { return downloadDelegate.progress }
|
||||
|
||||
var downloadDelegate: DownloadTaskDelegate { return delegate as! DownloadTaskDelegate }
|
||||
|
||||
// MARK: State
|
||||
|
||||
/// Cancels the request.
|
||||
open override func cancel() {
|
||||
downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 }
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.Task.DidCancel,
|
||||
object: self,
|
||||
userInfo: [Notification.Key.Task: task]
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: Progress
|
||||
|
||||
/// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server.
|
||||
///
|
||||
/// - parameter queue: The dispatch queue to execute the closure on.
|
||||
/// - parameter closure: The code to be executed periodically as data is read from the server.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
|
||||
downloadDelegate.progressHandler = (closure, queue)
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Destination
|
||||
|
||||
/// Creates a download file destination closure which uses the default file manager to move the temporary file to a
|
||||
/// file URL in the first available directory with the specified search path directory and search path domain mask.
|
||||
///
|
||||
/// - parameter directory: The search path directory. `.DocumentDirectory` by default.
|
||||
/// - parameter domain: The search path domain mask. `.UserDomainMask` by default.
|
||||
///
|
||||
/// - returns: A download file destination closure.
|
||||
open class func suggestedDownloadDestination(
|
||||
for directory: FileManager.SearchPathDirectory = .documentDirectory,
|
||||
in domain: FileManager.SearchPathDomainMask = .userDomainMask)
|
||||
-> DownloadFileDestination
|
||||
{
|
||||
return { temporaryURL, response in
|
||||
let directoryURLs = FileManager.default.urls(for: directory, in: domain)
|
||||
|
||||
if !directoryURLs.isEmpty {
|
||||
return (directoryURLs[0].appendingPathComponent(response.suggestedFilename!), [])
|
||||
}
|
||||
|
||||
return (temporaryURL, [])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Specific type of `Request` that manages an underlying `URLSessionUploadTask`.
|
||||
open class UploadRequest: DataRequest {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
enum Uploadable: TaskConvertible {
|
||||
case data(Data, URLRequest)
|
||||
case file(URL, URLRequest)
|
||||
case stream(InputStream, URLRequest)
|
||||
|
||||
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
|
||||
let task: URLSessionTask
|
||||
|
||||
switch self {
|
||||
case let .data(data, urlRequest):
|
||||
let urlRequest = try urlRequest.adapt(using: adapter)
|
||||
task = queue.syncResult { session.uploadTask(with: urlRequest, from: data) }
|
||||
case let .file(url, urlRequest):
|
||||
let urlRequest = try urlRequest.adapt(using: adapter)
|
||||
task = queue.syncResult { session.uploadTask(with: urlRequest, fromFile: url) }
|
||||
case let .stream(_, urlRequest):
|
||||
let urlRequest = try urlRequest.adapt(using: adapter)
|
||||
task = queue.syncResult { session.uploadTask(withStreamedRequest: urlRequest) }
|
||||
}
|
||||
|
||||
return task
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The progress of uploading the payload to the server for the upload request.
|
||||
open var uploadProgress: Progress { return uploadDelegate.uploadProgress }
|
||||
|
||||
var uploadDelegate: UploadTaskDelegate { return delegate as! UploadTaskDelegate }
|
||||
|
||||
// MARK: Upload Progress
|
||||
|
||||
/// Sets a closure to be called periodically during the lifecycle of the `UploadRequest` as data is sent to
|
||||
/// the server.
|
||||
///
|
||||
/// After the data is sent to the server, the `progress(queue:closure:)` APIs can be used to monitor the progress
|
||||
/// of data being read from the server.
|
||||
///
|
||||
/// - parameter queue: The dispatch queue to execute the closure on.
|
||||
/// - parameter closure: The code to be executed periodically as data is sent to the server.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
open func uploadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
|
||||
uploadDelegate.uploadProgressHandler = (closure, queue)
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
/// Specific type of `Request` that manages an underlying `URLSessionStreamTask`.
|
||||
open class StreamRequest: Request {
|
||||
enum Streamable: TaskConvertible {
|
||||
case stream(hostName: String, port: Int)
|
||||
case netService(NetService)
|
||||
|
||||
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
|
||||
let task: URLSessionTask
|
||||
|
||||
switch self {
|
||||
case let .stream(hostName, port):
|
||||
task = queue.syncResult { session.streamTask(withHostName: hostName, port: port) }
|
||||
case let .netService(netService):
|
||||
task = queue.syncResult { session.streamTask(with: netService) }
|
||||
}
|
||||
|
||||
return task
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
296
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Response.swift
generated
Normal file
296
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Response.swift
generated
Normal file
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// Response.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Used to store all data associated with an non-serialized response of a data or upload request.
|
||||
public struct DefaultDataResponse {
|
||||
/// The URL request sent to the server.
|
||||
public let request: URLRequest?
|
||||
|
||||
/// The server's response to the URL request.
|
||||
public let response: HTTPURLResponse?
|
||||
|
||||
/// The data returned by the server.
|
||||
public let data: Data?
|
||||
|
||||
/// The error encountered while executing or validating the request.
|
||||
public let error: Error?
|
||||
|
||||
var _metrics: AnyObject?
|
||||
|
||||
init(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) {
|
||||
self.request = request
|
||||
self.response = response
|
||||
self.data = data
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Used to store all data associated with a serialized response of a data or upload request.
|
||||
public struct DataResponse<Value> {
|
||||
/// The URL request sent to the server.
|
||||
public let request: URLRequest?
|
||||
|
||||
/// The server's response to the URL request.
|
||||
public let response: HTTPURLResponse?
|
||||
|
||||
/// The data returned by the server.
|
||||
public let data: Data?
|
||||
|
||||
/// The result of response serialization.
|
||||
public let result: Result<Value>
|
||||
|
||||
/// The timeline of the complete lifecycle of the `Request`.
|
||||
public let timeline: Timeline
|
||||
|
||||
var _metrics: AnyObject?
|
||||
|
||||
/// Creates a `DataResponse` instance with the specified parameters derived from response serialization.
|
||||
///
|
||||
/// - parameter request: The URL request sent to the server.
|
||||
/// - parameter response: The server's response to the URL request.
|
||||
/// - parameter data: The data returned by the server.
|
||||
/// - parameter result: The result of response serialization.
|
||||
/// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
|
||||
///
|
||||
/// - returns: The new `DataResponse` instance.
|
||||
public init(
|
||||
request: URLRequest?,
|
||||
response: HTTPURLResponse?,
|
||||
data: Data?,
|
||||
result: Result<Value>,
|
||||
timeline: Timeline = Timeline())
|
||||
{
|
||||
self.request = request
|
||||
self.response = response
|
||||
self.data = data
|
||||
self.result = result
|
||||
self.timeline = timeline
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes whether the result was a
|
||||
/// success or failure.
|
||||
public var description: String {
|
||||
return result.debugDescription
|
||||
}
|
||||
|
||||
/// The debug textual representation used when written to an output stream, which includes the URL request, the URL
|
||||
/// response, the server data, the response serialization result and the timeline.
|
||||
public var debugDescription: String {
|
||||
var output: [String] = []
|
||||
|
||||
output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil")
|
||||
output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
|
||||
output.append("[Data]: \(data?.count ?? 0) bytes")
|
||||
output.append("[Result]: \(result.debugDescription)")
|
||||
output.append("[Timeline]: \(timeline.debugDescription)")
|
||||
|
||||
return output.joined(separator: "\n")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Used to store all data associated with an non-serialized response of a download request.
|
||||
public struct DefaultDownloadResponse {
|
||||
/// The URL request sent to the server.
|
||||
public let request: URLRequest?
|
||||
|
||||
/// The server's response to the URL request.
|
||||
public let response: HTTPURLResponse?
|
||||
|
||||
/// The temporary destination URL of the data returned from the server.
|
||||
public let temporaryURL: URL?
|
||||
|
||||
/// The final destination URL of the data returned from the server if it was moved.
|
||||
public let destinationURL: URL?
|
||||
|
||||
/// The resume data generated if the request was cancelled.
|
||||
public let resumeData: Data?
|
||||
|
||||
/// The error encountered while executing or validating the request.
|
||||
public let error: Error?
|
||||
|
||||
var _metrics: AnyObject?
|
||||
|
||||
init(
|
||||
request: URLRequest?,
|
||||
response: HTTPURLResponse?,
|
||||
temporaryURL: URL?,
|
||||
destinationURL: URL?,
|
||||
resumeData: Data?,
|
||||
error: Error?)
|
||||
{
|
||||
self.request = request
|
||||
self.response = response
|
||||
self.temporaryURL = temporaryURL
|
||||
self.destinationURL = destinationURL
|
||||
self.resumeData = resumeData
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Used to store all data associated with a serialized response of a download request.
|
||||
public struct DownloadResponse<Value> {
|
||||
/// The URL request sent to the server.
|
||||
public let request: URLRequest?
|
||||
|
||||
/// The server's response to the URL request.
|
||||
public let response: HTTPURLResponse?
|
||||
|
||||
/// The temporary destination URL of the data returned from the server.
|
||||
public let temporaryURL: URL?
|
||||
|
||||
/// The final destination URL of the data returned from the server if it was moved.
|
||||
public let destinationURL: URL?
|
||||
|
||||
/// The resume data generated if the request was cancelled.
|
||||
public let resumeData: Data?
|
||||
|
||||
/// The result of response serialization.
|
||||
public let result: Result<Value>
|
||||
|
||||
/// The timeline of the complete lifecycle of the request.
|
||||
public let timeline: Timeline
|
||||
|
||||
var _metrics: AnyObject?
|
||||
|
||||
/// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
|
||||
///
|
||||
/// - parameter request: The URL request sent to the server.
|
||||
/// - parameter response: The server's response to the URL request.
|
||||
/// - parameter temporaryURL: The temporary destination URL of the data returned from the server.
|
||||
/// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved.
|
||||
/// - parameter resumeData: The resume data generated if the request was cancelled.
|
||||
/// - parameter result: The result of response serialization.
|
||||
/// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
|
||||
///
|
||||
/// - returns: The new `DownloadResponse` instance.
|
||||
public init(
|
||||
request: URLRequest?,
|
||||
response: HTTPURLResponse?,
|
||||
temporaryURL: URL?,
|
||||
destinationURL: URL?,
|
||||
resumeData: Data?,
|
||||
result: Result<Value>,
|
||||
timeline: Timeline = Timeline())
|
||||
{
|
||||
self.request = request
|
||||
self.response = response
|
||||
self.temporaryURL = temporaryURL
|
||||
self.destinationURL = destinationURL
|
||||
self.resumeData = resumeData
|
||||
self.result = result
|
||||
self.timeline = timeline
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes whether the result was a
|
||||
/// success or failure.
|
||||
public var description: String {
|
||||
return result.debugDescription
|
||||
}
|
||||
|
||||
/// The debug textual representation used when written to an output stream, which includes the URL request, the URL
|
||||
/// response, the temporary and destination URLs, the resume data, the response serialization result and the
|
||||
/// timeline.
|
||||
public var debugDescription: String {
|
||||
var output: [String] = []
|
||||
|
||||
output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil")
|
||||
output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
|
||||
output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")")
|
||||
output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")")
|
||||
output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes")
|
||||
output.append("[Result]: \(result.debugDescription)")
|
||||
output.append("[Timeline]: \(timeline.debugDescription)")
|
||||
|
||||
return output.joined(separator: "\n")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
protocol Response {
|
||||
/// The task metrics containing the request / response statistics.
|
||||
var _metrics: AnyObject? { get set }
|
||||
mutating func add(_ metrics: AnyObject?)
|
||||
}
|
||||
|
||||
extension Response {
|
||||
mutating func add(_ metrics: AnyObject?) {
|
||||
#if !os(watchOS)
|
||||
guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return }
|
||||
guard let metrics = metrics as? URLSessionTaskMetrics else { return }
|
||||
|
||||
_metrics = metrics
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
|
||||
extension DefaultDataResponse: Response {
|
||||
#if !os(watchOS)
|
||||
/// The task metrics containing the request / response statistics.
|
||||
public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
|
||||
extension DataResponse: Response {
|
||||
#if !os(watchOS)
|
||||
/// The task metrics containing the request / response statistics.
|
||||
public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
|
||||
extension DefaultDownloadResponse: Response {
|
||||
#if !os(watchOS)
|
||||
/// The task metrics containing the request / response statistics.
|
||||
public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
|
||||
extension DownloadResponse: Response {
|
||||
#if !os(watchOS)
|
||||
/// The task metrics containing the request / response statistics.
|
||||
public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,716 @@
|
||||
//
|
||||
// ResponseSerialization.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// The type in which all data response serializers must conform to in order to serialize a response.
|
||||
public protocol DataResponseSerializerProtocol {
|
||||
/// The type of serialized object to be created by this `DataResponseSerializerType`.
|
||||
associatedtype SerializedObject
|
||||
|
||||
/// A closure used by response handlers that takes a request, response, data and error and returns a result.
|
||||
var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<SerializedObject> { get }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// A generic `DataResponseSerializerType` used to serialize a request, response, and data into a serialized object.
|
||||
public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
|
||||
/// The type of serialized object to be created by this `DataResponseSerializer`.
|
||||
public typealias SerializedObject = Value
|
||||
|
||||
/// A closure used by response handlers that takes a request, response, data and error and returns a result.
|
||||
public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>
|
||||
|
||||
/// Initializes the `ResponseSerializer` instance with the given serialize response closure.
|
||||
///
|
||||
/// - parameter serializeResponse: The closure used to serialize the response.
|
||||
///
|
||||
/// - returns: The new generic response serializer instance.
|
||||
public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
|
||||
self.serializeResponse = serializeResponse
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// The type in which all download response serializers must conform to in order to serialize a response.
|
||||
public protocol DownloadResponseSerializerProtocol {
|
||||
/// The type of serialized object to be created by this `DownloadResponseSerializerType`.
|
||||
associatedtype SerializedObject
|
||||
|
||||
/// A closure used by response handlers that takes a request, response, url and error and returns a result.
|
||||
var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<SerializedObject> { get }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// A generic `DownloadResponseSerializerType` used to serialize a request, response, and data into a serialized object.
|
||||
public struct DownloadResponseSerializer<Value>: DownloadResponseSerializerProtocol {
|
||||
/// The type of serialized object to be created by this `DownloadResponseSerializer`.
|
||||
public typealias SerializedObject = Value
|
||||
|
||||
/// A closure used by response handlers that takes a request, response, url and error and returns a result.
|
||||
public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>
|
||||
|
||||
/// Initializes the `ResponseSerializer` instance with the given serialize response closure.
|
||||
///
|
||||
/// - parameter serializeResponse: The closure used to serialize the response.
|
||||
///
|
||||
/// - returns: The new generic response serializer instance.
|
||||
public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>) {
|
||||
self.serializeResponse = serializeResponse
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Default
|
||||
|
||||
extension DataRequest {
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter queue: The queue on which the completion handler is dispatched.
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
|
||||
delegate.queue.addOperation {
|
||||
(queue ?? DispatchQueue.main).async {
|
||||
var dataResponse = DefaultDataResponse(
|
||||
request: self.request,
|
||||
response: self.response,
|
||||
data: self.delegate.data,
|
||||
error: self.delegate.error
|
||||
)
|
||||
|
||||
dataResponse.add(self.delegate.metrics)
|
||||
|
||||
completionHandler(dataResponse)
|
||||
}
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter queue: The queue on which the completion handler is dispatched.
|
||||
/// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
|
||||
/// and data.
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func response<T: DataResponseSerializerProtocol>(
|
||||
queue: DispatchQueue? = nil,
|
||||
responseSerializer: T,
|
||||
completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
delegate.queue.addOperation {
|
||||
let result = responseSerializer.serializeResponse(
|
||||
self.request,
|
||||
self.response,
|
||||
self.delegate.data,
|
||||
self.delegate.error
|
||||
)
|
||||
|
||||
let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
|
||||
let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
|
||||
|
||||
let timeline = Timeline(
|
||||
requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
|
||||
initialResponseTime: initialResponseTime,
|
||||
requestCompletedTime: requestCompletedTime,
|
||||
serializationCompletedTime: CFAbsoluteTimeGetCurrent()
|
||||
)
|
||||
|
||||
var dataResponse = DataResponse<T.SerializedObject>(
|
||||
request: self.request,
|
||||
response: self.response,
|
||||
data: self.delegate.data,
|
||||
result: result,
|
||||
timeline: timeline
|
||||
)
|
||||
|
||||
dataResponse.add(self.delegate.metrics)
|
||||
|
||||
(queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter queue: The queue on which the completion handler is dispatched.
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func response(
|
||||
queue: DispatchQueue? = nil,
|
||||
completionHandler: @escaping (DefaultDownloadResponse) -> Void)
|
||||
-> Self
|
||||
{
|
||||
delegate.queue.addOperation {
|
||||
(queue ?? DispatchQueue.main).async {
|
||||
var downloadResponse = DefaultDownloadResponse(
|
||||
request: self.request,
|
||||
response: self.response,
|
||||
temporaryURL: self.downloadDelegate.temporaryURL,
|
||||
destinationURL: self.downloadDelegate.destinationURL,
|
||||
resumeData: self.downloadDelegate.resumeData,
|
||||
error: self.downloadDelegate.error
|
||||
)
|
||||
|
||||
downloadResponse.add(self.delegate.metrics)
|
||||
|
||||
completionHandler(downloadResponse)
|
||||
}
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter queue: The queue on which the completion handler is dispatched.
|
||||
/// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
|
||||
/// and data contained in the destination url.
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func response<T: DownloadResponseSerializerProtocol>(
|
||||
queue: DispatchQueue? = nil,
|
||||
responseSerializer: T,
|
||||
completionHandler: @escaping (DownloadResponse<T.SerializedObject>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
delegate.queue.addOperation {
|
||||
let result = responseSerializer.serializeResponse(
|
||||
self.request,
|
||||
self.response,
|
||||
self.downloadDelegate.fileURL,
|
||||
self.downloadDelegate.error
|
||||
)
|
||||
|
||||
let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
|
||||
let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
|
||||
|
||||
let timeline = Timeline(
|
||||
requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
|
||||
initialResponseTime: initialResponseTime,
|
||||
requestCompletedTime: requestCompletedTime,
|
||||
serializationCompletedTime: CFAbsoluteTimeGetCurrent()
|
||||
)
|
||||
|
||||
var downloadResponse = DownloadResponse<T.SerializedObject>(
|
||||
request: self.request,
|
||||
response: self.response,
|
||||
temporaryURL: self.downloadDelegate.temporaryURL,
|
||||
destinationURL: self.downloadDelegate.destinationURL,
|
||||
resumeData: self.downloadDelegate.resumeData,
|
||||
result: result,
|
||||
timeline: timeline
|
||||
)
|
||||
|
||||
downloadResponse.add(self.delegate.metrics)
|
||||
|
||||
(queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) }
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Data
|
||||
|
||||
extension Request {
|
||||
/// Returns a result data type that contains the response data as-is.
|
||||
///
|
||||
/// - parameter response: The response from the server.
|
||||
/// - parameter data: The data returned from the server.
|
||||
/// - parameter error: The error already encountered if it exists.
|
||||
///
|
||||
/// - returns: The result data type.
|
||||
public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result<Data> {
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) }
|
||||
|
||||
guard let validData = data else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
|
||||
}
|
||||
|
||||
return .success(validData)
|
||||
}
|
||||
}
|
||||
|
||||
extension DataRequest {
|
||||
/// Creates a response serializer that returns the associated data as-is.
|
||||
///
|
||||
/// - returns: A data response serializer.
|
||||
public static func dataResponseSerializer() -> DataResponseSerializer<Data> {
|
||||
return DataResponseSerializer { _, response, data, error in
|
||||
return Request.serializeResponseData(response: response, data: data, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseData(
|
||||
queue: DispatchQueue? = nil,
|
||||
completionHandler: @escaping (DataResponse<Data>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DataRequest.dataResponseSerializer(),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Creates a response serializer that returns the associated data as-is.
|
||||
///
|
||||
/// - returns: A data response serializer.
|
||||
public static func dataResponseSerializer() -> DownloadResponseSerializer<Data> {
|
||||
return DownloadResponseSerializer { _, response, fileURL, error in
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
guard let fileURL = fileURL else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: fileURL)
|
||||
return Request.serializeResponseData(response: response, data: data, error: error)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter completionHandler: The code to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseData(
|
||||
queue: DispatchQueue? = nil,
|
||||
completionHandler: @escaping (DownloadResponse<Data>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DownloadRequest.dataResponseSerializer(),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - String
|
||||
|
||||
extension Request {
|
||||
/// Returns a result string type initialized from the response data with the specified string encoding.
|
||||
///
|
||||
/// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
|
||||
/// response, falling back to the default HTTP default character set, ISO-8859-1.
|
||||
/// - parameter response: The response from the server.
|
||||
/// - parameter data: The data returned from the server.
|
||||
/// - parameter error: The error already encountered if it exists.
|
||||
///
|
||||
/// - returns: The result data type.
|
||||
public static func serializeResponseString(
|
||||
encoding: String.Encoding?,
|
||||
response: HTTPURLResponse?,
|
||||
data: Data?,
|
||||
error: Error?)
|
||||
-> Result<String>
|
||||
{
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success("") }
|
||||
|
||||
guard let validData = data else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
|
||||
}
|
||||
|
||||
var convertedEncoding = encoding
|
||||
|
||||
if let encodingName = response?.textEncodingName as CFString!, convertedEncoding == nil {
|
||||
convertedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(
|
||||
CFStringConvertIANACharSetNameToEncoding(encodingName))
|
||||
)
|
||||
}
|
||||
|
||||
let actualEncoding = convertedEncoding ?? String.Encoding.isoLatin1
|
||||
|
||||
if let string = String(data: validData, encoding: actualEncoding) {
|
||||
return .success(string)
|
||||
} else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension DataRequest {
|
||||
/// Creates a response serializer that returns a result string type initialized from the response data with
|
||||
/// the specified string encoding.
|
||||
///
|
||||
/// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
|
||||
/// response, falling back to the default HTTP default character set, ISO-8859-1.
|
||||
///
|
||||
/// - returns: A string response serializer.
|
||||
public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer<String> {
|
||||
return DataResponseSerializer { _, response, data, error in
|
||||
return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the
|
||||
/// server response, falling back to the default HTTP default character set,
|
||||
/// ISO-8859-1.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseString(
|
||||
queue: DispatchQueue? = nil,
|
||||
encoding: String.Encoding? = nil,
|
||||
completionHandler: @escaping (DataResponse<String>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Creates a response serializer that returns a result string type initialized from the response data with
|
||||
/// the specified string encoding.
|
||||
///
|
||||
/// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
|
||||
/// response, falling back to the default HTTP default character set, ISO-8859-1.
|
||||
///
|
||||
/// - returns: A string response serializer.
|
||||
public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DownloadResponseSerializer<String> {
|
||||
return DownloadResponseSerializer { _, response, fileURL, error in
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
guard let fileURL = fileURL else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: fileURL)
|
||||
return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the
|
||||
/// server response, falling back to the default HTTP default character set,
|
||||
/// ISO-8859-1.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseString(
|
||||
queue: DispatchQueue? = nil,
|
||||
encoding: String.Encoding? = nil,
|
||||
completionHandler: @escaping (DownloadResponse<String>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DownloadRequest.stringResponseSerializer(encoding: encoding),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - JSON
|
||||
|
||||
extension Request {
|
||||
/// Returns a JSON object contained in a result type constructed from the response data using `JSONSerialization`
|
||||
/// with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
|
||||
/// - parameter response: The response from the server.
|
||||
/// - parameter data: The data returned from the server.
|
||||
/// - parameter error: The error already encountered if it exists.
|
||||
///
|
||||
/// - returns: The result data type.
|
||||
public static func serializeResponseJSON(
|
||||
options: JSONSerialization.ReadingOptions,
|
||||
response: HTTPURLResponse?,
|
||||
data: Data?,
|
||||
error: Error?)
|
||||
-> Result<Any>
|
||||
{
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
|
||||
|
||||
guard let validData = data, validData.count > 0 else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
|
||||
}
|
||||
|
||||
do {
|
||||
let json = try JSONSerialization.jsonObject(with: validData, options: options)
|
||||
return .success(json)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension DataRequest {
|
||||
/// Creates a response serializer that returns a JSON object result type constructed from the response data using
|
||||
/// `JSONSerialization` with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
|
||||
///
|
||||
/// - returns: A JSON object response serializer.
|
||||
public static func jsonResponseSerializer(
|
||||
options: JSONSerialization.ReadingOptions = .allowFragments)
|
||||
-> DataResponseSerializer<Any>
|
||||
{
|
||||
return DataResponseSerializer { _, response, data, error in
|
||||
return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseJSON(
|
||||
queue: DispatchQueue? = nil,
|
||||
options: JSONSerialization.ReadingOptions = .allowFragments,
|
||||
completionHandler: @escaping (DataResponse<Any>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DataRequest.jsonResponseSerializer(options: options),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Creates a response serializer that returns a JSON object result type constructed from the response data using
|
||||
/// `JSONSerialization` with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
|
||||
///
|
||||
/// - returns: A JSON object response serializer.
|
||||
public static func jsonResponseSerializer(
|
||||
options: JSONSerialization.ReadingOptions = .allowFragments)
|
||||
-> DownloadResponseSerializer<Any>
|
||||
{
|
||||
return DownloadResponseSerializer { _, response, fileURL, error in
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
guard let fileURL = fileURL else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: fileURL)
|
||||
return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responseJSON(
|
||||
queue: DispatchQueue? = nil,
|
||||
options: JSONSerialization.ReadingOptions = .allowFragments,
|
||||
completionHandler: @escaping (DownloadResponse<Any>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DownloadRequest.jsonResponseSerializer(options: options),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Property List
|
||||
|
||||
extension Request {
|
||||
/// Returns a plist object contained in a result type constructed from the response data using
|
||||
/// `PropertyListSerialization` with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The property list reading options. Defaults to `[]`.
|
||||
/// - parameter response: The response from the server.
|
||||
/// - parameter data: The data returned from the server.
|
||||
/// - parameter error: The error already encountered if it exists.
|
||||
///
|
||||
/// - returns: The result data type.
|
||||
public static func serializeResponsePropertyList(
|
||||
options: PropertyListSerialization.ReadOptions,
|
||||
response: HTTPURLResponse?,
|
||||
data: Data?,
|
||||
error: Error?)
|
||||
-> Result<Any>
|
||||
{
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
|
||||
|
||||
guard let validData = data, validData.count > 0 else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
|
||||
}
|
||||
|
||||
do {
|
||||
let plist = try PropertyListSerialization.propertyList(from: validData, options: options, format: nil)
|
||||
return .success(plist)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .propertyListSerializationFailed(error: error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension DataRequest {
|
||||
/// Creates a response serializer that returns an object constructed from the response data using
|
||||
/// `PropertyListSerialization` with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The property list reading options. Defaults to `[]`.
|
||||
///
|
||||
/// - returns: A property list object response serializer.
|
||||
public static func propertyListResponseSerializer(
|
||||
options: PropertyListSerialization.ReadOptions = [])
|
||||
-> DataResponseSerializer<Any>
|
||||
{
|
||||
return DataResponseSerializer { _, response, data, error in
|
||||
return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter options: The property list reading options. Defaults to `[]`.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responsePropertyList(
|
||||
queue: DispatchQueue? = nil,
|
||||
options: PropertyListSerialization.ReadOptions = [],
|
||||
completionHandler: @escaping (DataResponse<Any>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DataRequest.propertyListResponseSerializer(options: options),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension DownloadRequest {
|
||||
/// Creates a response serializer that returns an object constructed from the response data using
|
||||
/// `PropertyListSerialization` with the specified reading options.
|
||||
///
|
||||
/// - parameter options: The property list reading options. Defaults to `[]`.
|
||||
///
|
||||
/// - returns: A property list object response serializer.
|
||||
public static func propertyListResponseSerializer(
|
||||
options: PropertyListSerialization.ReadOptions = [])
|
||||
-> DownloadResponseSerializer<Any>
|
||||
{
|
||||
return DownloadResponseSerializer { _, response, fileURL, error in
|
||||
guard error == nil else { return .failure(error!) }
|
||||
|
||||
guard let fileURL = fileURL else {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: fileURL)
|
||||
return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
|
||||
} catch {
|
||||
return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handler to be called once the request has finished.
|
||||
///
|
||||
/// - parameter options: The property list reading options. Defaults to `[]`.
|
||||
/// - parameter completionHandler: A closure to be executed once the request has finished.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func responsePropertyList(
|
||||
queue: DispatchQueue? = nil,
|
||||
options: PropertyListSerialization.ReadOptions = [],
|
||||
completionHandler: @escaping (DownloadResponse<Any>) -> Void)
|
||||
-> Self
|
||||
{
|
||||
return response(
|
||||
queue: queue,
|
||||
responseSerializer: DownloadRequest.propertyListResponseSerializer(options: options),
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of HTTP response status code that do not contain response data.
|
||||
private let emptyDataStatusCodes: Set<Int> = [204, 205]
|
||||
102
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Result.swift
generated
Normal file
102
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Result.swift
generated
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Result.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Used to represent whether a request was successful or encountered an error.
|
||||
///
|
||||
/// - success: The request and all post processing operations were successful resulting in the serialization of the
|
||||
/// provided associated value.
|
||||
///
|
||||
/// - failure: The request encountered an error resulting in a failure. The associated values are the original data
|
||||
/// provided by the server as well as the error that caused the failure.
|
||||
public enum Result<Value> {
|
||||
case success(Value)
|
||||
case failure(Error)
|
||||
|
||||
/// Returns `true` if the result is a success, `false` otherwise.
|
||||
public var isSuccess: Bool {
|
||||
switch self {
|
||||
case .success:
|
||||
return true
|
||||
case .failure:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the result is a failure, `false` otherwise.
|
||||
public var isFailure: Bool {
|
||||
return !isSuccess
|
||||
}
|
||||
|
||||
/// Returns the associated value if the result is a success, `nil` otherwise.
|
||||
public var value: Value? {
|
||||
switch self {
|
||||
case .success(let value):
|
||||
return value
|
||||
case .failure:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the associated error value if the result is a failure, `nil` otherwise.
|
||||
public var error: Error? {
|
||||
switch self {
|
||||
case .success:
|
||||
return nil
|
||||
case .failure(let error):
|
||||
return error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomStringConvertible
|
||||
|
||||
extension Result: CustomStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes whether the result was a
|
||||
/// success or failure.
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .success:
|
||||
return "SUCCESS"
|
||||
case .failure:
|
||||
return "FAILURE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomDebugStringConvertible
|
||||
|
||||
extension Result: CustomDebugStringConvertible {
|
||||
/// The debug textual representation used when written to an output stream, which includes whether the result was a
|
||||
/// success or failure in addition to the value or error.
|
||||
public var debugDescription: String {
|
||||
switch self {
|
||||
case .success(let value):
|
||||
return "SUCCESS: \(value)"
|
||||
case .failure(let error):
|
||||
return "FAILURE: \(error)"
|
||||
}
|
||||
}
|
||||
}
|
||||
293
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/ServerTrustPolicy.swift
generated
Normal file
293
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/ServerTrustPolicy.swift
generated
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// ServerTrustPolicy.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host.
|
||||
open class ServerTrustPolicyManager {
|
||||
/// The dictionary of policies mapped to a particular host.
|
||||
open let policies: [String: ServerTrustPolicy]
|
||||
|
||||
/// Initializes the `ServerTrustPolicyManager` instance with the given policies.
|
||||
///
|
||||
/// Since different servers and web services can have different leaf certificates, intermediate and even root
|
||||
/// certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This
|
||||
/// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key
|
||||
/// pinning for host3 and disabling evaluation for host4.
|
||||
///
|
||||
/// - parameter policies: A dictionary of all policies mapped to a particular host.
|
||||
///
|
||||
/// - returns: The new `ServerTrustPolicyManager` instance.
|
||||
public init(policies: [String: ServerTrustPolicy]) {
|
||||
self.policies = policies
|
||||
}
|
||||
|
||||
/// Returns the `ServerTrustPolicy` for the given host if applicable.
|
||||
///
|
||||
/// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
|
||||
/// this method and implement more complex mapping implementations such as wildcards.
|
||||
///
|
||||
/// - parameter host: The host to use when searching for a matching policy.
|
||||
///
|
||||
/// - returns: The server trust policy for the given host if found.
|
||||
open func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
|
||||
return policies[host]
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension URLSession {
|
||||
private struct AssociatedKeys {
|
||||
static var managerKey = "URLSession.ServerTrustPolicyManager"
|
||||
}
|
||||
|
||||
var serverTrustPolicyManager: ServerTrustPolicyManager? {
|
||||
get {
|
||||
return objc_getAssociatedObject(self, &AssociatedKeys.managerKey) as? ServerTrustPolicyManager
|
||||
}
|
||||
set (manager) {
|
||||
objc_setAssociatedObject(self, &AssociatedKeys.managerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ServerTrustPolicy
|
||||
|
||||
/// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when
|
||||
/// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust
|
||||
/// with a given set of criteria to determine whether the server trust is valid and the connection should be made.
|
||||
///
|
||||
/// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other
|
||||
/// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged
|
||||
/// to route all communication over an HTTPS connection with pinning enabled.
|
||||
///
|
||||
/// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to
|
||||
/// validate the host provided by the challenge. Applications are encouraged to always
|
||||
/// validate the host in production environments to guarantee the validity of the server's
|
||||
/// certificate chain.
|
||||
///
|
||||
/// - pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is
|
||||
/// considered valid if one of the pinned certificates match one of the server certificates.
|
||||
/// By validating both the certificate chain and host, certificate pinning provides a very
|
||||
/// secure form of server trust validation mitigating most, if not all, MITM attacks.
|
||||
/// Applications are encouraged to always validate the host and require a valid certificate
|
||||
/// chain in production environments.
|
||||
///
|
||||
/// - pinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered
|
||||
/// valid if one of the pinned public keys match one of the server certificate public keys.
|
||||
/// By validating both the certificate chain and host, public key pinning provides a very
|
||||
/// secure form of server trust validation mitigating most, if not all, MITM attacks.
|
||||
/// Applications are encouraged to always validate the host and require a valid certificate
|
||||
/// chain in production environments.
|
||||
///
|
||||
/// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid.
|
||||
///
|
||||
/// - customEvaluation: Uses the associated closure to evaluate the validity of the server trust.
|
||||
public enum ServerTrustPolicy {
|
||||
case performDefaultEvaluation(validateHost: Bool)
|
||||
case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool)
|
||||
case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
|
||||
case disableEvaluation
|
||||
case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool)
|
||||
|
||||
// MARK: - Bundle Location
|
||||
|
||||
/// Returns all certificates within the given bundle with a `.cer` file extension.
|
||||
///
|
||||
/// - parameter bundle: The bundle to search for all `.cer` files.
|
||||
///
|
||||
/// - returns: All certificates within the given bundle.
|
||||
public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] {
|
||||
var certificates: [SecCertificate] = []
|
||||
|
||||
let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
|
||||
bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil)
|
||||
}.joined())
|
||||
|
||||
for path in paths {
|
||||
if
|
||||
let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
|
||||
let certificate = SecCertificateCreateWithData(nil, certificateData)
|
||||
{
|
||||
certificates.append(certificate)
|
||||
}
|
||||
}
|
||||
|
||||
return certificates
|
||||
}
|
||||
|
||||
/// Returns all public keys within the given bundle with a `.cer` file extension.
|
||||
///
|
||||
/// - parameter bundle: The bundle to search for all `*.cer` files.
|
||||
///
|
||||
/// - returns: All public keys within the given bundle.
|
||||
public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] {
|
||||
var publicKeys: [SecKey] = []
|
||||
|
||||
for certificate in certificates(in: bundle) {
|
||||
if let publicKey = publicKey(for: certificate) {
|
||||
publicKeys.append(publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
return publicKeys
|
||||
}
|
||||
|
||||
// MARK: - Evaluation
|
||||
|
||||
/// Evaluates whether the server trust is valid for the given host.
|
||||
///
|
||||
/// - parameter serverTrust: The server trust to evaluate.
|
||||
/// - parameter host: The host of the challenge protection space.
|
||||
///
|
||||
/// - returns: Whether the server trust is valid.
|
||||
public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool {
|
||||
var serverTrustIsValid = false
|
||||
|
||||
switch self {
|
||||
case let .performDefaultEvaluation(validateHost):
|
||||
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
|
||||
SecTrustSetPolicies(serverTrust, policy)
|
||||
|
||||
serverTrustIsValid = trustIsValid(serverTrust)
|
||||
case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost):
|
||||
if validateCertificateChain {
|
||||
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
|
||||
SecTrustSetPolicies(serverTrust, policy)
|
||||
|
||||
SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray)
|
||||
SecTrustSetAnchorCertificatesOnly(serverTrust, true)
|
||||
|
||||
serverTrustIsValid = trustIsValid(serverTrust)
|
||||
} else {
|
||||
let serverCertificatesDataArray = certificateData(for: serverTrust)
|
||||
let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates)
|
||||
|
||||
outerLoop: for serverCertificateData in serverCertificatesDataArray {
|
||||
for pinnedCertificateData in pinnedCertificatesDataArray {
|
||||
if serverCertificateData == pinnedCertificateData {
|
||||
serverTrustIsValid = true
|
||||
break outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost):
|
||||
var certificateChainEvaluationPassed = true
|
||||
|
||||
if validateCertificateChain {
|
||||
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
|
||||
SecTrustSetPolicies(serverTrust, policy)
|
||||
|
||||
certificateChainEvaluationPassed = trustIsValid(serverTrust)
|
||||
}
|
||||
|
||||
if certificateChainEvaluationPassed {
|
||||
outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] {
|
||||
for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
|
||||
if serverPublicKey.isEqual(pinnedPublicKey) {
|
||||
serverTrustIsValid = true
|
||||
break outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case .disableEvaluation:
|
||||
serverTrustIsValid = true
|
||||
case let .customEvaluation(closure):
|
||||
serverTrustIsValid = closure(serverTrust, host)
|
||||
}
|
||||
|
||||
return serverTrustIsValid
|
||||
}
|
||||
|
||||
// MARK: - Private - Trust Validation
|
||||
|
||||
private func trustIsValid(_ trust: SecTrust) -> Bool {
|
||||
var isValid = false
|
||||
|
||||
var result = SecTrustResultType.invalid
|
||||
let status = SecTrustEvaluate(trust, &result)
|
||||
|
||||
if status == errSecSuccess {
|
||||
let unspecified = SecTrustResultType.unspecified
|
||||
let proceed = SecTrustResultType.proceed
|
||||
|
||||
|
||||
isValid = result == unspecified || result == proceed
|
||||
}
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
// MARK: - Private - Certificate Data
|
||||
|
||||
private func certificateData(for trust: SecTrust) -> [Data] {
|
||||
var certificates: [SecCertificate] = []
|
||||
|
||||
for index in 0..<SecTrustGetCertificateCount(trust) {
|
||||
if let certificate = SecTrustGetCertificateAtIndex(trust, index) {
|
||||
certificates.append(certificate)
|
||||
}
|
||||
}
|
||||
|
||||
return certificateData(for: certificates)
|
||||
}
|
||||
|
||||
private func certificateData(for certificates: [SecCertificate]) -> [Data] {
|
||||
return certificates.map { SecCertificateCopyData($0) as Data }
|
||||
}
|
||||
|
||||
// MARK: - Private - Public Key Extraction
|
||||
|
||||
private static func publicKeys(for trust: SecTrust) -> [SecKey] {
|
||||
var publicKeys: [SecKey] = []
|
||||
|
||||
for index in 0..<SecTrustGetCertificateCount(trust) {
|
||||
if
|
||||
let certificate = SecTrustGetCertificateAtIndex(trust, index),
|
||||
let publicKey = publicKey(for: certificate)
|
||||
{
|
||||
publicKeys.append(publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
return publicKeys
|
||||
}
|
||||
|
||||
private static func publicKey(for certificate: SecCertificate) -> SecKey? {
|
||||
var publicKey: SecKey?
|
||||
|
||||
let policy = SecPolicyCreateBasicX509()
|
||||
var trust: SecTrust?
|
||||
let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust)
|
||||
|
||||
if let trust = trust, trustCreationStatus == errSecSuccess {
|
||||
publicKey = SecTrustCopyPublicKey(trust)
|
||||
}
|
||||
|
||||
return publicKey
|
||||
}
|
||||
}
|
||||
681
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/SessionDelegate.swift
generated
Normal file
681
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/SessionDelegate.swift
generated
Normal file
@@ -0,0 +1,681 @@
|
||||
//
|
||||
// SessionDelegate.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Responsible for handling all delegate callbacks for the underlying session.
|
||||
open class SessionDelegate: NSObject {
|
||||
|
||||
// MARK: URLSessionDelegate Overrides
|
||||
|
||||
/// Overrides default behavior for URLSessionDelegate method `urlSession(_:didBecomeInvalidWithError:)`.
|
||||
open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`.
|
||||
open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
|
||||
|
||||
/// Overrides all behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)` and requires the caller to call the `completionHandler`.
|
||||
open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`.
|
||||
open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)?
|
||||
|
||||
// MARK: URLSessionTaskDelegate Overrides
|
||||
|
||||
/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`.
|
||||
open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?
|
||||
|
||||
/// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` and
|
||||
/// requires the caller to call the `completionHandler`.
|
||||
open var taskWillPerformHTTPRedirectionWithCompletion: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest, (URLRequest?) -> Void) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)`.
|
||||
open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
|
||||
|
||||
/// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)` and
|
||||
/// requires the caller to call the `completionHandler`.
|
||||
open var taskDidReceiveChallengeWithCompletion: ((URLSession, URLSessionTask, URLAuthenticationChallenge, (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)`.
|
||||
open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)?
|
||||
|
||||
/// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)` and
|
||||
/// requires the caller to call the `completionHandler`.
|
||||
open var taskNeedNewBodyStreamWithCompletion: ((URLSession, URLSessionTask, (InputStream?) -> Void) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)`.
|
||||
open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didCompleteWithError:)`.
|
||||
open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
|
||||
|
||||
// MARK: URLSessionDataDelegate Overrides
|
||||
|
||||
/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)`.
|
||||
open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)?
|
||||
|
||||
/// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)` and
|
||||
/// requires caller to call the `completionHandler`.
|
||||
open var dataTaskDidReceiveResponseWithCompletion: ((URLSession, URLSessionDataTask, URLResponse, (URLSession.ResponseDisposition) -> Void) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didBecome:)`.
|
||||
open var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:)`.
|
||||
open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`.
|
||||
open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?
|
||||
|
||||
/// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)` and
|
||||
/// requires caller to call the `completionHandler`.
|
||||
open var dataTaskWillCacheResponseWithCompletion: ((URLSession, URLSessionDataTask, CachedURLResponse, (CachedURLResponse?) -> Void) -> Void)?
|
||||
|
||||
// MARK: URLSessionDownloadDelegate Overrides
|
||||
|
||||
/// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didFinishDownloadingTo:)`.
|
||||
open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`.
|
||||
open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)`.
|
||||
open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
|
||||
|
||||
// MARK: URLSessionStreamDelegate Overrides
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:readClosedFor:)`.
|
||||
open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:writeClosedFor:)`.
|
||||
open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:betterRouteDiscoveredFor:)`.
|
||||
open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)?
|
||||
|
||||
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:streamTask:didBecome:outputStream:)`.
|
||||
open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)?
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
var retrier: RequestRetrier?
|
||||
weak var sessionManager: SessionManager?
|
||||
|
||||
private var requests: [Int: Request] = [:]
|
||||
private let lock = NSLock()
|
||||
|
||||
/// Access the task delegate for the specified task in a thread-safe manner.
|
||||
open subscript(task: URLSessionTask) -> Request? {
|
||||
get {
|
||||
lock.lock() ; defer { lock.unlock() }
|
||||
return requests[task.taskIdentifier]
|
||||
}
|
||||
set {
|
||||
lock.lock() ; defer { lock.unlock() }
|
||||
requests[task.taskIdentifier] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
/// Initializes the `SessionDelegate` instance.
|
||||
///
|
||||
/// - returns: The new `SessionDelegate` instance.
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: NSObject Overrides
|
||||
|
||||
/// Returns a `Bool` indicating whether the `SessionDelegate` implements or inherits a method that can respond
|
||||
/// to a specified message.
|
||||
///
|
||||
/// - parameter selector: A selector that identifies a message.
|
||||
///
|
||||
/// - returns: `true` if the receiver implements or inherits a method that can respond to selector, otherwise `false`.
|
||||
open override func responds(to selector: Selector) -> Bool {
|
||||
#if !os(OSX)
|
||||
if selector == #selector(URLSessionDelegate.urlSessionDidFinishEvents(forBackgroundURLSession:)) {
|
||||
return sessionDidFinishEventsForBackgroundURLSession != nil
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !os(watchOS)
|
||||
switch selector {
|
||||
case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)):
|
||||
return streamTaskReadClosed != nil
|
||||
case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)):
|
||||
return streamTaskWriteClosed != nil
|
||||
case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)):
|
||||
return streamTaskBetterRouteDiscovered != nil
|
||||
case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)):
|
||||
return streamTaskDidBecomeInputAndOutputStreams != nil
|
||||
default:
|
||||
break
|
||||
}
|
||||
#endif
|
||||
|
||||
switch selector {
|
||||
case #selector(URLSessionDelegate.urlSession(_:didBecomeInvalidWithError:)):
|
||||
return sessionDidBecomeInvalidWithError != nil
|
||||
case #selector(URLSessionDelegate.urlSession(_:didReceive:completionHandler:)):
|
||||
return (sessionDidReceiveChallenge != nil || sessionDidReceiveChallengeWithCompletion != nil)
|
||||
case #selector(URLSessionTaskDelegate.urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)):
|
||||
return (taskWillPerformHTTPRedirection != nil || taskWillPerformHTTPRedirectionWithCompletion != nil)
|
||||
case #selector(URLSessionDataDelegate.urlSession(_:dataTask:didReceive:completionHandler:)):
|
||||
return (dataTaskDidReceiveResponse != nil || dataTaskDidReceiveResponseWithCompletion != nil)
|
||||
default:
|
||||
return type(of: self).instancesRespond(to: selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - URLSessionDelegate
|
||||
|
||||
extension SessionDelegate: URLSessionDelegate {
|
||||
/// Tells the delegate that the session has been invalidated.
|
||||
///
|
||||
/// - parameter session: The session object that was invalidated.
|
||||
/// - parameter error: The error that caused invalidation, or nil if the invalidation was explicit.
|
||||
open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
|
||||
sessionDidBecomeInvalidWithError?(session, error)
|
||||
}
|
||||
|
||||
/// Requests credentials from the delegate in response to a session-level authentication request from the
|
||||
/// remote server.
|
||||
///
|
||||
/// - parameter session: The session containing the task that requested authentication.
|
||||
/// - parameter challenge: An object that contains the request for authentication.
|
||||
/// - parameter completionHandler: A handler that your delegate method must call providing the disposition
|
||||
/// and credential.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
didReceive challenge: URLAuthenticationChallenge,
|
||||
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
|
||||
{
|
||||
guard sessionDidReceiveChallengeWithCompletion == nil else {
|
||||
sessionDidReceiveChallengeWithCompletion?(session, challenge, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
|
||||
var credential: URLCredential?
|
||||
|
||||
if let sessionDidReceiveChallenge = sessionDidReceiveChallenge {
|
||||
(disposition, credential) = sessionDidReceiveChallenge(session, challenge)
|
||||
} else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
|
||||
let host = challenge.protectionSpace.host
|
||||
|
||||
if
|
||||
let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
|
||||
let serverTrust = challenge.protectionSpace.serverTrust
|
||||
{
|
||||
if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
|
||||
disposition = .useCredential
|
||||
credential = URLCredential(trust: serverTrust)
|
||||
} else {
|
||||
disposition = .cancelAuthenticationChallenge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
completionHandler(disposition, credential)
|
||||
}
|
||||
|
||||
#if !os(OSX)
|
||||
|
||||
/// Tells the delegate that all messages enqueued for a session have been delivered.
|
||||
///
|
||||
/// - parameter session: The session that no longer has any outstanding requests.
|
||||
open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
|
||||
sessionDidFinishEventsForBackgroundURLSession?(session)
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - URLSessionTaskDelegate
|
||||
|
||||
extension SessionDelegate: URLSessionTaskDelegate {
|
||||
/// Tells the delegate that the remote server requested an HTTP redirect.
|
||||
///
|
||||
/// - parameter session: The session containing the task whose request resulted in a redirect.
|
||||
/// - parameter task: The task whose request resulted in a redirect.
|
||||
/// - parameter response: An object containing the server’s response to the original request.
|
||||
/// - parameter request: A URL request object filled out with the new location.
|
||||
/// - parameter completionHandler: A closure that your handler should call with either the value of the request
|
||||
/// parameter, a modified URL request object, or NULL to refuse the redirect and
|
||||
/// return the body of the redirect response.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
willPerformHTTPRedirection response: HTTPURLResponse,
|
||||
newRequest request: URLRequest,
|
||||
completionHandler: @escaping (URLRequest?) -> Void)
|
||||
{
|
||||
guard taskWillPerformHTTPRedirectionWithCompletion == nil else {
|
||||
taskWillPerformHTTPRedirectionWithCompletion?(session, task, response, request, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
var redirectRequest: URLRequest? = request
|
||||
|
||||
if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
|
||||
redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
|
||||
}
|
||||
|
||||
completionHandler(redirectRequest)
|
||||
}
|
||||
|
||||
/// Requests credentials from the delegate in response to an authentication request from the remote server.
|
||||
///
|
||||
/// - parameter session: The session containing the task whose request requires authentication.
|
||||
/// - parameter task: The task whose request requires authentication.
|
||||
/// - parameter challenge: An object that contains the request for authentication.
|
||||
/// - parameter completionHandler: A handler that your delegate method must call providing the disposition
|
||||
/// and credential.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
didReceive challenge: URLAuthenticationChallenge,
|
||||
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
|
||||
{
|
||||
guard taskDidReceiveChallengeWithCompletion == nil else {
|
||||
taskDidReceiveChallengeWithCompletion?(session, task, challenge, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
|
||||
let result = taskDidReceiveChallenge(session, task, challenge)
|
||||
completionHandler(result.0, result.1)
|
||||
} else if let delegate = self[task]?.delegate {
|
||||
delegate.urlSession(
|
||||
session,
|
||||
task: task,
|
||||
didReceive: challenge,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
} else {
|
||||
urlSession(session, didReceive: challenge, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells the delegate when a task requires a new request body stream to send to the remote server.
|
||||
///
|
||||
/// - parameter session: The session containing the task that needs a new body stream.
|
||||
/// - parameter task: The task that needs a new body stream.
|
||||
/// - parameter completionHandler: A completion handler that your delegate method should call with the new body stream.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
|
||||
{
|
||||
guard taskNeedNewBodyStreamWithCompletion == nil else {
|
||||
taskNeedNewBodyStreamWithCompletion?(session, task, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
if let taskNeedNewBodyStream = taskNeedNewBodyStream {
|
||||
completionHandler(taskNeedNewBodyStream(session, task))
|
||||
} else if let delegate = self[task]?.delegate {
|
||||
delegate.urlSession(session, task: task, needNewBodyStream: completionHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/// Periodically informs the delegate of the progress of sending body content to the server.
|
||||
///
|
||||
/// - parameter session: The session containing the data task.
|
||||
/// - parameter task: The data task.
|
||||
/// - parameter bytesSent: The number of bytes sent since the last time this delegate method was called.
|
||||
/// - parameter totalBytesSent: The total number of bytes sent so far.
|
||||
/// - parameter totalBytesExpectedToSend: The expected length of the body data.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
didSendBodyData bytesSent: Int64,
|
||||
totalBytesSent: Int64,
|
||||
totalBytesExpectedToSend: Int64)
|
||||
{
|
||||
if let taskDidSendBodyData = taskDidSendBodyData {
|
||||
taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
|
||||
} else if let delegate = self[task]?.delegate as? UploadTaskDelegate {
|
||||
delegate.URLSession(
|
||||
session,
|
||||
task: task,
|
||||
didSendBodyData: bytesSent,
|
||||
totalBytesSent: totalBytesSent,
|
||||
totalBytesExpectedToSend: totalBytesExpectedToSend
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
/// Tells the delegate that the session finished collecting metrics for the task.
|
||||
///
|
||||
/// - parameter session: The session collecting the metrics.
|
||||
/// - parameter task: The task whose metrics have been collected.
|
||||
/// - parameter metrics: The collected metrics.
|
||||
@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
|
||||
@objc(URLSession:task:didFinishCollectingMetrics:)
|
||||
open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
|
||||
self[task]?.delegate.metrics = metrics
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// Tells the delegate that the task finished transferring data.
|
||||
///
|
||||
/// - parameter session: The session containing the task whose request finished transferring data.
|
||||
/// - parameter task: The task whose request finished transferring data.
|
||||
/// - parameter error: If an error occurred, an error object indicating how the transfer failed, otherwise nil.
|
||||
open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
/// Executed after it is determined that the request is not going to be retried
|
||||
let completeTask: (URLSession, URLSessionTask, Error?) -> Void = { [weak self] session, task, error in
|
||||
guard let strongSelf = self else { return }
|
||||
|
||||
if let taskDidComplete = strongSelf.taskDidComplete {
|
||||
taskDidComplete(session, task, error)
|
||||
} else if let delegate = strongSelf[task]?.delegate {
|
||||
delegate.urlSession(session, task: task, didCompleteWithError: error)
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name.Task.DidComplete,
|
||||
object: strongSelf,
|
||||
userInfo: [Notification.Key.Task: task]
|
||||
)
|
||||
|
||||
strongSelf[task] = nil
|
||||
}
|
||||
|
||||
guard let request = self[task], let sessionManager = sessionManager else {
|
||||
completeTask(session, task, error)
|
||||
return
|
||||
}
|
||||
|
||||
// Run all validations on the request before checking if an error occurred
|
||||
request.validations.forEach { $0() }
|
||||
|
||||
// Determine whether an error has occurred
|
||||
var error: Error? = error
|
||||
|
||||
if let taskDelegate = self[task]?.delegate, taskDelegate.error != nil {
|
||||
error = taskDelegate.error
|
||||
}
|
||||
|
||||
/// If an error occurred and the retrier is set, asynchronously ask the retrier if the request
|
||||
/// should be retried. Otherwise, complete the task by notifying the task delegate.
|
||||
if let retrier = retrier, let error = error {
|
||||
retrier.should(sessionManager, retry: request, with: error) { [weak self] shouldRetry, delay in
|
||||
guard shouldRetry else { completeTask(session, task, error) ; return }
|
||||
|
||||
DispatchQueue.utility.after(delay) { [weak self] in
|
||||
guard let strongSelf = self else { return }
|
||||
|
||||
let retrySucceeded = strongSelf.sessionManager?.retry(request) ?? false
|
||||
|
||||
if retrySucceeded, let task = request.task {
|
||||
strongSelf[task] = request
|
||||
return
|
||||
} else {
|
||||
completeTask(session, task, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
completeTask(session, task, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - URLSessionDataDelegate
|
||||
|
||||
extension SessionDelegate: URLSessionDataDelegate {
|
||||
/// Tells the delegate that the data task received the initial reply (headers) from the server.
|
||||
///
|
||||
/// - parameter session: The session containing the data task that received an initial reply.
|
||||
/// - parameter dataTask: The data task that received an initial reply.
|
||||
/// - parameter response: A URL response object populated with headers.
|
||||
/// - parameter completionHandler: A completion handler that your code calls to continue the transfer, passing a
|
||||
/// constant to indicate whether the transfer should continue as a data task or
|
||||
/// should become a download task.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
didReceive response: URLResponse,
|
||||
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
|
||||
{
|
||||
guard dataTaskDidReceiveResponseWithCompletion == nil else {
|
||||
dataTaskDidReceiveResponseWithCompletion?(session, dataTask, response, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
var disposition: URLSession.ResponseDisposition = .allow
|
||||
|
||||
if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
|
||||
disposition = dataTaskDidReceiveResponse(session, dataTask, response)
|
||||
}
|
||||
|
||||
completionHandler(disposition)
|
||||
}
|
||||
|
||||
/// Tells the delegate that the data task was changed to a download task.
|
||||
///
|
||||
/// - parameter session: The session containing the task that was replaced by a download task.
|
||||
/// - parameter dataTask: The data task that was replaced by a download task.
|
||||
/// - parameter downloadTask: The new download task that replaced the data task.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
didBecome downloadTask: URLSessionDownloadTask)
|
||||
{
|
||||
if let dataTaskDidBecomeDownloadTask = dataTaskDidBecomeDownloadTask {
|
||||
dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask)
|
||||
} else {
|
||||
self[downloadTask]?.delegate = DownloadTaskDelegate(task: downloadTask)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells the delegate that the data task has received some of the expected data.
|
||||
///
|
||||
/// - parameter session: The session containing the data task that provided data.
|
||||
/// - parameter dataTask: The data task that provided data.
|
||||
/// - parameter data: A data object containing the transferred data.
|
||||
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
if let dataTaskDidReceiveData = dataTaskDidReceiveData {
|
||||
dataTaskDidReceiveData(session, dataTask, data)
|
||||
} else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate {
|
||||
delegate.urlSession(session, dataTask: dataTask, didReceive: data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Asks the delegate whether the data (or upload) task should store the response in the cache.
|
||||
///
|
||||
/// - parameter session: The session containing the data (or upload) task.
|
||||
/// - parameter dataTask: The data (or upload) task.
|
||||
/// - parameter proposedResponse: The default caching behavior. This behavior is determined based on the current
|
||||
/// caching policy and the values of certain received headers, such as the Pragma
|
||||
/// and Cache-Control headers.
|
||||
/// - parameter completionHandler: A block that your handler must call, providing either the original proposed
|
||||
/// response, a modified version of that response, or NULL to prevent caching the
|
||||
/// response. If your delegate implements this method, it must call this completion
|
||||
/// handler; otherwise, your app leaks memory.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
willCacheResponse proposedResponse: CachedURLResponse,
|
||||
completionHandler: @escaping (CachedURLResponse?) -> Void)
|
||||
{
|
||||
guard dataTaskWillCacheResponseWithCompletion == nil else {
|
||||
dataTaskWillCacheResponseWithCompletion?(session, dataTask, proposedResponse, completionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
|
||||
completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse))
|
||||
} else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate {
|
||||
delegate.urlSession(
|
||||
session,
|
||||
dataTask: dataTask,
|
||||
willCacheResponse: proposedResponse,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
} else {
|
||||
completionHandler(proposedResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - URLSessionDownloadDelegate
|
||||
|
||||
extension SessionDelegate: URLSessionDownloadDelegate {
|
||||
/// Tells the delegate that a download task has finished downloading.
|
||||
///
|
||||
/// - parameter session: The session containing the download task that finished.
|
||||
/// - parameter downloadTask: The download task that finished.
|
||||
/// - parameter location: A file URL for the temporary file. Because the file is temporary, you must either
|
||||
/// open the file for reading or move it to a permanent location in your app’s sandbox
|
||||
/// container directory before returning from this delegate method.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didFinishDownloadingTo location: URL)
|
||||
{
|
||||
if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
|
||||
downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
|
||||
} else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
|
||||
delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
|
||||
}
|
||||
}
|
||||
|
||||
/// Periodically informs the delegate about the download’s progress.
|
||||
///
|
||||
/// - parameter session: The session containing the download task.
|
||||
/// - parameter downloadTask: The download task.
|
||||
/// - parameter bytesWritten: The number of bytes transferred since the last time this delegate
|
||||
/// method was called.
|
||||
/// - parameter totalBytesWritten: The total number of bytes transferred so far.
|
||||
/// - parameter totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length
|
||||
/// header. If this header was not provided, the value is
|
||||
/// `NSURLSessionTransferSizeUnknown`.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didWriteData bytesWritten: Int64,
|
||||
totalBytesWritten: Int64,
|
||||
totalBytesExpectedToWrite: Int64)
|
||||
{
|
||||
if let downloadTaskDidWriteData = downloadTaskDidWriteData {
|
||||
downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
|
||||
} else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
|
||||
delegate.urlSession(
|
||||
session,
|
||||
downloadTask: downloadTask,
|
||||
didWriteData: bytesWritten,
|
||||
totalBytesWritten: totalBytesWritten,
|
||||
totalBytesExpectedToWrite: totalBytesExpectedToWrite
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells the delegate that the download task has resumed downloading.
|
||||
///
|
||||
/// - parameter session: The session containing the download task that finished.
|
||||
/// - parameter downloadTask: The download task that resumed. See explanation in the discussion.
|
||||
/// - parameter fileOffset: If the file's cache policy or last modified date prevents reuse of the
|
||||
/// existing content, then this value is zero. Otherwise, this value is an
|
||||
/// integer representing the number of bytes on disk that do not need to be
|
||||
/// retrieved again.
|
||||
/// - parameter expectedTotalBytes: The expected length of the file, as provided by the Content-Length header.
|
||||
/// If this header was not provided, the value is NSURLSessionTransferSizeUnknown.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didResumeAtOffset fileOffset: Int64,
|
||||
expectedTotalBytes: Int64)
|
||||
{
|
||||
if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
|
||||
downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
|
||||
} else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
|
||||
delegate.urlSession(
|
||||
session,
|
||||
downloadTask: downloadTask,
|
||||
didResumeAtOffset: fileOffset,
|
||||
expectedTotalBytes: expectedTotalBytes
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - URLSessionStreamDelegate
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
extension SessionDelegate: URLSessionStreamDelegate {
|
||||
/// Tells the delegate that the read side of the connection has been closed.
|
||||
///
|
||||
/// - parameter session: The session.
|
||||
/// - parameter streamTask: The stream task.
|
||||
open func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask) {
|
||||
streamTaskReadClosed?(session, streamTask)
|
||||
}
|
||||
|
||||
/// Tells the delegate that the write side of the connection has been closed.
|
||||
///
|
||||
/// - parameter session: The session.
|
||||
/// - parameter streamTask: The stream task.
|
||||
open func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask) {
|
||||
streamTaskWriteClosed?(session, streamTask)
|
||||
}
|
||||
|
||||
/// Tells the delegate that the system has determined that a better route to the host is available.
|
||||
///
|
||||
/// - parameter session: The session.
|
||||
/// - parameter streamTask: The stream task.
|
||||
open func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask) {
|
||||
streamTaskBetterRouteDiscovered?(session, streamTask)
|
||||
}
|
||||
|
||||
/// Tells the delegate that the stream task has been completed and provides the unopened stream objects.
|
||||
///
|
||||
/// - parameter session: The session.
|
||||
/// - parameter streamTask: The stream task.
|
||||
/// - parameter inputStream: The new input stream.
|
||||
/// - parameter outputStream: The new output stream.
|
||||
open func urlSession(
|
||||
_ session: URLSession,
|
||||
streamTask: URLSessionStreamTask,
|
||||
didBecome inputStream: InputStream,
|
||||
outputStream: OutputStream)
|
||||
{
|
||||
streamTaskDidBecomeInputAndOutputStreams?(session, streamTask, inputStream, outputStream)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
776
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/SessionManager.swift
generated
Normal file
776
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/SessionManager.swift
generated
Normal file
@@ -0,0 +1,776 @@
|
||||
//
|
||||
// SessionManager.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`.
|
||||
open class SessionManager {
|
||||
|
||||
// MARK: - Helper Types
|
||||
|
||||
/// Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as
|
||||
/// associated values.
|
||||
///
|
||||
/// - Success: Represents a successful `MultipartFormData` encoding and contains the new `UploadRequest` along with
|
||||
/// streaming information.
|
||||
/// - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding
|
||||
/// error.
|
||||
public enum MultipartFormDataEncodingResult {
|
||||
case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?)
|
||||
case failure(Error)
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// A default instance of `SessionManager`, used by top-level Alamofire request methods, and suitable for use
|
||||
/// directly for any ad hoc requests.
|
||||
open static let `default`: SessionManager = {
|
||||
let configuration = URLSessionConfiguration.default
|
||||
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
|
||||
|
||||
return SessionManager(configuration: configuration)
|
||||
}()
|
||||
|
||||
/// Creates default values for the "Accept-Encoding", "Accept-Language" and "User-Agent" headers.
|
||||
open static let defaultHTTPHeaders: HTTPHeaders = {
|
||||
// Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3
|
||||
let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
|
||||
|
||||
// Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
|
||||
let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in
|
||||
let quality = 1.0 - (Double(index) * 0.1)
|
||||
return "\(languageCode);q=\(quality)"
|
||||
}.joined(separator: ", ")
|
||||
|
||||
// User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
|
||||
// Example: `iOS Example/1.0 (com.alamofire.iOS-Example; build:1; iOS 9.3.0) Alamofire/3.4.2`
|
||||
let userAgent: String = {
|
||||
if let info = Bundle.main.infoDictionary {
|
||||
let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
|
||||
let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
|
||||
let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
|
||||
let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
|
||||
|
||||
let osNameVersion: String = {
|
||||
let version = ProcessInfo.processInfo.operatingSystemVersion
|
||||
let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
|
||||
|
||||
let osName: String = {
|
||||
#if os(iOS)
|
||||
return "iOS"
|
||||
#elseif os(watchOS)
|
||||
return "watchOS"
|
||||
#elseif os(tvOS)
|
||||
return "tvOS"
|
||||
#elseif os(OSX)
|
||||
return "OS X"
|
||||
#elseif os(Linux)
|
||||
return "Linux"
|
||||
#else
|
||||
return "Unknown"
|
||||
#endif
|
||||
}()
|
||||
|
||||
return "\(osName) \(versionString)"
|
||||
}()
|
||||
|
||||
let alamofireVersion: String = {
|
||||
guard
|
||||
let afInfo = Bundle(for: SessionManager.self).infoDictionary,
|
||||
let build = afInfo["CFBundleShortVersionString"]
|
||||
else { return "Unknown" }
|
||||
|
||||
return "Alamofire/\(build)"
|
||||
}()
|
||||
|
||||
return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
|
||||
}
|
||||
|
||||
return "Alamofire"
|
||||
}()
|
||||
|
||||
return [
|
||||
"Accept-Encoding": acceptEncoding,
|
||||
"Accept-Language": acceptLanguage,
|
||||
"User-Agent": userAgent
|
||||
]
|
||||
}()
|
||||
|
||||
/// Default memory threshold used when encoding `MultipartFormData` in bytes.
|
||||
open static let multipartFormDataEncodingMemoryThreshold: UInt64 = 10_000_000
|
||||
|
||||
/// The underlying session.
|
||||
open let session: URLSession
|
||||
|
||||
/// The session delegate handling all the task and session delegate callbacks.
|
||||
open let delegate: SessionDelegate
|
||||
|
||||
/// Whether to start requests immediately after being constructed. `true` by default.
|
||||
open var startRequestsImmediately: Bool = true
|
||||
|
||||
/// The request adapter called each time a new request is created.
|
||||
open var adapter: RequestAdapter?
|
||||
|
||||
/// The request retrier called each time a request encounters an error to determine whether to retry the request.
|
||||
open var retrier: RequestRetrier? {
|
||||
get { return delegate.retrier }
|
||||
set { delegate.retrier = newValue }
|
||||
}
|
||||
|
||||
/// The background completion handler closure provided by the UIApplicationDelegate
|
||||
/// `application:handleEventsForBackgroundURLSession:completionHandler:` method. By setting the background
|
||||
/// completion handler, the SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` closure implementation
|
||||
/// will automatically call the handler.
|
||||
///
|
||||
/// If you need to handle your own events before the handler is called, then you need to override the
|
||||
/// SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` and manually call the handler when finished.
|
||||
///
|
||||
/// `nil` by default.
|
||||
open var backgroundCompletionHandler: (() -> Void)?
|
||||
|
||||
let queue = DispatchQueue(label: "org.alamofire.session-manager." + UUID().uuidString)
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
/// Creates an instance with the specified `configuration`, `delegate` and `serverTrustPolicyManager`.
|
||||
///
|
||||
/// - parameter configuration: The configuration used to construct the managed session.
|
||||
/// `URLSessionConfiguration.default` by default.
|
||||
/// - parameter delegate: The delegate used when initializing the session. `SessionDelegate()` by
|
||||
/// default.
|
||||
/// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
|
||||
/// challenges. `nil` by default.
|
||||
///
|
||||
/// - returns: The new `SessionManager` instance.
|
||||
public init(
|
||||
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
|
||||
delegate: SessionDelegate = SessionDelegate(),
|
||||
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
|
||||
{
|
||||
self.delegate = delegate
|
||||
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
|
||||
|
||||
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
|
||||
}
|
||||
|
||||
/// Creates an instance with the specified `session`, `delegate` and `serverTrustPolicyManager`.
|
||||
///
|
||||
/// - parameter session: The URL session.
|
||||
/// - parameter delegate: The delegate of the URL session. Must equal the URL session's delegate.
|
||||
/// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
|
||||
/// challenges. `nil` by default.
|
||||
///
|
||||
/// - returns: The new `SessionManager` instance if the URL session's delegate matches; `nil` otherwise.
|
||||
public init?(
|
||||
session: URLSession,
|
||||
delegate: SessionDelegate,
|
||||
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
|
||||
{
|
||||
guard delegate === session.delegate else { return nil }
|
||||
|
||||
self.delegate = delegate
|
||||
self.session = session
|
||||
|
||||
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
|
||||
}
|
||||
|
||||
private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) {
|
||||
session.serverTrustPolicyManager = serverTrustPolicyManager
|
||||
|
||||
delegate.sessionManager = self
|
||||
|
||||
delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
|
||||
guard let strongSelf = self else { return }
|
||||
DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
session.invalidateAndCancel()
|
||||
}
|
||||
|
||||
// MARK: - Data Request
|
||||
|
||||
/// Creates a `DataRequest` to retrieve the contents of the specified `url`, `method`, `parameters`, `encoding`
|
||||
/// and `headers`.
|
||||
///
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.get` by default.
|
||||
/// - parameter parameters: The parameters. `nil` by default.
|
||||
/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DataRequest`.
|
||||
@discardableResult
|
||||
open func request(
|
||||
_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> DataRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
|
||||
return request(encodedURLRequest)
|
||||
} catch {
|
||||
return request(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `DataRequest` to retrieve the contents of a URL based on the specified `urlRequest`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `DataRequest`.
|
||||
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
|
||||
do {
|
||||
let originalRequest = try urlRequest.asURLRequest()
|
||||
let originalTask = DataRequest.Requestable(urlRequest: originalRequest)
|
||||
|
||||
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
|
||||
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
|
||||
|
||||
delegate[task] = request
|
||||
|
||||
if startRequestsImmediately { request.resume() }
|
||||
|
||||
return request
|
||||
} catch {
|
||||
return request(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Private - Request Implementation
|
||||
|
||||
private func request(failedWith error: Error) -> DataRequest {
|
||||
let request = DataRequest(session: session, requestTask: .data(nil, nil), error: error)
|
||||
if startRequestsImmediately { request.resume() }
|
||||
return request
|
||||
}
|
||||
|
||||
// MARK: - Download Request
|
||||
|
||||
// MARK: URL Request
|
||||
|
||||
/// Creates a `DownloadRequest` to retrieve the contents the specified `url`, `method`, `parameters`, `encoding`,
|
||||
/// `headers` and save them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.get` by default.
|
||||
/// - parameter parameters: The parameters. `nil` by default.
|
||||
/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
open func download(
|
||||
_ url: URLConvertible,
|
||||
method: HTTPMethod = .get,
|
||||
parameters: Parameters? = nil,
|
||||
encoding: ParameterEncoding = URLEncoding.default,
|
||||
headers: HTTPHeaders? = nil,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
|
||||
return download(encodedURLRequest, to: destination)
|
||||
} catch {
|
||||
return download(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `DownloadRequest` to retrieve the contents of a URL based on the specified `urlRequest` and save
|
||||
/// them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter urlRequest: The URL request
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
open func download(
|
||||
_ urlRequest: URLRequestConvertible,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try urlRequest.asURLRequest()
|
||||
return download(.request(urlRequest), to: destination)
|
||||
} catch {
|
||||
return download(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Resume Data
|
||||
|
||||
/// Creates a `DownloadRequest` from the `resumeData` produced from a previous request cancellation to retrieve
|
||||
/// the contents of the original request and save them to the `destination`.
|
||||
///
|
||||
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
|
||||
/// underlying URL session.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
|
||||
/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for
|
||||
/// additional information.
|
||||
/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `DownloadRequest`.
|
||||
@discardableResult
|
||||
open func download(
|
||||
resumingWith resumeData: Data,
|
||||
to destination: DownloadRequest.DownloadFileDestination? = nil)
|
||||
-> DownloadRequest
|
||||
{
|
||||
return download(.resumeData(resumeData), to: destination)
|
||||
}
|
||||
|
||||
// MARK: Private - Download Implementation
|
||||
|
||||
private func download(
|
||||
_ downloadable: DownloadRequest.Downloadable,
|
||||
to destination: DownloadRequest.DownloadFileDestination?)
|
||||
-> DownloadRequest
|
||||
{
|
||||
do {
|
||||
let task = try downloadable.task(session: session, adapter: adapter, queue: queue)
|
||||
let request = DownloadRequest(session: session, requestTask: .download(downloadable, task))
|
||||
|
||||
request.downloadDelegate.destination = destination
|
||||
|
||||
delegate[task] = request
|
||||
|
||||
if startRequestsImmediately { request.resume() }
|
||||
|
||||
return request
|
||||
} catch {
|
||||
return download(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func download(failedWith error: Error) -> DownloadRequest {
|
||||
let download = DownloadRequest(session: session, requestTask: .download(nil, nil), error: error)
|
||||
if startRequestsImmediately { download.resume() }
|
||||
return download
|
||||
}
|
||||
|
||||
// MARK: - Upload Request
|
||||
|
||||
// MARK: File
|
||||
|
||||
/// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `file`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter file: The file to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(
|
||||
_ fileURL: URL,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
return upload(fileURL, with: urlRequest)
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `UploadRequest` from the specified `urlRequest` for uploading the `file`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter file: The file to upload.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
do {
|
||||
let urlRequest = try urlRequest.asURLRequest()
|
||||
return upload(.file(fileURL, urlRequest))
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Data
|
||||
|
||||
/// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `data`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter data: The data to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(
|
||||
_ data: Data,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
return upload(data, with: urlRequest)
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `data`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter data: The data to upload.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
do {
|
||||
let urlRequest = try urlRequest.asURLRequest()
|
||||
return upload(.data(data, urlRequest))
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: InputStream
|
||||
|
||||
/// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `stream`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter stream: The stream to upload.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(
|
||||
_ stream: InputStream,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil)
|
||||
-> UploadRequest
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
return upload(stream, with: urlRequest)
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `stream`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter stream: The stream to upload.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
///
|
||||
/// - returns: The created `UploadRequest`.
|
||||
@discardableResult
|
||||
open func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest {
|
||||
do {
|
||||
let urlRequest = try urlRequest.asURLRequest()
|
||||
return upload(.stream(stream, urlRequest))
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: MultipartFormData
|
||||
|
||||
/// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new
|
||||
/// `UploadRequest` using the `url`, `method` and `headers`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
|
||||
/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
|
||||
/// `multipartFormDataEncodingMemoryThreshold` by default.
|
||||
/// - parameter url: The URL.
|
||||
/// - parameter method: The HTTP method. `.post` by default.
|
||||
/// - parameter headers: The HTTP headers. `nil` by default.
|
||||
/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
|
||||
open func upload(
|
||||
multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
|
||||
to url: URLConvertible,
|
||||
method: HTTPMethod = .post,
|
||||
headers: HTTPHeaders? = nil,
|
||||
encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
|
||||
{
|
||||
do {
|
||||
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
|
||||
|
||||
return upload(
|
||||
multipartFormData: multipartFormData,
|
||||
usingThreshold: encodingMemoryThreshold,
|
||||
with: urlRequest,
|
||||
encodingCompletion: encodingCompletion
|
||||
)
|
||||
} catch {
|
||||
DispatchQueue.main.async { encodingCompletion?(.failure(error)) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new
|
||||
/// `UploadRequest` using the `urlRequest`.
|
||||
///
|
||||
/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
|
||||
/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
|
||||
/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
|
||||
/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
|
||||
/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
|
||||
/// used for larger payloads such as video content.
|
||||
///
|
||||
/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
|
||||
/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
|
||||
/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
|
||||
/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
|
||||
/// technique was used.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
|
||||
/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
|
||||
/// `multipartFormDataEncodingMemoryThreshold` by default.
|
||||
/// - parameter urlRequest: The URL request.
|
||||
/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
|
||||
open func upload(
|
||||
multipartFormData: @escaping (MultipartFormData) -> Void,
|
||||
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
|
||||
with urlRequest: URLRequestConvertible,
|
||||
encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
|
||||
{
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
let formData = MultipartFormData()
|
||||
multipartFormData(formData)
|
||||
|
||||
do {
|
||||
var urlRequestWithContentType = try urlRequest.asURLRequest()
|
||||
urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
|
||||
|
||||
let isBackgroundSession = self.session.configuration.identifier != nil
|
||||
|
||||
if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
|
||||
let data = try formData.encode()
|
||||
|
||||
let encodingResult = MultipartFormDataEncodingResult.success(
|
||||
request: self.upload(data, with: urlRequestWithContentType),
|
||||
streamingFromDisk: false,
|
||||
streamFileURL: nil
|
||||
)
|
||||
|
||||
DispatchQueue.main.async { encodingCompletion?(encodingResult) }
|
||||
} else {
|
||||
let fileManager = FileManager.default
|
||||
let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
|
||||
let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
|
||||
let fileName = UUID().uuidString
|
||||
let fileURL = directoryURL.appendingPathComponent(fileName)
|
||||
|
||||
var directoryError: Error?
|
||||
|
||||
// Create directory inside serial queue to ensure two threads don't do this in parallel
|
||||
self.queue.sync {
|
||||
do {
|
||||
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
|
||||
} catch {
|
||||
directoryError = error
|
||||
}
|
||||
}
|
||||
|
||||
if let directoryError = directoryError { throw directoryError }
|
||||
|
||||
try formData.writeEncodedData(to: fileURL)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
let encodingResult = MultipartFormDataEncodingResult.success(
|
||||
request: self.upload(fileURL, with: urlRequestWithContentType),
|
||||
streamingFromDisk: true,
|
||||
streamFileURL: fileURL
|
||||
)
|
||||
encodingCompletion?(encodingResult)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
DispatchQueue.main.async { encodingCompletion?(.failure(error)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Private - Upload Implementation
|
||||
|
||||
private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest {
|
||||
do {
|
||||
let task = try uploadable.task(session: session, adapter: adapter, queue: queue)
|
||||
let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task))
|
||||
|
||||
if case let .stream(inputStream, _) = uploadable {
|
||||
upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream }
|
||||
}
|
||||
|
||||
delegate[task] = upload
|
||||
|
||||
if startRequestsImmediately { upload.resume() }
|
||||
|
||||
return upload
|
||||
} catch {
|
||||
return upload(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func upload(failedWith error: Error) -> UploadRequest {
|
||||
let upload = UploadRequest(session: session, requestTask: .upload(nil, nil), error: error)
|
||||
if startRequestsImmediately { upload.resume() }
|
||||
return upload
|
||||
}
|
||||
|
||||
#if !os(watchOS)
|
||||
|
||||
// MARK: - Stream Request
|
||||
|
||||
// MARK: Hostname and Port
|
||||
|
||||
/// Creates a `StreamRequest` for bidirectional streaming using the `hostname` and `port`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter hostName: The hostname of the server to connect to.
|
||||
/// - parameter port: The port of the server to connect to.
|
||||
///
|
||||
/// - returns: The created `StreamRequest`.
|
||||
@discardableResult
|
||||
open func stream(withHostName hostName: String, port: Int) -> StreamRequest {
|
||||
return stream(.stream(hostName: hostName, port: port))
|
||||
}
|
||||
|
||||
// MARK: NetService
|
||||
|
||||
/// Creates a `StreamRequest` for bidirectional streaming using the `netService`.
|
||||
///
|
||||
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
|
||||
///
|
||||
/// - parameter netService: The net service used to identify the endpoint.
|
||||
///
|
||||
/// - returns: The created `StreamRequest`.
|
||||
@discardableResult
|
||||
open func stream(with netService: NetService) -> StreamRequest {
|
||||
return stream(.netService(netService))
|
||||
}
|
||||
|
||||
// MARK: Private - Stream Implementation
|
||||
|
||||
private func stream(_ streamable: StreamRequest.Streamable) -> StreamRequest {
|
||||
do {
|
||||
let task = try streamable.task(session: session, adapter: adapter, queue: queue)
|
||||
let request = StreamRequest(session: session, requestTask: .stream(streamable, task))
|
||||
|
||||
delegate[task] = request
|
||||
|
||||
if startRequestsImmediately { request.resume() }
|
||||
|
||||
return request
|
||||
} catch {
|
||||
return stream(failedWith: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func stream(failedWith error: Error) -> StreamRequest {
|
||||
let stream = StreamRequest(session: session, requestTask: .stream(nil, nil), error: error)
|
||||
if startRequestsImmediately { stream.resume() }
|
||||
return stream
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - Internal - Retry Request
|
||||
|
||||
func retry(_ request: Request) -> Bool {
|
||||
guard let originalTask = request.originalTask else { return false }
|
||||
|
||||
do {
|
||||
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
|
||||
|
||||
request.delegate.task = task // resets all task delegate data
|
||||
|
||||
request.startTime = CFAbsoluteTimeGetCurrent()
|
||||
request.endTime = nil
|
||||
|
||||
task.resume()
|
||||
|
||||
return true
|
||||
} catch {
|
||||
request.delegate.error = error
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
448
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/TaskDelegate.swift
generated
Normal file
448
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/TaskDelegate.swift
generated
Normal file
@@ -0,0 +1,448 @@
|
||||
//
|
||||
// TaskDelegate.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// The task delegate is responsible for handling all delegate callbacks for the underlying task as well as
|
||||
/// executing all operations attached to the serial operation queue upon task completion.
|
||||
open class TaskDelegate: NSObject {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The serial operation queue used to execute all operations after the task completes.
|
||||
open let queue: OperationQueue
|
||||
|
||||
var task: URLSessionTask? {
|
||||
didSet { reset() }
|
||||
}
|
||||
|
||||
var data: Data? { return nil }
|
||||
var error: Error?
|
||||
|
||||
var initialResponseTime: CFAbsoluteTime?
|
||||
var credential: URLCredential?
|
||||
var metrics: AnyObject? // URLSessionTaskMetrics
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
init(task: URLSessionTask?) {
|
||||
self.task = task
|
||||
|
||||
self.queue = {
|
||||
let operationQueue = OperationQueue()
|
||||
|
||||
operationQueue.maxConcurrentOperationCount = 1
|
||||
operationQueue.isSuspended = true
|
||||
operationQueue.qualityOfService = .utility
|
||||
|
||||
return operationQueue
|
||||
}()
|
||||
}
|
||||
|
||||
func reset() {
|
||||
error = nil
|
||||
initialResponseTime = nil
|
||||
}
|
||||
|
||||
// MARK: URLSessionTaskDelegate
|
||||
|
||||
var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?
|
||||
var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
|
||||
var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)?
|
||||
var taskDidCompleteWithError: ((URLSession, URLSessionTask, Error?) -> Void)?
|
||||
|
||||
@objc(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
willPerformHTTPRedirection response: HTTPURLResponse,
|
||||
newRequest request: URLRequest,
|
||||
completionHandler: @escaping (URLRequest?) -> Void)
|
||||
{
|
||||
var redirectRequest: URLRequest? = request
|
||||
|
||||
if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
|
||||
redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
|
||||
}
|
||||
|
||||
completionHandler(redirectRequest)
|
||||
}
|
||||
|
||||
@objc(URLSession:task:didReceiveChallenge:completionHandler:)
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
didReceive challenge: URLAuthenticationChallenge,
|
||||
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
|
||||
{
|
||||
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
|
||||
var credential: URLCredential?
|
||||
|
||||
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
|
||||
(disposition, credential) = taskDidReceiveChallenge(session, task, challenge)
|
||||
} else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
|
||||
let host = challenge.protectionSpace.host
|
||||
|
||||
if let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
|
||||
let serverTrust = challenge.protectionSpace.serverTrust
|
||||
{
|
||||
if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
|
||||
disposition = .useCredential
|
||||
credential = URLCredential(trust: serverTrust)
|
||||
} else {
|
||||
disposition = .cancelAuthenticationChallenge
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if challenge.previousFailureCount > 0 {
|
||||
disposition = .rejectProtectionSpace
|
||||
} else {
|
||||
credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
|
||||
|
||||
if credential != nil {
|
||||
disposition = .useCredential
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
completionHandler(disposition, credential)
|
||||
}
|
||||
|
||||
@objc(URLSession:task:needNewBodyStream:)
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
|
||||
{
|
||||
var bodyStream: InputStream?
|
||||
|
||||
if let taskNeedNewBodyStream = taskNeedNewBodyStream {
|
||||
bodyStream = taskNeedNewBodyStream(session, task)
|
||||
}
|
||||
|
||||
completionHandler(bodyStream)
|
||||
}
|
||||
|
||||
@objc(URLSession:task:didCompleteWithError:)
|
||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
if let taskDidCompleteWithError = taskDidCompleteWithError {
|
||||
taskDidCompleteWithError(session, task, error)
|
||||
} else {
|
||||
if let error = error {
|
||||
if self.error == nil { self.error = error }
|
||||
|
||||
if
|
||||
let downloadDelegate = self as? DownloadTaskDelegate,
|
||||
let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data
|
||||
{
|
||||
downloadDelegate.resumeData = resumeData
|
||||
}
|
||||
}
|
||||
|
||||
queue.isSuspended = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
var dataTask: URLSessionDataTask { return task as! URLSessionDataTask }
|
||||
|
||||
override var data: Data? {
|
||||
if dataStream != nil {
|
||||
return nil
|
||||
} else {
|
||||
return mutableData
|
||||
}
|
||||
}
|
||||
|
||||
var progress: Progress
|
||||
var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
|
||||
|
||||
var dataStream: ((_ data: Data) -> Void)?
|
||||
|
||||
private var totalBytesReceived: Int64 = 0
|
||||
private var mutableData: Data
|
||||
|
||||
private var expectedContentLength: Int64?
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
override init(task: URLSessionTask?) {
|
||||
mutableData = Data()
|
||||
progress = Progress(totalUnitCount: 0)
|
||||
|
||||
super.init(task: task)
|
||||
}
|
||||
|
||||
override func reset() {
|
||||
super.reset()
|
||||
|
||||
progress = Progress(totalUnitCount: 0)
|
||||
totalBytesReceived = 0
|
||||
mutableData = Data()
|
||||
expectedContentLength = nil
|
||||
}
|
||||
|
||||
// MARK: URLSessionDataDelegate
|
||||
|
||||
var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)?
|
||||
var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)?
|
||||
var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
|
||||
var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
didReceive response: URLResponse,
|
||||
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
|
||||
{
|
||||
var disposition: URLSession.ResponseDisposition = .allow
|
||||
|
||||
expectedContentLength = response.expectedContentLength
|
||||
|
||||
if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
|
||||
disposition = dataTaskDidReceiveResponse(session, dataTask, response)
|
||||
}
|
||||
|
||||
completionHandler(disposition)
|
||||
}
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
didBecome downloadTask: URLSessionDownloadTask)
|
||||
{
|
||||
dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask)
|
||||
}
|
||||
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
|
||||
|
||||
if let dataTaskDidReceiveData = dataTaskDidReceiveData {
|
||||
dataTaskDidReceiveData(session, dataTask, data)
|
||||
} else {
|
||||
if let dataStream = dataStream {
|
||||
dataStream(data)
|
||||
} else {
|
||||
mutableData.append(data)
|
||||
}
|
||||
|
||||
let bytesReceived = Int64(data.count)
|
||||
totalBytesReceived += bytesReceived
|
||||
let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
|
||||
|
||||
progress.totalUnitCount = totalBytesExpected
|
||||
progress.completedUnitCount = totalBytesReceived
|
||||
|
||||
if let progressHandler = progressHandler {
|
||||
progressHandler.queue.async { progressHandler.closure(self.progress) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
dataTask: URLSessionDataTask,
|
||||
willCacheResponse proposedResponse: CachedURLResponse,
|
||||
completionHandler: @escaping (CachedURLResponse?) -> Void)
|
||||
{
|
||||
var cachedResponse: CachedURLResponse? = proposedResponse
|
||||
|
||||
if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
|
||||
cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse)
|
||||
}
|
||||
|
||||
completionHandler(cachedResponse)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
var downloadTask: URLSessionDownloadTask { return task as! URLSessionDownloadTask }
|
||||
|
||||
var progress: Progress
|
||||
var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
|
||||
|
||||
var resumeData: Data?
|
||||
override var data: Data? { return resumeData }
|
||||
|
||||
var destination: DownloadRequest.DownloadFileDestination?
|
||||
|
||||
var temporaryURL: URL?
|
||||
var destinationURL: URL?
|
||||
|
||||
var fileURL: URL? { return destination != nil ? destinationURL : temporaryURL }
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
override init(task: URLSessionTask?) {
|
||||
progress = Progress(totalUnitCount: 0)
|
||||
super.init(task: task)
|
||||
}
|
||||
|
||||
override func reset() {
|
||||
super.reset()
|
||||
|
||||
progress = Progress(totalUnitCount: 0)
|
||||
resumeData = nil
|
||||
}
|
||||
|
||||
// MARK: URLSessionDownloadDelegate
|
||||
|
||||
var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> URL)?
|
||||
var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
|
||||
var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didFinishDownloadingTo location: URL)
|
||||
{
|
||||
temporaryURL = location
|
||||
|
||||
if let destination = destination {
|
||||
let result = destination(location, downloadTask.response as! HTTPURLResponse)
|
||||
let destination = result.destinationURL
|
||||
let options = result.options
|
||||
|
||||
do {
|
||||
destinationURL = destination
|
||||
|
||||
if options.contains(.removePreviousFile) {
|
||||
if FileManager.default.fileExists(atPath: destination.path) {
|
||||
try FileManager.default.removeItem(at: destination)
|
||||
}
|
||||
}
|
||||
|
||||
if options.contains(.createIntermediateDirectories) {
|
||||
let directory = destination.deletingLastPathComponent()
|
||||
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
|
||||
try FileManager.default.moveItem(at: location, to: destination)
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didWriteData bytesWritten: Int64,
|
||||
totalBytesWritten: Int64,
|
||||
totalBytesExpectedToWrite: Int64)
|
||||
{
|
||||
if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
|
||||
|
||||
if let downloadTaskDidWriteData = downloadTaskDidWriteData {
|
||||
downloadTaskDidWriteData(
|
||||
session,
|
||||
downloadTask,
|
||||
bytesWritten,
|
||||
totalBytesWritten,
|
||||
totalBytesExpectedToWrite
|
||||
)
|
||||
} else {
|
||||
progress.totalUnitCount = totalBytesExpectedToWrite
|
||||
progress.completedUnitCount = totalBytesWritten
|
||||
|
||||
if let progressHandler = progressHandler {
|
||||
progressHandler.queue.async { progressHandler.closure(self.progress) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func urlSession(
|
||||
_ session: URLSession,
|
||||
downloadTask: URLSessionDownloadTask,
|
||||
didResumeAtOffset fileOffset: Int64,
|
||||
expectedTotalBytes: Int64)
|
||||
{
|
||||
if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
|
||||
downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
|
||||
} else {
|
||||
progress.totalUnitCount = expectedTotalBytes
|
||||
progress.completedUnitCount = fileOffset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
class UploadTaskDelegate: DataTaskDelegate {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
var uploadTask: URLSessionUploadTask { return task as! URLSessionUploadTask }
|
||||
|
||||
var uploadProgress: Progress
|
||||
var uploadProgressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
override init(task: URLSessionTask?) {
|
||||
uploadProgress = Progress(totalUnitCount: 0)
|
||||
super.init(task: task)
|
||||
}
|
||||
|
||||
override func reset() {
|
||||
super.reset()
|
||||
uploadProgress = Progress(totalUnitCount: 0)
|
||||
}
|
||||
|
||||
// MARK: URLSessionTaskDelegate
|
||||
|
||||
var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
|
||||
|
||||
func URLSession(
|
||||
_ session: URLSession,
|
||||
task: URLSessionTask,
|
||||
didSendBodyData bytesSent: Int64,
|
||||
totalBytesSent: Int64,
|
||||
totalBytesExpectedToSend: Int64)
|
||||
{
|
||||
if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
|
||||
|
||||
if let taskDidSendBodyData = taskDidSendBodyData {
|
||||
taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
|
||||
} else {
|
||||
uploadProgress.totalUnitCount = totalBytesExpectedToSend
|
||||
uploadProgress.completedUnitCount = totalBytesSent
|
||||
|
||||
if let uploadProgressHandler = uploadProgressHandler {
|
||||
uploadProgressHandler.queue.async { uploadProgressHandler.closure(self.uploadProgress) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Timeline.swift
generated
Normal file
136
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Timeline.swift
generated
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// Timeline.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Responsible for computing the timing metrics for the complete lifecycle of a `Request`.
|
||||
public struct Timeline {
|
||||
/// The time the request was initialized.
|
||||
public let requestStartTime: CFAbsoluteTime
|
||||
|
||||
/// The time the first bytes were received from or sent to the server.
|
||||
public let initialResponseTime: CFAbsoluteTime
|
||||
|
||||
/// The time when the request was completed.
|
||||
public let requestCompletedTime: CFAbsoluteTime
|
||||
|
||||
/// The time when the response serialization was completed.
|
||||
public let serializationCompletedTime: CFAbsoluteTime
|
||||
|
||||
/// The time interval in seconds from the time the request started to the initial response from the server.
|
||||
public let latency: TimeInterval
|
||||
|
||||
/// The time interval in seconds from the time the request started to the time the request completed.
|
||||
public let requestDuration: TimeInterval
|
||||
|
||||
/// The time interval in seconds from the time the request completed to the time response serialization completed.
|
||||
public let serializationDuration: TimeInterval
|
||||
|
||||
/// The time interval in seconds from the time the request started to the time response serialization completed.
|
||||
public let totalDuration: TimeInterval
|
||||
|
||||
/// Creates a new `Timeline` instance with the specified request times.
|
||||
///
|
||||
/// - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`.
|
||||
/// - parameter initialResponseTime: The time the first bytes were received from or sent to the server.
|
||||
/// Defaults to `0.0`.
|
||||
/// - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`.
|
||||
/// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults
|
||||
/// to `0.0`.
|
||||
///
|
||||
/// - returns: The new `Timeline` instance.
|
||||
public init(
|
||||
requestStartTime: CFAbsoluteTime = 0.0,
|
||||
initialResponseTime: CFAbsoluteTime = 0.0,
|
||||
requestCompletedTime: CFAbsoluteTime = 0.0,
|
||||
serializationCompletedTime: CFAbsoluteTime = 0.0)
|
||||
{
|
||||
self.requestStartTime = requestStartTime
|
||||
self.initialResponseTime = initialResponseTime
|
||||
self.requestCompletedTime = requestCompletedTime
|
||||
self.serializationCompletedTime = serializationCompletedTime
|
||||
|
||||
self.latency = initialResponseTime - requestStartTime
|
||||
self.requestDuration = requestCompletedTime - requestStartTime
|
||||
self.serializationDuration = serializationCompletedTime - requestCompletedTime
|
||||
self.totalDuration = serializationCompletedTime - requestStartTime
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomStringConvertible
|
||||
|
||||
extension Timeline: CustomStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes the latency, the request
|
||||
/// duration and the total duration.
|
||||
public var description: String {
|
||||
let latency = String(format: "%.3f", self.latency)
|
||||
let requestDuration = String(format: "%.3f", self.requestDuration)
|
||||
let serializationDuration = String(format: "%.3f", self.serializationDuration)
|
||||
let totalDuration = String(format: "%.3f", self.totalDuration)
|
||||
|
||||
// NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
|
||||
// fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
|
||||
let timings = [
|
||||
"\"Latency\": " + latency + " secs",
|
||||
"\"Request Duration\": " + requestDuration + " secs",
|
||||
"\"Serialization Duration\": " + serializationDuration + " secs",
|
||||
"\"Total Duration\": " + totalDuration + " secs"
|
||||
]
|
||||
|
||||
return "Timeline: { " + timings.joined(separator: ", ") + " }"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomDebugStringConvertible
|
||||
|
||||
extension Timeline: CustomDebugStringConvertible {
|
||||
/// The textual representation used when written to an output stream, which includes the request start time, the
|
||||
/// initial response time, the request completed time, the serialization completed time, the latency, the request
|
||||
/// duration and the total duration.
|
||||
public var debugDescription: String {
|
||||
let requestStartTime = String(format: "%.3f", self.requestStartTime)
|
||||
let initialResponseTime = String(format: "%.3f", self.initialResponseTime)
|
||||
let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime)
|
||||
let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime)
|
||||
let latency = String(format: "%.3f", self.latency)
|
||||
let requestDuration = String(format: "%.3f", self.requestDuration)
|
||||
let serializationDuration = String(format: "%.3f", self.serializationDuration)
|
||||
let totalDuration = String(format: "%.3f", self.totalDuration)
|
||||
|
||||
// NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
|
||||
// fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
|
||||
let timings = [
|
||||
"\"Request Start Time\": " + requestStartTime,
|
||||
"\"Initial Response Time\": " + initialResponseTime,
|
||||
"\"Request Completed Time\": " + requestCompletedTime,
|
||||
"\"Serialization Completed Time\": " + serializationCompletedTime,
|
||||
"\"Latency\": " + latency + " secs",
|
||||
"\"Request Duration\": " + requestDuration + " secs",
|
||||
"\"Serialization Duration\": " + serializationDuration + " secs",
|
||||
"\"Total Duration\": " + totalDuration + " secs"
|
||||
]
|
||||
|
||||
return "Timeline: { " + timings.joined(separator: ", ") + " }"
|
||||
}
|
||||
}
|
||||
309
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Validation.swift
generated
Normal file
309
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Alamofire/Source/Validation.swift
generated
Normal file
@@ -0,0 +1,309 @@
|
||||
//
|
||||
// Validation.swift
|
||||
//
|
||||
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Request {
|
||||
|
||||
// MARK: Helper Types
|
||||
|
||||
fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
|
||||
|
||||
/// Used to represent whether validation was successful or encountered an error resulting in a failure.
|
||||
///
|
||||
/// - success: The validation was successful.
|
||||
/// - failure: The validation failed encountering the provided error.
|
||||
public enum ValidationResult {
|
||||
case success
|
||||
case failure(Error)
|
||||
}
|
||||
|
||||
fileprivate struct MIMEType {
|
||||
let type: String
|
||||
let subtype: String
|
||||
|
||||
var isWildcard: Bool { return type == "*" && subtype == "*" }
|
||||
|
||||
init?(_ string: String) {
|
||||
let components: [String] = {
|
||||
let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)
|
||||
return split.components(separatedBy: "/")
|
||||
}()
|
||||
|
||||
if let type = components.first, let subtype = components.last {
|
||||
self.type = type
|
||||
self.subtype = subtype
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func matches(_ mime: MIMEType) -> Bool {
|
||||
switch (type, subtype) {
|
||||
case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
fileprivate var acceptableStatusCodes: [Int] { return Array(200..<300) }
|
||||
|
||||
fileprivate var acceptableContentTypes: [String] {
|
||||
if let accept = request?.value(forHTTPHeaderField: "Accept") {
|
||||
return accept.components(separatedBy: ",")
|
||||
}
|
||||
|
||||
return ["*/*"]
|
||||
}
|
||||
|
||||
// MARK: Status Code
|
||||
|
||||
fileprivate func validate<S: Sequence>(
|
||||
statusCode acceptableStatusCodes: S,
|
||||
response: HTTPURLResponse)
|
||||
-> ValidationResult
|
||||
where S.Iterator.Element == Int
|
||||
{
|
||||
if acceptableStatusCodes.contains(response.statusCode) {
|
||||
return .success
|
||||
} else {
|
||||
let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode)
|
||||
return .failure(AFError.responseValidationFailed(reason: reason))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Content Type
|
||||
|
||||
fileprivate func validate<S: Sequence>(
|
||||
contentType acceptableContentTypes: S,
|
||||
response: HTTPURLResponse,
|
||||
data: Data?)
|
||||
-> ValidationResult
|
||||
where S.Iterator.Element == String
|
||||
{
|
||||
guard let data = data, data.count > 0 else { return .success }
|
||||
|
||||
guard
|
||||
let responseContentType = response.mimeType,
|
||||
let responseMIMEType = MIMEType(responseContentType)
|
||||
else {
|
||||
for contentType in acceptableContentTypes {
|
||||
if let mimeType = MIMEType(contentType), mimeType.isWildcard {
|
||||
return .success
|
||||
}
|
||||
}
|
||||
|
||||
let error: AFError = {
|
||||
let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes))
|
||||
return AFError.responseValidationFailed(reason: reason)
|
||||
}()
|
||||
|
||||
return .failure(error)
|
||||
}
|
||||
|
||||
for contentType in acceptableContentTypes {
|
||||
if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) {
|
||||
return .success
|
||||
}
|
||||
}
|
||||
|
||||
let error: AFError = {
|
||||
let reason: ErrorReason = .unacceptableContentType(
|
||||
acceptableContentTypes: Array(acceptableContentTypes),
|
||||
responseContentType: responseContentType
|
||||
)
|
||||
|
||||
return AFError.responseValidationFailed(reason: reason)
|
||||
}()
|
||||
|
||||
return .failure(error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension DataRequest {
|
||||
/// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
|
||||
/// request was valid.
|
||||
public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
|
||||
|
||||
/// Validates the request, using the specified closure.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter validation: A closure to validate the request.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate(_ validation: @escaping Validation) -> Self {
|
||||
let validationExecution: () -> Void = {
|
||||
if
|
||||
let response = self.response,
|
||||
self.delegate.error == nil,
|
||||
case let .failure(error) = validation(self.request, response, self.delegate.data)
|
||||
{
|
||||
self.delegate.error = error
|
||||
}
|
||||
}
|
||||
|
||||
validations.append(validationExecution)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Validates that the response has a status code in the specified sequence.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter range: The range of acceptable status codes.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
|
||||
return validate { _, response, _ in
|
||||
return self.validate(statusCode: acceptableStatusCodes, response: response)
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that the response has a content type in the specified sequence.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate<S: Sequence>(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String {
|
||||
return validate { _, response, data in
|
||||
return self.validate(contentType: acceptableContentTypes, response: response, data: data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
|
||||
/// type matches any specified in the Accept HTTP header field.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate() -> Self {
|
||||
return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension DownloadRequest {
|
||||
/// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
|
||||
/// destination URL, and returns whether the request was valid.
|
||||
public typealias Validation = (
|
||||
_ request: URLRequest?,
|
||||
_ response: HTTPURLResponse,
|
||||
_ temporaryURL: URL?,
|
||||
_ destinationURL: URL?)
|
||||
-> ValidationResult
|
||||
|
||||
/// Validates the request, using the specified closure.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter validation: A closure to validate the request.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate(_ validation: @escaping Validation) -> Self {
|
||||
let validationExecution: () -> Void = {
|
||||
let request = self.request
|
||||
let temporaryURL = self.downloadDelegate.temporaryURL
|
||||
let destinationURL = self.downloadDelegate.destinationURL
|
||||
|
||||
if
|
||||
let response = self.response,
|
||||
self.delegate.error == nil,
|
||||
case let .failure(error) = validation(request, response, temporaryURL, destinationURL)
|
||||
{
|
||||
self.delegate.error = error
|
||||
}
|
||||
}
|
||||
|
||||
validations.append(validationExecution)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Validates that the response has a status code in the specified sequence.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter range: The range of acceptable status codes.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
|
||||
return validate { _, response, _, _ in
|
||||
return self.validate(statusCode: acceptableStatusCodes, response: response)
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that the response has a content type in the specified sequence.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate<S: Sequence>(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String {
|
||||
return validate { _, response, _, _ in
|
||||
let fileURL = self.downloadDelegate.fileURL
|
||||
|
||||
guard let validFileURL = fileURL else {
|
||||
return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
|
||||
}
|
||||
|
||||
do {
|
||||
let data = try Data(contentsOf: validFileURL)
|
||||
return self.validate(contentType: acceptableContentTypes, response: response, data: data)
|
||||
} catch {
|
||||
return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
|
||||
/// type matches any specified in the Accept HTTP header field.
|
||||
///
|
||||
/// If validation fails, subsequent calls to response handlers will have an associated error.
|
||||
///
|
||||
/// - returns: The request.
|
||||
@discardableResult
|
||||
public func validate() -> Self {
|
||||
return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "PetstoreClient",
|
||||
"platforms": {
|
||||
"ios": "9.0",
|
||||
"osx": "10.11"
|
||||
},
|
||||
"version": "0.0.1",
|
||||
"source": {
|
||||
"git": "git@github.com:swagger-api/swagger-mustache.git",
|
||||
"tag": "v1.0.0"
|
||||
},
|
||||
"authors": "",
|
||||
"license": "Apache License, Version 2.0",
|
||||
"homepage": "https://github.com/swagger-api/swagger-codegen",
|
||||
"summary": "PetstoreClient",
|
||||
"source_files": "PetstoreClient/Classes/Swaggers/**/*.swift",
|
||||
"dependencies": {
|
||||
"Alamofire": [
|
||||
"~> 4.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
19
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Manifest.lock
generated
Normal file
19
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Manifest.lock
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
PODS:
|
||||
- Alamofire (4.0.0)
|
||||
- PetstoreClient (0.0.1):
|
||||
- Alamofire (~> 4.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- PetstoreClient (from `../`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
PetstoreClient:
|
||||
:path: ../
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: fef59f00388f267e52d9b432aa5d93dc97190f14
|
||||
PetstoreClient: bbde3383c51466fdda24ec28153ce2847ae5456f
|
||||
|
||||
PODFILE CHECKSUM: da9f5a7ad6086f2c7abb73cf2c35cefce04a9a30
|
||||
|
||||
COCOAPODS: 1.0.1
|
||||
1119
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Pods.xcodeproj/project.pbxproj
generated
Normal file
1119
samples/client/petstore/swift3/default/SwaggerClientTests/Pods/Pods.xcodeproj/project.pbxproj
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_Alamofire : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_Alamofire
|
||||
@end
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
FOUNDATION_EXPORT double AlamofireVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user