diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java index 62fc70efdea..377c8de24d9 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/AndroidClientCodegen.java @@ -47,26 +47,6 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi "native", "super", "while") ); - additionalProperties.put("invokerPackage", invokerPackage); - additionalProperties.put("groupId", groupId); - additionalProperties.put("artifactId", artifactId); - additionalProperties.put("artifactVersion", artifactVersion); - - supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); - - supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); - supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); - supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); - supportingFiles.add(new SupportingFile("apiInvoker.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); - supportingFiles.add(new SupportingFile("httpPatch.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java")); - supportingFiles.add(new SupportingFile("jsonUtil.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); - supportingFiles.add(new SupportingFile("apiException.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); - languageSpecificPrimitives = new HashSet( Arrays.asList( "String", @@ -80,6 +60,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi ); instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("map", "HashMap"); + + cliOptions.add(new CliOption("invokerPackage", "root package to use for the generated code")); + cliOptions.add(new CliOption("groupId", "groupId for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("artifactId", "artifactId for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("artifactVersion", "artifact version for use in the generated build.gradle and pom.xml")); + cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); + cliOptions.add(new CliOption("useAndroidMavenGradlePlugin", "A flag to toggle android-maven gradle plugin. Default is true.")); } @Override @@ -177,6 +164,96 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi return camelize(operationId, true); } + + @Override + public void processOpts() { + super.processOpts(); + + if(additionalProperties.containsKey("invokerPackage")) { + this.setInvokerPackage((String)additionalProperties.get("invokerPackage")); + } + else{ + //not set, use default to be passed to template + additionalProperties.put("invokerPackage", invokerPackage); + } + + if(additionalProperties.containsKey("groupId")) { + this.setGroupId((String)additionalProperties.get("groupId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("groupId", groupId); + } + + if(additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String)additionalProperties.get("artifactId")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactId", artifactId); + } + + if(additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String)additionalProperties.get("artifactVersion")); + } + else{ + //not set, use to be passed to template + additionalProperties.put("artifactVersion", artifactVersion); + } + + if(additionalProperties.containsKey("sourceFolder")) { + this.setSourceFolder((String)additionalProperties.get("sourceFolder")); + } + if(additionalProperties.containsKey("useAndroidMavenGradlePlugin")) { + this.setUseAndroidMavenGradlePlugin((Boolean)additionalProperties.get("useAndroidMavenGradlePlugin")); + } + else{ + additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); + } + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin); + + supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); + supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); + supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); + supportingFiles.add(new SupportingFile("apiInvoker.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); + supportingFiles.add(new SupportingFile("httpPatch.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java")); + supportingFiles.add(new SupportingFile("jsonUtil.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); + supportingFiles.add(new SupportingFile("apiException.mustache", + (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); + } + + public Boolean getUseAndroidMavenGradlePlugin() { + return useAndroidMavenGradlePlugin; + } + + public void setUseAndroidMavenGradlePlugin(Boolean useAndroidMavenGradlePlugin) { + this.useAndroidMavenGradlePlugin = useAndroidMavenGradlePlugin; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } } diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java index fe15b75f82d..6d9966c7fe4 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java @@ -106,17 +106,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { this.setSourceFolder((String)additionalProperties.get("sourceFolder")); } + final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiClient.java")); - supportingFiles.add(new SupportingFile("Configuration.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Configuration.java")); - supportingFiles.add(new SupportingFile("JsonUtil.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java")); - supportingFiles.add(new SupportingFile("StringUtil.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "StringUtil.java")); - supportingFiles.add(new SupportingFile("apiException.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java")); + supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); + supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); + supportingFiles.add(new SupportingFile("JsonUtil.mustache", invokerFolder, "JsonUtil.java")); + supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); + + final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator); + supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); + supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); + supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); + supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); } diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JaxRSServerCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JaxRSServerCodegen.java index 0bc8097d671..4631a804fc7 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JaxRSServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JaxRSServerCodegen.java @@ -27,7 +27,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf } public JaxRSServerCodegen() { - super(); + super.processOpts(); sourceFolder = "src/gen/java"; @@ -37,7 +37,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf apiTemplateFiles.put("apiService.mustache", ".java"); apiTemplateFiles.put("apiServiceImpl.mustache", ".java"); apiTemplateFiles.put("apiServiceFactory.mustache", ".java"); - templateDir = "JavaJaxRS"; apiPackage = System.getProperty( "swagger.codegen.jaxrs.apipackage", "io.swagger.api") ; modelPackage = System.getProperty( "swagger.codegen.jaxrs.modelpackage", "io.swagger.model" ); @@ -48,6 +47,24 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put("title", title); + + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "String", + "boolean", + "Boolean", + "Double", + "Integer", + "Long", + "Float") + ); + } + + + @Override + public void processOpts() { + super.processOpts(); + supportingFiles.clear(); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); @@ -62,16 +79,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf supportingFiles.add(new SupportingFile("web.mustache", ("src/main/webapp/WEB-INF"), "web.xml")); - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "String", - "boolean", - "Boolean", - "Double", - "Integer", - "Long", - "Float") - ); } @Override diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java index 97c9752cd3d..ab1cf2ec8d7 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/ObjcClientCodegen.java @@ -140,6 +140,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h")); + supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m")); + supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h")); supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile")); } diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java index 6fb7a7d70c1..2f643724b14 100644 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -82,6 +82,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("map", "map"); typeMapping.put("array", "array"); typeMapping.put("list", "array"); + typeMapping.put("object", "object"); supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json")); supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php")); diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java index 590e17f6326..7f9a77d3132 100755 --- a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java @@ -27,15 +27,16 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig super(); eggPackage = module + "-python"; - invokerPackage = eggPackage + "/" + module; + + invokerPackage = eggPackage + File.separatorChar + module; - outputFolder = "generated-code/python"; + outputFolder = "generated-code" + File.separatorChar + "python"; modelTemplateFiles.put("model.mustache", ".py"); apiTemplateFiles.put("api.mustache", ".py"); templateDir = "python"; - apiPackage = invokerPackage + ".apis"; - modelPackage = invokerPackage + ".models"; + apiPackage = invokerPackage + File.separatorChar + "apis"; + modelPackage = invokerPackage + File.separatorChar + "models"; languageSpecificPrimitives.clear(); languageSpecificPrimitives.add("int"); @@ -68,13 +69,12 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig supportingFiles.add(new SupportingFile("README.mustache", eggPackage, "README.md")); supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py")); - supportingFiles.add(new SupportingFile("swagger.mustache", invokerPackage, "swagger.py")); + supportingFiles.add(new SupportingFile("api_client.mustache", invokerPackage, "api_client.py")); supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py")); - supportingFiles.add(new SupportingFile("util.mustache", invokerPackage, "util.py")); - supportingFiles.add(new SupportingFile("config.mustache", invokerPackage, "config.py")); + supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage, "configuration.py")); supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py")); - supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage.replace('.', File.separatorChar), "__init__.py")); - supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage.replace('.', File.separatorChar), "__init__.py")); + supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py")); + supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py")); } @Override @@ -84,11 +84,11 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String apiFileFolder() { - return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); + return outputFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar); } public String modelFileFolder() { - return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); + return outputFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar); } @Override diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 3cdab739907..352401ba0d8 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -16,8 +16,8 @@ import com.sun.jersey.multipart.FormDataMultiPart; import javax.ws.rs.core.Response.Status.Family; import javax.ws.rs.core.MediaType; -import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; @@ -34,12 +34,19 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.text.ParseException; +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); private boolean debugging = false; private String basePath = "{{basePath}}"; + private Map authentications; + private DateFormat dateFormat; public ApiClient() { @@ -52,6 +59,14 @@ public class ApiClient { // Set default User-Agent. setUserAgent("Java-Swagger"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); } public String getBasePath() { @@ -63,6 +78,75 @@ public class ApiClient { return this; } + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + /** * Set the User-Agent header's value (by adding to the default header map). */ @@ -252,10 +336,14 @@ public class ApiClient { * @param body The request body object * @param headerParams The header parameters * @param formParams The form parameters - * @param contentType The request Content-Type + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply * @return The response body in type of string */ - public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType) throws ApiException { + public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + Client client = getClient(); StringBuilder b = new StringBuilder(); @@ -364,6 +452,19 @@ public class ApiClient { } } + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + private void updateParamsForAuth(String[] authNames, Map queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + /** * Encode the given form parameters as request body. */ diff --git a/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache index 9d7523d1fb3..e936b423a91 100644 --- a/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/Configuration.mustache @@ -9,7 +9,7 @@ public class Configuration { */ public static ApiClient getDefaultApiClient() { return defaultApiClient; - } + } /** * Set the default API client, which would be used when creating API diff --git a/modules/swagger-codegen/src/main/resources/Java/api.mustache b/modules/swagger-codegen/src/main/resources/Java/api.mustache index fc2ce748f9b..63357afd896 100644 --- a/modules/swagger-codegen/src/main/resources/Java/api.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/api.mustache @@ -108,7 +108,8 @@ public class {{classname}} { } try { - String response = apiClient.invokeAPI(path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String response = apiClient.invokeAPI(path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return {{#returnType}}({{{returnType}}}) apiClient.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}}; } diff --git a/modules/swagger-codegen/src/main/resources/Java/auth/ApiKeyAuth.mustache b/modules/swagger-codegen/src/main/resources/Java/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..65720b958cb --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/auth/ApiKeyAuth.mustache @@ -0,0 +1,55 @@ +package {{invokerPackage}}.auth; + +import java.util.Map; + +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(Map queryParams, Map headerParams) { + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location == "query") { + queryParams.put(paramName, value); + } else if (location == "header") { + headerParams.put(paramName, value); + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/Java/auth/Authentication.mustache b/modules/swagger-codegen/src/main/resources/Java/auth/Authentication.mustache new file mode 100644 index 00000000000..1b2e2bc2fbe --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/auth/Authentication.mustache @@ -0,0 +1,8 @@ +package {{invokerPackage}}.auth; + +import java.util.Map; + +public interface Authentication { + /** Apply authentication settings to header and query params. */ + void applyToParams(Map queryParams, Map headerParams); +} diff --git a/modules/swagger-codegen/src/main/resources/Java/auth/HttpBasicAuth.mustache b/modules/swagger-codegen/src/main/resources/Java/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..22a64b1a24e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/auth/HttpBasicAuth.mustache @@ -0,0 +1,37 @@ +package {{invokerPackage}}.auth; + +import java.util.Map; + +import java.io.UnsupportedEncodingException; +import javax.xml.bind.DatatypeConverter; + +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(Map queryParams, Map headerParams) { + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + try { + headerParams.put("Authorization", "Basic " + DatatypeConverter.printBase64Binary(str.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/Java/auth/OAuth.mustache b/modules/swagger-codegen/src/main/resources/Java/auth/OAuth.mustache new file mode 100644 index 00000000000..ef84b8cc05e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/auth/OAuth.mustache @@ -0,0 +1,10 @@ +package {{invokerPackage}}.auth; + +import java.util.Map; + +public class OAuth implements Authentication { + @Override + public void applyToParams(Map queryParams, Map headerParams) { + // TODO: support oauth + } +} diff --git a/modules/swagger-codegen/src/main/resources/android-java/build.mustache b/modules/swagger-codegen/src/main/resources/android-java/build.mustache index 62a56bf066e..66fcef2a371 100644 --- a/modules/swagger-codegen/src/main/resources/android-java/build.mustache +++ b/modules/swagger-codegen/src/main/resources/android-java/build.mustache @@ -60,10 +60,10 @@ dependencies { compile "com.google.code.gson:gson:$gson_version" compile "org.apache.httpcomponents:httpcore:$httpclient_version" compile "org.apache.httpcomponents:httpclient:$httpclient_version" - compile ("org.apache.httpcomponents:httpcore:$httpcore_version") { + compile ("org.apache.httpcomponents:httpcore:$httpclient_version") { exclude(group: 'org.apache.httpcomponents', module: 'httpclient') } - compile ("org.apache.httpcomponents:httpmime:$httpmime_version") { + compile ("org.apache.httpcomponents:httpmime:$httpclient_version") { exclude(group: 'org.apache.httpcomponents', module: 'httpclient') } testCompile "junit:junit:$junit_version" diff --git a/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache b/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache index 3a6ff4111d1..ae8d18d3731 100644 --- a/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache +++ b/modules/swagger-codegen/src/main/resources/android-java/jsonUtil.mustache @@ -5,7 +5,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.List; -import io.swagger.client.model.*; +import {{modelPackage}}.*; public class JsonUtil { public static GsonBuilder gsonBuilder; diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index c5b72977cf5..ad57cffdf34 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Net; using System.Text; +using System.Threading.Tasks; using Newtonsoft.Json; using RestSharp; @@ -36,7 +37,16 @@ namespace {{invokerPackage}} { private Dictionary defaultHeaderMap = new Dictionary(); - public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + public Object CallApi(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, + Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { + var response = Task.Run(async () => { + var resp = await CallApiAsync(Path, Method, QueryParams, PostBody, HeaderParams, FormParams, FileParams, AuthSettings); + return resp; + }); + return response.Result; + } + + public async Task CallApiAsync(String Path, RestSharp.Method Method, Dictionary QueryParams, String PostBody, Dictionary HeaderParams, Dictionary FormParams, Dictionary FileParams, String[] AuthSettings) { var request = new RestRequest(Path, Method); @@ -67,7 +77,7 @@ namespace {{invokerPackage}} { request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter } - return (Object)restClient.Execute(request); + return (Object) await restClient.ExecuteTaskAsync(request); } diff --git a/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache similarity index 68% rename from modules/swagger-codegen/src/main/resources/csharp/apiException.mustache rename to modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache index fd68a46a976..38a340be249 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/apiException.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache @@ -11,6 +11,12 @@ namespace {{invokerPackage}} { /// The error code (HTTP status code). public int ErrorCode { get; set; } + /// + /// Gets or sets the error content (body json object) + /// + /// The error content (Http response body). + public dynamic ErrorContent { get; private set; } + /// /// Initializes a new instance of the class. /// @@ -26,6 +32,11 @@ namespace {{invokerPackage}} { this.ErrorCode = errorCode; } + public ApiException(int errorCode, string message, dynamic errorContent = null) : base(message) { + this.ErrorCode = errorCode; + this.ErrorContent = errorContent; + } + } } diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index 8e4a468add3..117446441fa 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using RestSharp; using {{invokerPackage}}; using {{modelPackage}}; @@ -8,10 +9,30 @@ using {{modelPackage}}; namespace {{package}} { {{#operations}} + + public interface I{{classname}} { + {{#operation}} + /// + /// {{summary}} {{notes}} + /// + {{#allParams}}/// {{description}}{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + /// + /// {{summary}} {{notes}} + /// + {{#allParams}}/// {{description}}{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/operation}} + } + /// /// Represents a collection of functions to interact with the API endpoints /// - public class {{classname}} { + public class {{classname}} : I{{classname}} { + /// /// Initializes a new instance of the class. /// @@ -61,8 +82,7 @@ namespace {{package}} { /// /// {{summary}} {{notes}} /// -{{#allParams}} /// {{description}} -{{/allParams}} + {{#allParams}}/// {{description}}{{/allParams}} /// {{#returnType}}{{{returnType}}}{{/returnType}} public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { @@ -98,12 +118,56 @@ namespace {{package}} { IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings); if (((int)response.StatusCode) >= 400) { - throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content); + throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content); } {{#returnType}}return ({{{returnType}}}) apiClient.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} return;{{/returnType}} } + + /// + /// {{summary}} {{notes}} + /// + {{#allParams}}/// {{description}}{{/allParams}} + /// {{#returnType}}{{{returnType}}}{{/returnType}} + public async {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}"); + {{/required}}{{/allParams}} + + var path = "{{path}}"; + path = path.Replace("{format}", "json"); + {{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", apiClient.ParameterToString({{{paramName}}})); + {{/pathParams}} + + var queryParams = new Dictionary(); + var headerParams = new Dictionary(); + var formParams = new Dictionary(); + var fileParams = new Dictionary(); + String postBody = null; + + {{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // query parameter + {{/queryParams}} + {{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // header parameter + {{/headerParams}} + {{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}} + {{/formParams}} + {{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter + {{/bodyParam}} + + // authentication setting, if any + String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + // make the HTTP request + IRestResponse response = (IRestResponse) await apiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings); + if (((int)response.StatusCode) >= 400) { + throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content); + } + {{#returnType}}return ({{{returnType}}}) ApiInvoker.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}} + return;{{/returnType}} + } {{/operation}} - } + } {{/operations}} } diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h index cd6f52db5c6..250811c4016 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.h @@ -3,7 +3,7 @@ /** * A key for `NSError` user info dictionaries. - * + * * The corresponding value is the parsed response body for an HTTP error. */ extern NSString *const SWGResponseObjectErrorKey; @@ -20,56 +20,197 @@ extern NSString *const SWGResponseObjectErrorKey; @property(nonatomic, assign) BOOL logHTTP; @property(nonatomic, readonly) NSOperationQueue* queue; +/** + * Get the Api Client instance from pool + * + * @param baseUrl The base url of api client. + * + * @return The SWGApiClient instance. + */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; +/** + * Get the operations queue + * + * @return The `shardQueue` static variable. + */ +(NSOperationQueue*) sharedQueue; +/** + * Turn on logging + * + * @param state logging state, must be `YES` or `NO` + */ +(void)setLoggingEnabled:(bool) state; +/** + * Clear Cache + */ +(void)clearCache; +/** + * Turn on cache + * + * @param enabled If the cached is enable, must be `YES` or `NO` + */ +(void)setCacheEnabled:(BOOL) enabled; +/** + * Get the request queue size + * + * @return The size of `queuedRequests` static variable. + */ +(unsigned long)requestQueueSize; +/** + * Set the client unreachable + * + * @param state off line state, must be `YES` or `NO` + */ +(void) setOfflineState:(BOOL) state; +/** + * Get the client reachability + * + * @return The client reachability. + */ +(AFNetworkReachabilityStatus) getReachabilityStatus; +/** + * Get the next request id + * + * @return The next executed request id. + */ +(NSNumber*) nextRequestId; +/** + * Generate request id and add it to the queue + * + * @return The next executed request id. + */ +(NSNumber*) queueRequest; +/** + * Remove request id from the queue + * + * @param requestId The request which will be removed. + */ +(void) cancelRequest:(NSNumber*)requestId; +/** + * URL encode NSString + * + * @param unescaped The string which will be escaped. + * + * @return The escaped string. + */ +(NSString*) escape:(id)unescaped; +/** + * Customize the behavior when the reachability changed + * + * @param changeBlock The block will be executed when the reachability changed. + */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; +/** + * Set the client reachability strategy + * + * @param host The host of SWGApiClient. + */ +(void) configureCacheReachibilityForHost:(NSString*)host; +/** + * Detect Accept header from accepts NSArray + * + * @param accepts NSArray of header + * + * @return The Accept header + */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; + +/** + * Detect Content-Type header from contentTypes NSArray + * + * @param contentTypes NSArray of header + * + * @return The Content-Type header + */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; +/** + * Set header for request + * + * @param value The header value + * @param forKey The header key + */ -(void)setHeaderValue:(NSString*) value - forKey:(NSString*) forKey; + forKey:(NSString*) forKey; +/** + * Update header parameters and query parameters for authentication + * + * @param headers The header parameter will be udpated, passed by pointer to pointer. + * @param querys The query parameters will be updated, passed by pointer to pointer. + * @param authSettings The authentication names NSArray. + */ +- (void) updateHeaderParams:(NSDictionary **)headers + queryParams:(NSDictionary **)querys + WithAuthSettings:(NSArray *)authSettings; + +/** + * Perform request + * + * Request with non-empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. + */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; +/** + * Perform request + * + * Request with empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. + */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m index b38b02e0e03..5e2985bbe79 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m +++ b/modules/swagger-codegen/src/main/resources/objc/SWGApiClient.m @@ -1,6 +1,7 @@ #import "SWGApiClient.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" +#import "SWGConfiguration.h" @implementation SWGApiClient @@ -15,10 +16,22 @@ static NSOperationQueue* sharedQueue; static void (^reachabilityChangeBlock)(int); static bool loggingEnabled = true; +#pragma mark - Log Methods + +(void)setLoggingEnabled:(bool) state { loggingEnabled = state; } +- (void)logRequest:(NSURLRequest*)request { + NSLog(@"request: %@", [self descriptionForRequest:request]); +} + +- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { + NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); +} + +#pragma mark - + +(void)clearCache { [[NSURLCache sharedURLCache] removeAllCachedResponses]; } @@ -305,19 +318,47 @@ static bool loggingEnabled = true; return [[request URL] absoluteString]; } -- (void)logRequest:(NSURLRequest*)request { - NSLog(@"request: %@", [self descriptionForRequest:request]); + +/** + * Update header and query params based on authentication settings + */ +- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers + queryParams:(NSDictionary *__autoreleasing *)querys + WithAuthSettings:(NSArray *)authSettings { + + if (!authSettings || [authSettings count] == 0) { + return; + } + + NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers]; + NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys]; + + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + for (NSString *auth in authSettings) { + NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; + + if (authSetting) { + if ([authSetting[@"in"] isEqualToString:@"header"]) { + [headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + else if ([authSetting[@"in"] isEqualToString:@"query"]) { + [querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + } + } + + *headers = [NSDictionary dictionaryWithDictionary:headersWithAuth]; + *querys = [NSDictionary dictionaryWithDictionary:querysWithAuth]; } -- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { - NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); -} +#pragma mark - Perform Request Methods -(NSNumber*) dictionary: (NSString*) path method: (NSString*) method queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSDictionary*, NSError *))completionBlock { @@ -342,6 +383,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ @@ -476,6 +520,7 @@ static bool loggingEnabled = true; queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSString*, NSError *))completionBlock { @@ -500,6 +545,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache new file mode 100644 index 00000000000..1e5e7135574 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-body.mustache @@ -0,0 +1,99 @@ +#import "SWGConfiguration.h" + +@interface SWGConfiguration () + +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey; +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix; + +@end + +@implementation SWGConfiguration + +#pragma mark - Singletion Methods + ++ (instancetype) sharedConfig { + static SWGConfiguration *shardConfig = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shardConfig = [[self alloc] init]; + }); + return shardConfig; +} + +#pragma mark - Initialize Methods + +- (instancetype) init { + self = [super init]; + if (self) { + self.username = @""; + self.password = @""; + self.mutableApiKey = [NSMutableDictionary dictionary]; + self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Instance Methods + +- (NSString *) getApiKeyWithPrefix:(NSString *)key { + if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]]; + } + else if ([self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]]; + } + else { + return @""; + } +} + +- (NSString *) getBasicAuthToken { + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", self.username, self.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + return basicAuthCredentials; +} + +#pragma mark - Setter Methods + +- (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { + [self.mutableApiKey setValue:value forKey:field]; +} + +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field { + [self.mutableApiKeyPrefix setValue:value forKey:field]; +} + +#pragma mark - Getter Methods + +- (NSDictionary *) apiKey { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKey]; +} + +- (NSDictionary *) apiKeyPrefix { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKeyPrefix]; +} + +#pragma mark - + +- (NSDictionary *) authSettings { + return @{ {{#authMethods}}{{#isApiKey}} + @"{{name}}": @{ + @"type": @"api_key", + @"in": {{#isKeyInHeader}}@"header"{{/isKeyInHeader}}{{#isKeyInQuery}}@"query"{{/isKeyInQuery}}, + @"key": @"{{keyParamName}}", + @"value": [self getApiKeyWithPrefix:@"{{keyParamName}}"] + }, + {{/isApiKey}}{{#isBasic}} + @"{{name}}": @{ + @"type": @"basic", + @"in": @"header", + @"key": @"Authorization", + @"value": [self getBasicAuthToken] + }, + {{/isBasic}}{{/authMethods}} + }; +} + +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache new file mode 100644 index 00000000000..33023ca3c6f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/objc/SWGConfiguration-header.mustache @@ -0,0 +1,56 @@ +#import + +@interface SWGConfiguration : NSObject + + +/** + * Api key values for Api Key type Authentication + * + * To add or remove api key, use `setValue:forApiKeyField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKey; + +/** + * Api key prefix values to be prepend to the respective api key + * + * To add or remove prefix, use `setValue:forApiKeyPrefixField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix; + +/** + * Usename and Password for Basic type Authentication + */ +@property (nonatomic) NSString *username; +@property (nonatomic) NSString *password; + +/** + * Get configuration singleton instance + */ ++ (instancetype) sharedConfig; + +/** + * Sets field in `apiKey` + */ +- (void) setValue:(NSString *)value forApiKeyField:(NSString*)field; + +/** + * Sets field in `apiKeyPrefix` + */ +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field; + +/** + * Get API key (with prefix if set) + */ +- (NSString *) getApiKeyWithPrefix:(NSString *) key; + +/** + * Get Basic Auth token + */ +- (NSString *) getBasicAuthToken; + +/** + * Get Authentication Setings + */ +- (NSDictionary *) authSettings; + +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m b/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m index 9ce319940dd..83303045185 100644 --- a/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m +++ b/modules/swagger-codegen/src/main/resources/objc/SWGQueryParamCollection.m @@ -13,4 +13,4 @@ return self; } -@end \ No newline at end of file +@end diff --git a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache index abe4376d1ac..40d75bd806b 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache @@ -39,6 +39,8 @@ static NSString * basePath = @"{{basePath}}"; return self; } +#pragma mark - + +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static {{classname}}* singletonAPI = nil; @@ -129,6 +131,9 @@ static NSString * basePath = @"{{basePath}}"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]]; + // Authentication setting + NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}]; + id bodyDictionary = nil; {{#bodyParam}} id __body = {{paramName}}; diff --git a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache index 4d571f756ce..65f4c39e0b3 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache @@ -10,6 +10,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache index 5aabef86841..acaeaf2ddf5 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiBodyResponseWithContainer.mustache @@ -4,6 +4,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache index 81cf1343e53..da8ea063bfb 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiNonPrimitiveResponse.mustache @@ -5,6 +5,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache index 3d6b105f227..d44d356526d 100644 --- a/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/apiPrimitiveResponse.mustache @@ -4,6 +4,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache index ab4062a6dbe..7bbbc14c066 100644 --- a/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/voidResponse.mustache @@ -3,6 +3,7 @@ queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/modules/swagger-codegen/src/main/resources/perlApiClient.mustache b/modules/swagger-codegen/src/main/resources/perl/ApiClient.mustache similarity index 100% rename from modules/swagger-codegen/src/main/resources/perlApiClient.mustache rename to modules/swagger-codegen/src/main/resources/perl/ApiClient.mustache diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache index df7f508de69..476d3b625c2 100644 --- a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/APIClient.mustache @@ -182,13 +182,10 @@ class ApiClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - if ($headerParams != null) { - # add default header - $headerParams = array_merge((array)self::$default_header, $headerParams); + $headerParams = array_merge((array)self::$default_header, (array)$headerParams); - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - } + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; } // form data @@ -292,7 +289,9 @@ class ApiClient { } else if (is_object($data)) { $values = array(); foreach (array_keys($data::$swaggerTypes) as $property) { - $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + if ($data->$property !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + } } $sanitized = $values; } else { @@ -377,17 +376,16 @@ class ApiClient { { if (null === $data) { $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] $inner = substr($class, 4, -1); - $values = array(); + $deserialized = array(); if(strrpos($inner, ",") !== false) { $subClass_array = explode(',', $inner, 2); $subClass = $subClass_array[1]; foreach ($data as $key => $value) { - $values[] = array($key => self::deserialize($value, $subClass)); + $deserialized[$key] = self::deserialize($value, $subClass); } } - $deserialized = $values; } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { $subClass = substr($class, 6, -1); $values = array(); @@ -397,7 +395,7 @@ class ApiClient { $deserialized = $values; } elseif ($class == 'DateTime') { $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { settype($data, $class); $deserialized = $data; } else { diff --git a/modules/swagger-codegen/src/main/resources/python/__init__package.mustache b/modules/swagger-codegen/src/main/resources/python/__init__package.mustache index 7b48136d3a9..921f4dac0eb 100644 --- a/modules/swagger-codegen/src/main/resources/python/__init__package.mustache +++ b/modules/swagger-codegen/src/main/resources/python/__init__package.mustache @@ -7,4 +7,4 @@ from __future__ import absolute_import {{#apiInfo}}{{#apis}}from .apis.{{classVarName}} import {{classname}} {{/apis}}{{/apiInfo}} # import ApiClient -from .swagger import ApiClient +from .api_client import ApiClient diff --git a/modules/swagger-codegen/src/main/resources/python/api.mustache b/modules/swagger-codegen/src/main/resources/python/api.mustache index d5e24398f0e..7153ee2b040 100644 --- a/modules/swagger-codegen/src/main/resources/python/api.mustache +++ b/modules/swagger-codegen/src/main/resources/python/api.mustache @@ -27,9 +27,8 @@ import os # python 2 and python 3 compatibility library from six import iteritems -from ..util import remove_none - -from .. import config +from .. import configuration +from ..api_client import ApiClient {{#operations}} class {{classname}}(object): @@ -38,7 +37,10 @@ class {{classname}}(object): if api_client: self.api_client = api_client else: - self.api_client = config.api_client + if not configuration.api_client: + configuration.api_client = ApiClient('{{basePath}}') + self.api_client = configuration.api_client + {{#operation}} def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs): """ @@ -66,13 +68,32 @@ class {{classname}}(object): resource_path = '{{path}}'.replace('{format}', 'json') method = '{{httpMethod}}' - path_params = remove_none(dict({{#pathParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/pathParams}})) - query_params = remove_none(dict({{#queryParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/queryParams}})) - header_params = remove_none(dict({{#headerParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/headerParams}})) - form_params = remove_none(dict({{#formParams}}{{^isFile}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/isFile}}{{/formParams}})) - files = remove_none(dict({{#formParams}}{{#isFile}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/isFile}}{{/formParams}})) - body_params = {{#bodyParam}}params.get('{{paramName}}'){{/bodyParam}}{{^bodyParam}}None{{/bodyParam}} - + path_params = {} + {{#pathParams}} + if '{{paramName}}' in params: + path_params['{{baseName}}'] = params['{{paramName}}'] + {{/pathParams}} + query_params = {} + {{#queryParams}} + if '{{paramName}}' in params: + query_params['{{baseName}}'] = params['{{paramName}}'] + {{/queryParams}} + header_params = {} + {{#headerParams}} + if '{{paramName}}' in params: + header_params['{{baseName}}'] = params['{{paramName}}'] + {{/headerParams}} + form_params = {} + files = {} + {{#formParams}} + if '{{paramName}}' in params: + {{#notFile}}form_params['{{baseName}}'] = params['{{paramName}}']{{/notFile}}{{#isFile}}files['{{baseName}}'] = params['{{paramName}}']{{/isFile}} + {{/formParams}} + body_params = None + {{#bodyParam}} + if '{{paramName}}' in params: + body_params = params['{{paramName}}'] + {{/bodyParam}} # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept([{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) if not header_params['Accept']: @@ -81,9 +102,12 @@ class {{classname}}(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) + # Authentication setting + auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}) + response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings) {{#returnType}} return response {{/returnType}}{{/operation}} diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py b/modules/swagger-codegen/src/main/resources/python/api_client.mustache similarity index 86% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py rename to modules/swagger-codegen/src/main/resources/python/api_client.mustache index 21430c469c8..b8cc4cc2a84 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/swagger.py +++ b/modules/swagger-codegen/src/main/resources/python/api_client.mustache @@ -28,6 +28,7 @@ except ImportError: # for python2 from urllib import quote +from . import configuration class ApiClient(object): """ @@ -37,7 +38,7 @@ class ApiClient(object): :param header_name: a header to pass when making calls to the API :param header_value: a header value to pass when making calls to the API """ - def __init__(self, host=None, header_name=None, header_value=None): + def __init__(self, host=configuration.host, header_name=None, header_value=None): self.default_headers = {} if header_name is not None: self.default_headers[header_name] = header_value @@ -58,15 +59,15 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None): + body=None, post_params=None, files=None, response=None, auth_settings=None): # headers parameters - headers = self.default_headers.copy() - headers.update(header_params) + header_params = header_params or {} + header_params.update(self.default_headers) if self.cookie: - headers['Cookie'] = self.cookie - if headers: - headers = self.sanitize_for_serialization(headers) + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) # path parameters if path_params: @@ -85,6 +86,9 @@ class ApiClient(object): post_params = self.prepare_post_parameters(post_params, files) post_params = self.sanitize_for_serialization(post_params) + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + # body if body: body = self.sanitize_for_serialization(body) @@ -93,7 +97,7 @@ class ApiClient(object): url = self.host + resource_path # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=headers, + response_data = self.request(method, url, query_params=query_params, headers=header_params, post_params=post_params, body=body) # deserialize response data @@ -244,11 +248,12 @@ class ApiClient(object): if files: for k, v in iteritems(files): - with open(v, 'rb') as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' - params[k] = tuple([filename, filedata, mimetype]) + if v: + with open(v, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + params[k] = tuple([filename, filedata, mimetype]) return params @@ -279,3 +284,20 @@ class ApiClient(object): return 'application/json' else: return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """ + Update header and query params based on authentication setting + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = configuration.auth_settings().get(auth) + if auth_setting: + if auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys[auth_setting['key']] = auth_setting['value'] + else: + raise ValueError('Authentication token must be in `query` or `header`') diff --git a/modules/swagger-codegen/src/main/resources/python/config.mustache b/modules/swagger-codegen/src/main/resources/python/config.mustache deleted file mode 100644 index e8c36aee77b..00000000000 --- a/modules/swagger-codegen/src/main/resources/python/config.mustache +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import absolute_import - -from .swagger import ApiClient - -# Configuration variables - -api_client = ApiClient("{{basePath}}") - diff --git a/modules/swagger-codegen/src/main/resources/python/configuration.mustache b/modules/swagger-codegen/src/main/resources/python/configuration.mustache new file mode 100644 index 00000000000..d3a7093a02a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/python/configuration.mustache @@ -0,0 +1,51 @@ +from __future__ import absolute_import +import base64 +import urllib3 + +def get_api_key_with_prefix(key): + global api_key + global api_key_prefix + + if api_key.get(key) and api_key_prefix.get(key): + return api_key_prefix[key] + ' ' + api_key[key] + elif api_key.get(key): + return api_key[key] + +def get_basic_auth_token(): + global username + global password + + return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization') + +def auth_settings(): + return { {{#authMethods}}{{#isApiKey}} + '{{name}}': { + 'type': 'api_key', + 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': get_api_key_with_prefix('{{keyParamName}}') + }, + {{/isApiKey}}{{#isBasic}} + '{{name}}': { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': get_basic_auth_token() + }, + {{/isBasic}}{{/authMethods}} + } + +# Default Base url +host = "{{basePath}}" + +# Default api client +api_client = None + +# Authentication settings + +api_key = {} +api_key_prefix = {} +username = '' +password = '' + + diff --git a/modules/swagger-codegen/src/main/resources/python/rest.mustache b/modules/swagger-codegen/src/main/resources/python/rest.mustache index da99abc2493..508f3d6693a 100644 --- a/modules/swagger-codegen/src/main/resources/python/rest.mustache +++ b/modules/swagger-codegen/src/main/resources/python/rest.mustache @@ -1,4 +1,10 @@ # coding: utf-8 + +""" +Credit: this file (rest.py) is modified based on rest.py in Dropbox Python SDK: +https://www.dropbox.com/developers/core/sdks/python +""" + import sys import io import json @@ -120,7 +126,7 @@ class RESTClientObject(object): r = RESTResponse(r) if r.status not in range(200, 206): - raise ErrorResponse(r) + raise ApiException(r) return self.process_response(r) @@ -157,7 +163,7 @@ class RESTClientObject(object): return self.request("PATCH", url, headers=headers, post_params=post_params, body=body) -class ErrorResponse(Exception): +class ApiException(Exception): """ Non-2xx HTTP response """ @@ -184,7 +190,10 @@ class ErrorResponse(Exception): """ Custom error response messages """ - return "({0})\nReason: {1}\nHeader: {2}\nBody: {3}\n".\ + return "({0})\n"\ + "Reason: {1}\n"\ + "HTTP response headers: {2}\n"\ + "HTTP response body: {3}\n".\ format(self.status, self.reason, self.headers, self.body) class RESTClient(object): diff --git a/modules/swagger-codegen/src/main/resources/python/util.mustache b/modules/swagger-codegen/src/main/resources/python/util.mustache deleted file mode 100644 index 1137a5d2d23..00000000000 --- a/modules/swagger-codegen/src/main/resources/python/util.mustache +++ /dev/null @@ -1,17 +0,0 @@ -from six import iteritems - -def remove_none(obj): - if isinstance(obj, (list, tuple, set)): - return type(obj)(remove_none(x) for x in obj if x is not None) - elif isinstance(obj, dict): - return type(obj)((remove_none(k), remove_none(v)) - for k, v in iteritems(obj) if k is not None and v is not None) - else: - return obj - - -def inspect_vars(obj): - if not hasattr(obj, '__dict__'): - return obj - else: - return {k: inspect_vars(getattr(obj, k)) for k in dir(obj)} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index 940c3851c15..0adcbe7031d 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -16,8 +16,8 @@ import com.sun.jersey.multipart.FormDataMultiPart; import javax.ws.rs.core.Response.Status.Family; import javax.ws.rs.core.MediaType; -import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; @@ -34,12 +34,19 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.text.ParseException; +import io.swagger.client.auth.Authentication; +import io.swagger.client.auth.HttpBasicAuth; +import io.swagger.client.auth.ApiKeyAuth; +import io.swagger.client.auth.OAuth; + public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); private boolean debugging = false; private String basePath = "http://petstore.swagger.io/v2"; + private Map authentications; + private DateFormat dateFormat; public ApiClient() { @@ -52,6 +59,13 @@ public class ApiClient { // Set default User-Agent. setUserAgent("Java-Swagger"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap(); + authentications.put("api_key", new ApiKeyAuth("header", "api_key")); + authentications.put("petstore_auth", new OAuth()); + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); } public String getBasePath() { @@ -63,6 +77,75 @@ public class ApiClient { return this; } + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + /** * Set the User-Agent header's value (by adding to the default header map). */ @@ -252,10 +335,14 @@ public class ApiClient { * @param body The request body object * @param headerParams The header parameters * @param formParams The form parameters - * @param contentType The request Content-Type + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply * @return The response body in type of string */ - public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType) throws ApiException { + public String invokeAPI(String path, String method, Map queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + Client client = getClient(); StringBuilder b = new StringBuilder(); @@ -364,6 +451,19 @@ public class ApiClient { } } + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + private void updateParamsForAuth(String[] authNames, Map queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + /** * Encode the given form parameters as request body. */ diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java index f7c360d6122..04899a110f6 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/Configuration.java @@ -9,7 +9,7 @@ public class Configuration { */ public static ApiClient getDefaultApiClient() { return defaultApiClient; - } + } /** * Set the default API client, which would be used when creating API diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java index 58123f2298d..bc793fd41ee 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java @@ -84,7 +84,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -140,7 +141,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -198,7 +200,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (List) apiClient.deserialize(response, "array", Pet.class); } @@ -256,7 +259,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (List) apiClient.deserialize(response, "array", Pet.class); } @@ -318,7 +322,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "api_key", "petstore_auth" }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (Pet) apiClient.deserialize(response, "", Pet.class); } @@ -396,7 +401,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -461,7 +467,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -539,7 +546,8 @@ public class PetApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "petstore_auth" }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java index 000fef4b442..727e791c603 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java @@ -83,7 +83,8 @@ public class StoreApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { "api_key" }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (Map) apiClient.deserialize(response, "map", Map.class); } @@ -139,7 +140,8 @@ public class StoreApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (Order) apiClient.deserialize(response, "", Order.class); } @@ -201,7 +203,8 @@ public class StoreApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (Order) apiClient.deserialize(response, "", Order.class); } @@ -263,7 +266,8 @@ public class StoreApi { } try { - String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java index 870382edcbc..9e55bbed590 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java @@ -84,7 +84,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -140,7 +141,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -196,7 +198,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -257,7 +260,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (String) apiClient.deserialize(response, "", String.class); } @@ -312,7 +316,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -374,7 +379,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (User) apiClient.deserialize(response, "", User.class); } @@ -437,7 +443,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "PUT", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } @@ -499,7 +506,8 @@ public class UserApi { } try { - String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType); + String[] authNames = new String[] { }; + String response = apiClient.invokeAPI(path, "DELETE", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return ; } diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/auth/ApiKeyAuth.java b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/ApiKeyAuth.java new file mode 100644 index 00000000000..ce55babb51d --- /dev/null +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/ApiKeyAuth.java @@ -0,0 +1,55 @@ +package io.swagger.client.auth; + +import java.util.Map; + +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(Map queryParams, Map headerParams) { + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location == "query") { + queryParams.put(paramName, value); + } else if (location == "header") { + headerParams.put(paramName, value); + } + } +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/auth/Authentication.java b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/Authentication.java new file mode 100644 index 00000000000..3f372404c8d --- /dev/null +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/Authentication.java @@ -0,0 +1,8 @@ +package io.swagger.client.auth; + +import java.util.Map; + +public interface Authentication { + /** Apply authentication settings to header and query params. */ + void applyToParams(Map queryParams, Map headerParams); +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/auth/HttpBasicAuth.java b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/HttpBasicAuth.java new file mode 100644 index 00000000000..24bff8c2266 --- /dev/null +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/HttpBasicAuth.java @@ -0,0 +1,37 @@ +package io.swagger.client.auth; + +import java.util.Map; + +import java.io.UnsupportedEncodingException; +import javax.xml.bind.DatatypeConverter; + +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(Map queryParams, Map headerParams) { + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + try { + headerParams.put("Authorization", "Basic " + DatatypeConverter.printBase64Binary(str.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/auth/OAuth.java b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/OAuth.java new file mode 100644 index 00000000000..d834f4580c2 --- /dev/null +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/auth/OAuth.java @@ -0,0 +1,10 @@ +package io.swagger.client.auth; + +import java.util.Map; + +public class OAuth implements Authentication { + @Override + public void applyToParams(Map queryParams, Map headerParams) { + // TODO: support oauth + } +} diff --git a/samples/client/petstore/java/src/test/java/io/swagger/client/ApiClientTest.java b/samples/client/petstore/java/src/test/java/io/swagger/client/ApiClientTest.java index 891b8e17d13..d0ec118083a 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/client/ApiClientTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/client/ApiClientTest.java @@ -1,5 +1,9 @@ package io.swagger.client; +import io.swagger.client.auth.*; + +import java.util.Map; + import static org.junit.Assert.*; import org.junit.*; @@ -10,6 +14,7 @@ public class ApiClientTest { public void setup() { apiClient = new ApiClient(); } + @Test public void testSelectHeaderAccept() { String[] accepts = { "APPLICATION/JSON", "APPLICATION/XML" }; @@ -45,4 +50,62 @@ public class ApiClientTest { contentTypes = new String[] { }; assertEquals("application/json", apiClient.selectHeaderContentType(contentTypes)); } + + @Test + public void testGetAuthentications() { + Map auths = apiClient.getAuthentications(); + + Authentication auth = auths.get("api_key"); + assertNotNull(auth); + assertTrue(auth instanceof ApiKeyAuth); + ApiKeyAuth apiKeyAuth = (ApiKeyAuth) auth; + assertEquals("header", apiKeyAuth.getLocation()); + assertEquals("api_key", apiKeyAuth.getParamName()); + + auth = auths.get("petstore_auth"); + assertTrue(auth instanceof OAuth); + assertSame(auth, apiClient.getAuthentication("petstore_auth")); + + assertNull(auths.get("unknown")); + + try { + auths.put("my_auth", new HttpBasicAuth()); + fail("the authentications returned should not be modifiable"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testSetUsername() { + try { + apiClient.setUsername("my-username"); + fail("there should be no HTTP basic authentications"); + } catch (RuntimeException e) { + } + } + + @Test + public void testSetPassword() { + try { + apiClient.setPassword("my-password"); + fail("there should be no HTTP basic authentications"); + } catch (RuntimeException e) { + } + } + + @Test + public void testSetApiKeyAndPrefix() { + ApiKeyAuth auth = (ApiKeyAuth) apiClient.getAuthentications().get("api_key"); + auth.setApiKey(null); + auth.setApiKeyPrefix(null); + + apiClient.setApiKey("my-api-key"); + apiClient.setApiKeyPrefix("Token"); + assertEquals("my-api-key", auth.getApiKey()); + assertEquals("Token", auth.getApiKeyPrefix()); + + // reset values + auth.setApiKey(null); + auth.setApiKeyPrefix(null); + } } diff --git a/samples/client/petstore/java/src/test/java/io/swagger/client/auth/ApiKeyAuthTest.java b/samples/client/petstore/java/src/test/java/io/swagger/client/auth/ApiKeyAuthTest.java new file mode 100644 index 00000000000..f90ee3d7b22 --- /dev/null +++ b/samples/client/petstore/java/src/test/java/io/swagger/client/auth/ApiKeyAuthTest.java @@ -0,0 +1,40 @@ +package io.swagger.client.auth; + +import java.util.Map; +import java.util.HashMap; + +import static org.junit.Assert.*; +import org.junit.*; + +public class ApiKeyAuthTest { + @Test + public void testApplyToParamsInQuery() { + Map queryParams = new HashMap(); + Map headerParams = new HashMap(); + + ApiKeyAuth auth = new ApiKeyAuth("query", "api_key"); + auth.setApiKey("my-api-key"); + auth.applyToParams(queryParams, headerParams); + + assertEquals(1, queryParams.size()); + assertEquals("my-api-key", queryParams.get("api_key")); + // no changes to header parameters + assertEquals(0, headerParams.size()); + } + + @Test + public void testApplyToParamsInHeaderWithPrefix() { + Map queryParams = new HashMap(); + Map headerParams = new HashMap(); + + ApiKeyAuth auth = new ApiKeyAuth("header", "X-API-TOKEN"); + auth.setApiKey("my-api-token"); + auth.setApiKeyPrefix("Token"); + auth.applyToParams(queryParams, headerParams); + + // no changes to query parameters + assertEquals(0, queryParams.size()); + assertEquals(1, headerParams.size()); + assertEquals("Token my-api-token", headerParams.get("X-API-TOKEN")); + } +} diff --git a/samples/client/petstore/java/src/test/java/io/swagger/client/auth/HttpBasicAuthTest.java b/samples/client/petstore/java/src/test/java/io/swagger/client/auth/HttpBasicAuthTest.java new file mode 100644 index 00000000000..87d6eca8b82 --- /dev/null +++ b/samples/client/petstore/java/src/test/java/io/swagger/client/auth/HttpBasicAuthTest.java @@ -0,0 +1,48 @@ +package io.swagger.client.auth; + +import java.util.Map; +import java.util.HashMap; + +import static org.junit.Assert.*; +import org.junit.*; + +public class HttpBasicAuthTest { + HttpBasicAuth auth = null; + + @Before + public void setup() { + auth = new HttpBasicAuth(); + } + + @Test + public void testApplyToParams() { + Map queryParams = new HashMap(); + Map headerParams = new HashMap(); + + auth.setUsername("my-username"); + auth.setPassword("my-password"); + auth.applyToParams(queryParams, headerParams); + + // no changes to query parameters + assertEquals(0, queryParams.size()); + assertEquals(1, headerParams.size()); + // the string below is base64-encoded result of "my-username:my-password" with the "Basic " prefix + String expected = "Basic bXktdXNlcm5hbWU6bXktcGFzc3dvcmQ="; + assertEquals(expected, headerParams.get("Authorization")); + + // null username should be treated as empty string + auth.setUsername(null); + auth.applyToParams(queryParams, headerParams); + // the string below is base64-encoded result of ":my-password" with the "Basic " prefix + expected = "Basic Om15LXBhc3N3b3Jk"; + assertEquals(expected, headerParams.get("Authorization")); + + // null password should be treated as empty string + auth.setUsername("my-username"); + auth.setPassword(null); + auth.applyToParams(queryParams, headerParams); + // the string below is base64-encoded result of "my-username:" with the "Basic " prefix + expected = "Basic bXktdXNlcm5hbWU6"; + assertEquals(expected, headerParams.get("Authorization")); + } +} diff --git a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java index 4ea5474eb59..854af7121da 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -5,6 +5,7 @@ import io.swagger.client.ApiClient; import io.swagger.client.Configuration; import io.swagger.client.api.*; import io.swagger.client.model.*; +import io.swagger.client.auth.*; import java.util.*; import java.io.*; @@ -18,6 +19,9 @@ public class PetApiTest { @Before public void setup() { api = new PetApi(); + // setup authentication + ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); + apiKeyAuth.setApiKey("special-key"); } @Test diff --git a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/StoreApiTest.java index 25a52009b9e..1499c4eaf86 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/StoreApiTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -1,8 +1,10 @@ package io.swagger.petstore.test; import io.swagger.client.ApiException; +import io.swagger.client.Configuration; import io.swagger.client.api.*; import io.swagger.client.model.*; +import io.swagger.client.auth.*; import java.util.*; import java.io.*; @@ -16,6 +18,9 @@ public class StoreApiTest { @Before public void setup() { api = new StoreApi(); + // setup authentication + ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); + apiKeyAuth.setApiKey("special-key"); } @Test @@ -65,4 +70,4 @@ public class StoreApiTest { return order; } -} \ No newline at end of file +} diff --git a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/UserApiTest.java b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/UserApiTest.java index 9d683faab7a..e3bccd0dcdb 100644 --- a/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/UserApiTest.java +++ b/samples/client/petstore/java/src/test/java/io/swagger/petstore/test/UserApiTest.java @@ -1,8 +1,10 @@ package io.swagger.petstore.test; import io.swagger.client.ApiException; +import io.swagger.client.Configuration; import io.swagger.client.api.*; import io.swagger.client.model.*; +import io.swagger.client.auth.*; import java.util.*; import java.io.*; @@ -16,6 +18,9 @@ public class UserApiTest { @Before public void setup() { api = new UserApi(); + // setup authentication + ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); + apiKeyAuth.setApiKey("special-key"); } @Test @@ -81,4 +86,4 @@ public class UserApiTest { return user; } -} \ No newline at end of file +} diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj index 723caec2cdb..5c1bfabf608 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ BA525648922D4C0E9F44D4F1 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DA4F1067C343C3962F1542 /* libPods.a */; }; + CF0560EB1B1855CF00C0D4EC /* SWGConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */; }; CF31D0991B105E4B00509935 /* SWGApiClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF31D0981B105E4B00509935 /* SWGApiClientTest.m */; }; CFD1B6701B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */; }; CFD1B6711B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */; }; @@ -56,6 +57,8 @@ /* Begin PBXFileReference section */ 73DA4F1067C343C3962F1542 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; A425648B5C0A4849C7668069 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "../Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + CF0560E91B1855CF00C0D4EC /* SWGConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWGConfiguration.h; sourceTree = ""; }; + CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWGConfiguration.m; sourceTree = ""; }; CF31D0981B105E4B00509935 /* SWGApiClientTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWGApiClientTest.m; sourceTree = ""; }; CFD1B66E1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JSONValueTransformer+ISO8601.h"; sourceTree = ""; }; CFD1B66F1B05EC7D00DCCD51 /* JSONValueTransformer+ISO8601.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JSONValueTransformer+ISO8601.m"; sourceTree = ""; }; @@ -234,6 +237,8 @@ EA8B8AA31AC6683700638FBB /* SWGQueryParamCollection.m */, EAEA85CC1811D3AE00F06E69 /* SWGApiClient.h */, EAEA85CD1811D3AE00F06E69 /* SWGApiClient.m */, + CF0560E91B1855CF00C0D4EC /* SWGConfiguration.h */, + CF0560EA1B1855CF00C0D4EC /* SWGConfiguration.m */, EAEA85CE1811D3AE00F06E69 /* SWGCategory.h */, EAEA85CF1811D3AE00F06E69 /* SWGCategory.m */, EAEA85D21811D3AE00F06E69 /* SWGFile.h */, @@ -395,6 +400,7 @@ buildActionMask = 2147483647; files = ( EAEA85E51811D3AE00F06E69 /* SWGCategory.m in Sources */, + CF0560EB1B1855CF00C0D4EC /* SWGConfiguration.m in Sources */, EAEA85ED1811D3AE00F06E69 /* SWGTag.m in Sources */, EA6699B31811D2FA00A70D03 /* ViewController.m in Sources */, EA6699AA1811D2FA00A70D03 /* AppDelegate.m in Sources */, diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme new file mode 100644 index 00000000000..1a2a738abea --- /dev/null +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/PetstoreClient.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000000..912710bdccc --- /dev/null +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient.xcodeproj/xcuserdata/geekerzp.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + PetstoreClient.xcscheme + + orderHint + 4 + + + SuppressBuildableAutocreation + + EA6699951811D2FA00A70D03 + + primary + + + EA6699B91811D2FB00A70D03 + + primary + + + + + diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m index 7c47bb1f271..d56bc037206 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClient/ViewController.m @@ -8,6 +8,7 @@ #import "ViewController.h" #import "SWGPetApi.h" +#import "SWGConfiguration.h" @interface ViewController () @@ -53,6 +54,14 @@ // } ]; */ + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + config.username = @"foo"; + config.password = @"bar"; + SWGPetApi *api = [[SWGPetApi alloc] init]; + [api addPetWithCompletionBlock:nil + completionHandler:^(NSError *error) { + + }]; } - (void)didReceiveMemoryWarning diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m index cfc2dc7804f..5b5f145cc12 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/PetApiTest.m @@ -37,6 +37,24 @@ } if(output){ XCTAssertNotNil([output _id], @"token was nil"); + + // test category of pet is correct + XCTAssertEqualObjects(output.category._id, pet.category._id); + XCTAssertEqualObjects(output.category.name, pet.category.name); + + // test tags of pet is correct + XCTAssertTrue([output.tags isKindOfClass:[NSArray class]]); + [pet.tags enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + SWGTag *foundTag = [[SWGTag alloc] init]; + for (SWGTag *tag in output.tags) { + if ([tag _id] == [obj _id]) { + foundTag = tag; + } + } + XCTAssertNotNil(foundTag); + XCTAssertEqualObjects([foundTag _id], [obj _id]); + XCTAssertEqualObjects([foundTag name], [obj name]); + }]; } [expectation fulfill]; }]; @@ -231,10 +249,20 @@ SWGPet * pet = [[SWGPet alloc] init]; pet._id = [[NSNumber alloc] initWithLong:[[NSDate date] timeIntervalSince1970]]; pet.name = @"monkey"; + SWGCategory * category = [[SWGCategory alloc] init]; + category._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; category.name = @"super-happy"; - pet.category = category; + + SWGTag *tag1 = [[SWGTag alloc] init]; + tag1._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; + tag1.name = @"test tag 1"; + SWGTag *tag2 = [[SWGTag alloc] init]; + tag2._id = [[NSNumber alloc] initWithInteger:arc4random_uniform(100000)]; + tag2.name = @"test tag 2"; + pet.tags = (NSArray *)[[NSArray alloc] initWithObjects:tag1, tag2, nil]; + pet.status = @"available"; NSArray * photos = [[NSArray alloc] initWithObjects:@"http://foo.bar.com/3", @"http://foo.bar.com/4", nil]; diff --git a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m index 0464bf569e9..61925b16960 100644 --- a/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m +++ b/samples/client/petstore/objc/PetstoreClient/PetstoreClientTests/SWGApiClientTest.m @@ -1,16 +1,19 @@ #import #import #import "SWGApiClient.h" +#import "SWGConfiguration.h" @interface SWGApiClientTest : XCTestCase +@property (nonatomic) SWGApiClient *apiClient; + @end @implementation SWGApiClientTest - (void)setUp { [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. + self.apiClient = [[SWGApiClient alloc] init]; } - (void)tearDown { @@ -56,4 +59,43 @@ XCTAssertEqualObjects([SWGApiClient selectHeaderContentType:contentTypes], @"application/json"); } +- (void)testConfiguration { + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + [config setValue:@"123456" forApiKeyField:@"api_key"]; + [config setValue:@"PREFIX" forApiKeyPrefixField:@"api_key"]; + config.username = @"test_username"; + config.password = @"test_password"; + + NSDictionary *headerParams = @{@"test1": @"value1"}; + NSDictionary *queryParams = @{@"test2": @"value2"}; + NSArray *authSettings = @[@"api_key", @"unknown"]; + + // test prefix + XCTAssertEqualObjects(@"PREFIX", config.apiKeyPrefix[@"api_key"]); + [self.apiClient updateHeaderParams:&headerParams + queryParams:&queryParams + WithAuthSettings:authSettings]; + + // test api key auth + XCTAssertEqualObjects(headerParams[@"test1"], @"value1"); + XCTAssertEqualObjects(headerParams[@"api_key"], @"PREFIX 123456"); + XCTAssertEqualObjects(queryParams[@"test2"], @"value2"); + + // test basic auth + XCTAssertEqualObjects(@"test_username", config.username); + XCTAssertEqualObjects(@"test_password", config.password); +} + +- (void)testGetBasicAuthToken { + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + config.username = @"test_username"; + config.password = @"test_password"; + + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", config.username, config.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + XCTAssertEqualObjects(basicAuthCredentials, [config getBasicAuthToken]); +} + @end diff --git a/samples/client/petstore/objc/Podfile.lock b/samples/client/petstore/objc/Podfile.lock index 6ac776ab37a..48b1f809658 100644 --- a/samples/client/petstore/objc/Podfile.lock +++ b/samples/client/petstore/objc/Podfile.lock @@ -20,7 +20,7 @@ PODS: - AFNetworking/UIKit (2.5.4): - AFNetworking/NSURLConnection - AFNetworking/NSURLSession - - ISO8601 (0.2.0) + - ISO8601 (0.3.0) - JSONModel (1.1.0) DEPENDENCIES: @@ -30,7 +30,7 @@ DEPENDENCIES: SPEC CHECKSUMS: AFNetworking: 05edc0ac4c4c8cf57bcf4b84be5b0744b6d8e71e - ISO8601: 962282de75074c38bbfaa7b133b0e743ed6deb8d + ISO8601: 8d8a22d5edf0554a1cf75bac028c76c1dc0ffaef JSONModel: ec77e9865236a7a09d9cf7668df6b4b328d9ec1d COCOAPODS: 0.37.1 diff --git a/samples/client/petstore/objc/client/SWGApiClient.h b/samples/client/petstore/objc/client/SWGApiClient.h index cd6f52db5c6..250811c4016 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.h +++ b/samples/client/petstore/objc/client/SWGApiClient.h @@ -3,7 +3,7 @@ /** * A key for `NSError` user info dictionaries. - * + * * The corresponding value is the parsed response body for an HTTP error. */ extern NSString *const SWGResponseObjectErrorKey; @@ -20,56 +20,197 @@ extern NSString *const SWGResponseObjectErrorKey; @property(nonatomic, assign) BOOL logHTTP; @property(nonatomic, readonly) NSOperationQueue* queue; +/** + * Get the Api Client instance from pool + * + * @param baseUrl The base url of api client. + * + * @return The SWGApiClient instance. + */ +(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; +/** + * Get the operations queue + * + * @return The `shardQueue` static variable. + */ +(NSOperationQueue*) sharedQueue; +/** + * Turn on logging + * + * @param state logging state, must be `YES` or `NO` + */ +(void)setLoggingEnabled:(bool) state; +/** + * Clear Cache + */ +(void)clearCache; +/** + * Turn on cache + * + * @param enabled If the cached is enable, must be `YES` or `NO` + */ +(void)setCacheEnabled:(BOOL) enabled; +/** + * Get the request queue size + * + * @return The size of `queuedRequests` static variable. + */ +(unsigned long)requestQueueSize; +/** + * Set the client unreachable + * + * @param state off line state, must be `YES` or `NO` + */ +(void) setOfflineState:(BOOL) state; +/** + * Get the client reachability + * + * @return The client reachability. + */ +(AFNetworkReachabilityStatus) getReachabilityStatus; +/** + * Get the next request id + * + * @return The next executed request id. + */ +(NSNumber*) nextRequestId; +/** + * Generate request id and add it to the queue + * + * @return The next executed request id. + */ +(NSNumber*) queueRequest; +/** + * Remove request id from the queue + * + * @param requestId The request which will be removed. + */ +(void) cancelRequest:(NSNumber*)requestId; +/** + * URL encode NSString + * + * @param unescaped The string which will be escaped. + * + * @return The escaped string. + */ +(NSString*) escape:(id)unescaped; +/** + * Customize the behavior when the reachability changed + * + * @param changeBlock The block will be executed when the reachability changed. + */ +(void) setReachabilityChangeBlock:(void(^)(int))changeBlock; +/** + * Set the client reachability strategy + * + * @param host The host of SWGApiClient. + */ +(void) configureCacheReachibilityForHost:(NSString*)host; +/** + * Detect Accept header from accepts NSArray + * + * @param accepts NSArray of header + * + * @return The Accept header + */ +(NSString *) selectHeaderAccept:(NSArray *)accepts; + +/** + * Detect Content-Type header from contentTypes NSArray + * + * @param contentTypes NSArray of header + * + * @return The Content-Type header + */ +(NSString *) selectHeaderContentType:(NSArray *)contentTypes; +/** + * Set header for request + * + * @param value The header value + * @param forKey The header key + */ -(void)setHeaderValue:(NSString*) value - forKey:(NSString*) forKey; + forKey:(NSString*) forKey; +/** + * Update header parameters and query parameters for authentication + * + * @param headers The header parameter will be udpated, passed by pointer to pointer. + * @param querys The query parameters will be updated, passed by pointer to pointer. + * @param authSettings The authentication names NSArray. + */ +- (void) updateHeaderParams:(NSDictionary **)headers + queryParams:(NSDictionary **)querys + WithAuthSettings:(NSArray *)authSettings; + +/** + * Perform request + * + * Request with non-empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. + */ -(NSNumber*) dictionary:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock; +/** + * Perform request + * + * Request with empty response + * + * @param path Request url. + * @param method Request method. + * @param queryParams Request query parameters. + * @param body Request body. + * @param headerParams Request header parameters. + * @param authSettings Request authentication names. + * @param requestContentType Request content-type. + * @param responseContentType Response content-type. + * @param completionBlock The block will be executed when the request completed. + * + * @return The request id. + */ -(NSNumber*) stringWithCompletionBlock:(NSString*) path method:(NSString*) method queryParams:(NSDictionary*) queryParams body:(id) body headerParams:(NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType:(NSString*) requestContentType responseContentType:(NSString*) responseContentType completionBlock:(void (^)(NSString*, NSError *))completionBlock; @end + diff --git a/samples/client/petstore/objc/client/SWGApiClient.m b/samples/client/petstore/objc/client/SWGApiClient.m index b38b02e0e03..5e2985bbe79 100644 --- a/samples/client/petstore/objc/client/SWGApiClient.m +++ b/samples/client/petstore/objc/client/SWGApiClient.m @@ -1,6 +1,7 @@ #import "SWGApiClient.h" #import "SWGFile.h" #import "SWGQueryParamCollection.h" +#import "SWGConfiguration.h" @implementation SWGApiClient @@ -15,10 +16,22 @@ static NSOperationQueue* sharedQueue; static void (^reachabilityChangeBlock)(int); static bool loggingEnabled = true; +#pragma mark - Log Methods + +(void)setLoggingEnabled:(bool) state { loggingEnabled = state; } +- (void)logRequest:(NSURLRequest*)request { + NSLog(@"request: %@", [self descriptionForRequest:request]); +} + +- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { + NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); +} + +#pragma mark - + +(void)clearCache { [[NSURLCache sharedURLCache] removeAllCachedResponses]; } @@ -305,19 +318,47 @@ static bool loggingEnabled = true; return [[request URL] absoluteString]; } -- (void)logRequest:(NSURLRequest*)request { - NSLog(@"request: %@", [self descriptionForRequest:request]); + +/** + * Update header and query params based on authentication settings + */ +- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers + queryParams:(NSDictionary *__autoreleasing *)querys + WithAuthSettings:(NSArray *)authSettings { + + if (!authSettings || [authSettings count] == 0) { + return; + } + + NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers]; + NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys]; + + SWGConfiguration *config = [SWGConfiguration sharedConfig]; + for (NSString *auth in authSettings) { + NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; + + if (authSetting) { + if ([authSetting[@"in"] isEqualToString:@"header"]) { + [headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + else if ([authSetting[@"in"] isEqualToString:@"query"]) { + [querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; + } + } + } + + *headers = [NSDictionary dictionaryWithDictionary:headersWithAuth]; + *querys = [NSDictionary dictionaryWithDictionary:querysWithAuth]; } -- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { - NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); -} +#pragma mark - Perform Request Methods -(NSNumber*) dictionary: (NSString*) path method: (NSString*) method queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSDictionary*, NSError *))completionBlock { @@ -342,6 +383,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ @@ -476,6 +520,7 @@ static bool loggingEnabled = true; queryParams: (NSDictionary*) queryParams body: (id) body headerParams: (NSDictionary*) headerParams + authSettings: (NSArray *) authSettings requestContentType: (NSString*) requestContentType responseContentType: (NSString*) responseContentType completionBlock: (void (^)(NSString*, NSError *))completionBlock { @@ -500,6 +545,9 @@ static bool loggingEnabled = true; else { self.responseSerializer = [AFHTTPResponseSerializer serializer]; } + + // auth setting + [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; NSMutableURLRequest * request = nil; if (body != nil && [body isKindOfClass:[NSArray class]]){ diff --git a/samples/client/petstore/objc/client/SWGConfiguration.h b/samples/client/petstore/objc/client/SWGConfiguration.h new file mode 100644 index 00000000000..33023ca3c6f --- /dev/null +++ b/samples/client/petstore/objc/client/SWGConfiguration.h @@ -0,0 +1,56 @@ +#import + +@interface SWGConfiguration : NSObject + + +/** + * Api key values for Api Key type Authentication + * + * To add or remove api key, use `setValue:forApiKeyField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKey; + +/** + * Api key prefix values to be prepend to the respective api key + * + * To add or remove prefix, use `setValue:forApiKeyPrefixField:`. + */ +@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix; + +/** + * Usename and Password for Basic type Authentication + */ +@property (nonatomic) NSString *username; +@property (nonatomic) NSString *password; + +/** + * Get configuration singleton instance + */ ++ (instancetype) sharedConfig; + +/** + * Sets field in `apiKey` + */ +- (void) setValue:(NSString *)value forApiKeyField:(NSString*)field; + +/** + * Sets field in `apiKeyPrefix` + */ +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field; + +/** + * Get API key (with prefix if set) + */ +- (NSString *) getApiKeyWithPrefix:(NSString *) key; + +/** + * Get Basic Auth token + */ +- (NSString *) getBasicAuthToken; + +/** + * Get Authentication Setings + */ +- (NSDictionary *) authSettings; + +@end diff --git a/samples/client/petstore/objc/client/SWGConfiguration.m b/samples/client/petstore/objc/client/SWGConfiguration.m new file mode 100644 index 00000000000..89d5a597946 --- /dev/null +++ b/samples/client/petstore/objc/client/SWGConfiguration.m @@ -0,0 +1,92 @@ +#import "SWGConfiguration.h" + +@interface SWGConfiguration () + +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey; +@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix; + +@end + +@implementation SWGConfiguration + +#pragma mark - Singletion Methods + ++ (instancetype) sharedConfig { + static SWGConfiguration *shardConfig = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shardConfig = [[self alloc] init]; + }); + return shardConfig; +} + +#pragma mark - Initialize Methods + +- (instancetype) init { + self = [super init]; + if (self) { + self.username = @""; + self.password = @""; + self.mutableApiKey = [NSMutableDictionary dictionary]; + self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Instance Methods + +- (NSString *) getApiKeyWithPrefix:(NSString *)key { + if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]]; + } + else if ([self.apiKey objectForKey:key]) { + return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]]; + } + else { + return @""; + } +} + +- (NSString *) getBasicAuthToken { + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", self.username, self.password]; + NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding]; + basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]]; + + return basicAuthCredentials; +} + +#pragma mark - Setter Methods + +- (void) setValue:(NSString *)value forApiKeyField:(NSString *)field { + [self.mutableApiKey setValue:value forKey:field]; +} + +- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field { + [self.mutableApiKeyPrefix setValue:value forKey:field]; +} + +#pragma mark - Getter Methods + +- (NSDictionary *) apiKey { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKey]; +} + +- (NSDictionary *) apiKeyPrefix { + return [NSDictionary dictionaryWithDictionary:self.mutableApiKeyPrefix]; +} + +#pragma mark - + +- (NSDictionary *) authSettings { + return @{ + @"api_key": @{ + @"type": @"api_key", + @"in": @"header", + @"key": @"api_key", + @"value": [self getApiKeyWithPrefix:@"api_key"] + }, + + }; +} + +@end diff --git a/samples/client/petstore/objc/client/SWGPetApi.m b/samples/client/petstore/objc/client/SWGPetApi.m index 9487713984b..c14da125af5 100644 --- a/samples/client/petstore/objc/client/SWGPetApi.m +++ b/samples/client/petstore/objc/client/SWGPetApi.m @@ -38,6 +38,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGPetApi* singletonAPI = nil; @@ -115,6 +117,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/json", @"application/xml"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; id __body = body; @@ -160,6 +165,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -218,6 +224,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/json", @"application/xml"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; id __body = body; @@ -263,6 +272,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -327,6 +337,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -346,6 +359,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -427,6 +441,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -446,6 +463,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -525,6 +543,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"api_key", @"petstore_auth"]; + id bodyDictionary = nil; @@ -552,6 +573,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -627,6 +649,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"application/x-www-form-urlencoded"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -665,6 +690,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -731,6 +757,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -753,6 +782,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -819,6 +849,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[@"multipart/form-data"]]; + // Authentication setting + NSArray *authSettings = @[@"petstore_auth"]; + id bodyDictionary = nil; @@ -864,6 +897,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/objc/client/SWGQueryParamCollection.m b/samples/client/petstore/objc/client/SWGQueryParamCollection.m index 9ce319940dd..83303045185 100644 --- a/samples/client/petstore/objc/client/SWGQueryParamCollection.m +++ b/samples/client/petstore/objc/client/SWGQueryParamCollection.m @@ -13,4 +13,4 @@ return self; } -@end \ No newline at end of file +@end diff --git a/samples/client/petstore/objc/client/SWGStoreApi.h b/samples/client/petstore/objc/client/SWGStoreApi.h index c2d0dd6b36b..49d8db806c8 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.h +++ b/samples/client/petstore/objc/client/SWGStoreApi.h @@ -8,6 +8,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/samples/client/petstore/objc/client/SWGStoreApi.m b/samples/client/petstore/objc/client/SWGStoreApi.m index 98b9d9a4eec..a112db6d639 100644 --- a/samples/client/petstore/objc/client/SWGStoreApi.m +++ b/samples/client/petstore/objc/client/SWGStoreApi.m @@ -37,6 +37,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGStoreApi* singletonAPI = nil; @@ -112,6 +114,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[@"api_key"]; + id bodyDictionary = nil; @@ -131,6 +136,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -199,6 +205,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -249,6 +258,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -320,6 +330,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -347,6 +360,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -418,6 +432,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -440,6 +457,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/objc/client/SWGUserApi.h b/samples/client/petstore/objc/client/SWGUserApi.h index d9d5a8abc18..e6e73ddfba6 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.h +++ b/samples/client/petstore/objc/client/SWGUserApi.h @@ -8,6 +8,7 @@ @property(nonatomic, assign)SWGApiClient *apiClient; +-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; diff --git a/samples/client/petstore/objc/client/SWGUserApi.m b/samples/client/petstore/objc/client/SWGUserApi.m index 97a79f01b6d..e2fe69aca8d 100644 --- a/samples/client/petstore/objc/client/SWGUserApi.m +++ b/samples/client/petstore/objc/client/SWGUserApi.m @@ -37,6 +37,8 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; return self; } +#pragma mark - + +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { static SWGUserApi* singletonAPI = nil; @@ -114,6 +116,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -159,6 +164,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -217,6 +223,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -262,6 +271,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -320,6 +330,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -365,6 +378,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -433,6 +447,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -457,6 +474,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -524,6 +542,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -546,6 +567,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -608,6 +630,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -635,6 +660,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSDictionary *data, NSError *error) { @@ -708,6 +734,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; id __body = body; @@ -753,6 +782,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { @@ -815,6 +845,9 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; // request content type NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[]]; + // Authentication setting + NSArray *authSettings = @[]; + id bodyDictionary = nil; @@ -837,6 +870,7 @@ static NSString * basePath = @"http://petstore.swagger.io/v2"; queryParams: queryParams body: bodyDictionary headerParams: headerParams + authSettings: authSettings requestContentType: requestContentType responseContentType: responseContentType completionBlock: ^(NSString *data, NSError *error) { diff --git a/samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm b/samples/client/petstore/perl/lib/WWW/SwaggerClient/ApiClient.pm similarity index 100% rename from samples/client/petstore/perl/lib/WWW/SwaggerClient/APIClient.pm rename to samples/client/petstore/perl/lib/WWW/SwaggerClient/ApiClient.pm diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php index 11b06862875..229709562ef 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/APIClient.php @@ -187,13 +187,10 @@ class ApiClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - if ($headerParams != null) { - # add default header - $headerParams = array_merge((array)self::$default_header, $headerParams); + $headerParams = array_merge((array)self::$default_header, (array)$headerParams); - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - } + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; } // form data @@ -297,7 +294,9 @@ class ApiClient { } else if (is_object($data)) { $values = array(); foreach (array_keys($data::$swaggerTypes) as $property) { - $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + if ($data->$property !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property); + } } $sanitized = $values; } else { @@ -382,17 +381,16 @@ class ApiClient { { if (null === $data) { $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] $inner = substr($class, 4, -1); - $values = array(); + $deserialized = array(); if(strrpos($inner, ",") !== false) { $subClass_array = explode(',', $inner, 2); $subClass = $subClass_array[1]; foreach ($data as $key => $value) { - $values[] = array($key => self::deserialize($value, $subClass)); + $deserialized[$key] = self::deserialize($value, $subClass); } } - $deserialized = $values; } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { $subClass = substr($class, 6, -1); $values = array(); @@ -402,7 +400,7 @@ class ApiClient { $deserialized = $values; } elseif ($class == 'DateTime') { $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) { + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { settype($data, $class); $deserialized = $data; } else { diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php index d02b8e74558..390cf332b23 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php @@ -181,7 +181,7 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame($response->name, 'PHP Unit Test'); } - // test + // test upload file public function testUploadFile() { // initialize the API client @@ -194,6 +194,20 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame($add_response, NULL); } + // test get inventory + public function testGetInventory() + { + // initialize the API client + $api_client = new SwaggerClient\APIClient('http://petstore.swagger.io/v2'); + $store_api = new SwaggerClient\StoreAPI($api_client); + // get inventory + $get_response = $store_api->getInventory(); + + $this->assertInternalType("int", $get_response['sold']); + $this->assertInternalType("int", $get_response['pending']); + + } + } ?> diff --git a/samples/client/petstore/php/test.php b/samples/client/petstore/php/test.php index a358ea5df45..f39e0dae4cf 100644 --- a/samples/client/petstore/php/test.php +++ b/samples/client/petstore/php/test.php @@ -12,8 +12,11 @@ require_once('SwaggerClient-php/SwaggerClient.php'); $petId = 10005; // ID of pet that needs to be fetched try { + // get pet by id //$pet_api = new SwaggerClient\PetAPI($api_client); $pet_api = new SwaggerClient\PetAPI(); + // test default header + $pet_api->getApiClient()->addDefaultHeader("TEST_API_KEY", "09182sdkanafndsl903"); // return Pet (model) $response = $pet_api->getPetById($petId); var_dump($response); @@ -21,11 +24,33 @@ try { // test upload file (exception) $upload_response = $pet_api->uploadFile($petId, "test meta", NULL); -} catch (SwaggerClient\ApiException $e) { + // add pet (post json) + $new_pet_id = 10005; + $new_pet = new SwaggerClient\models\Pet; + $new_pet->id = $new_pet_id; + $new_pet->name = "PHP Unit Test"; + // new tag + $tag= new SwaggerClient\models\Tag; + $tag->id = $new_pet_id; // use the same id as pet + //$tag->name = "test php tag"; + // new category + $category = new SwaggerClient\models\Category; + $category->id = 0; // use the same id as pet + //$category->name = "test php category"; + + $new_pet->tags = array($tag); + $new_pet->category = $category; + + $pet_api = new SwaggerClient\PetAPI(); + // add a new pet (model) + $add_response = $pet_api->addPet($new_pet); + +} catch (Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; echo 'HTTP response headers: ', $e->getResponseHeaders(), "\n"; echo 'HTTP response body: ', $e->getResponseBody(), "\n"; echo 'HTTP status code: ', $e->getCode(), "\n"; } + ?> diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py index 9d4b2db3de5..3e7b51b8467 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py @@ -13,4 +13,4 @@ from .apis.pet_api import PetApi from .apis.store_api import StoreApi # import ApiClient -from .swagger import ApiClient +from .api_client import ApiClient diff --git a/modules/swagger-codegen/src/main/resources/python/swagger.mustache b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/api_client.py similarity index 86% rename from modules/swagger-codegen/src/main/resources/python/swagger.mustache rename to samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/api_client.py index 21430c469c8..b8cc4cc2a84 100644 --- a/modules/swagger-codegen/src/main/resources/python/swagger.mustache +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/api_client.py @@ -28,6 +28,7 @@ except ImportError: # for python2 from urllib import quote +from . import configuration class ApiClient(object): """ @@ -37,7 +38,7 @@ class ApiClient(object): :param header_name: a header to pass when making calls to the API :param header_value: a header value to pass when making calls to the API """ - def __init__(self, host=None, header_name=None, header_value=None): + def __init__(self, host=configuration.host, header_name=None, header_value=None): self.default_headers = {} if header_name is not None: self.default_headers[header_name] = header_value @@ -58,15 +59,15 @@ class ApiClient(object): self.default_headers[header_name] = header_value def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, response=None): + body=None, post_params=None, files=None, response=None, auth_settings=None): # headers parameters - headers = self.default_headers.copy() - headers.update(header_params) + header_params = header_params or {} + header_params.update(self.default_headers) if self.cookie: - headers['Cookie'] = self.cookie - if headers: - headers = self.sanitize_for_serialization(headers) + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) # path parameters if path_params: @@ -85,6 +86,9 @@ class ApiClient(object): post_params = self.prepare_post_parameters(post_params, files) post_params = self.sanitize_for_serialization(post_params) + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + # body if body: body = self.sanitize_for_serialization(body) @@ -93,7 +97,7 @@ class ApiClient(object): url = self.host + resource_path # perform request and return response - response_data = self.request(method, url, query_params=query_params, headers=headers, + response_data = self.request(method, url, query_params=query_params, headers=header_params, post_params=post_params, body=body) # deserialize response data @@ -244,11 +248,12 @@ class ApiClient(object): if files: for k, v in iteritems(files): - with open(v, 'rb') as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' - params[k] = tuple([filename, filedata, mimetype]) + if v: + with open(v, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + params[k] = tuple([filename, filedata, mimetype]) return params @@ -279,3 +284,20 @@ class ApiClient(object): return 'application/json' else: return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """ + Update header and query params based on authentication setting + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = configuration.auth_settings().get(auth) + if auth_setting: + if auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys[auth_setting['key']] = auth_setting['value'] + else: + raise ValueError('Authentication token must be in `query` or `header`') diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py index ad4bad57412..549b7fe956f 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py @@ -27,9 +27,8 @@ import os # python 2 and python 3 compatibility library from six import iteritems -from ..util import remove_none - -from .. import config +from .. import configuration +from ..api_client import ApiClient class PetApi(object): @@ -37,7 +36,10 @@ class PetApi(object): if api_client: self.api_client = api_client else: - self.api_client = config.api_client + if not configuration.api_client: + configuration.api_client = ApiClient('http://petstore.swagger.io/v2') + self.api_client = configuration.api_client + def update_pet(self, **kwargs): """ @@ -61,13 +63,20 @@ class PetApi(object): resource_path = '/pet'.replace('{format}', 'json') method = 'PUT' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -76,9 +85,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def add_pet(self, **kwargs): """ @@ -102,13 +114,20 @@ class PetApi(object): resource_path = '/pet'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -117,9 +136,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/json', 'application/xml']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def find_pets_by_status(self, **kwargs): """ @@ -143,13 +165,20 @@ class PetApi(object): resource_path = '/pet/findByStatus'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict()) - query_params = remove_none(dict(status=params.get('status'))) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + query_params = {} + + if 'status' in params: + query_params['status'] = params['status'] + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -158,9 +187,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]') + response='list[Pet]', auth_settings=auth_settings) return response @@ -186,13 +218,20 @@ class PetApi(object): resource_path = '/pet/findByTags'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict()) - query_params = remove_none(dict(tags=params.get('tags'))) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + query_params = {} + + if 'tags' in params: + query_params['tags'] = params['tags'] + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -201,9 +240,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='list[Pet]') + response='list[Pet]', auth_settings=auth_settings) return response @@ -233,13 +275,20 @@ class PetApi(object): resource_path = '/pet/{petId}'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict(petId=params.get('pet_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'pet_id' in params: + path_params['petId'] = params['pet_id'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -248,9 +297,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['api_key', 'petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Pet') + response='Pet', auth_settings=auth_settings) return response @@ -282,13 +334,26 @@ class PetApi(object): resource_path = '/pet/{petId}'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict(petId=params.get('pet_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict(name=params.get('name'), status=params.get('status'))) - files = remove_none(dict()) + path_params = {} + + if 'pet_id' in params: + path_params['petId'] = params['pet_id'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + if 'name' in params: + form_params['name'] = params['name'] + + if 'status' in params: + form_params['status'] = params['status'] + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -297,9 +362,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['application/x-www-form-urlencoded']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def delete_pet(self, pet_id, **kwargs): """ @@ -328,13 +396,23 @@ class PetApi(object): resource_path = '/pet/{petId}'.replace('{format}', 'json') method = 'DELETE' - path_params = remove_none(dict(petId=params.get('pet_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict(api_key=params.get('api_key'))) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'pet_id' in params: + path_params['petId'] = params['pet_id'] + + query_params = {} + + header_params = {} + + if 'api_key' in params: + header_params['api_key'] = params['api_key'] + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -343,9 +421,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def upload_file(self, pet_id, **kwargs): """ @@ -375,13 +456,26 @@ class PetApi(object): resource_path = '/pet/{petId}/uploadImage'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict(petId=params.get('pet_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict(additionalMetadata=params.get('additional_metadata'), )) - files = remove_none(dict(file=params.get('file'))) + path_params = {} + + if 'pet_id' in params: + path_params['petId'] = params['pet_id'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + if 'additional_metadata' in params: + form_params['additionalMetadata'] = params['additional_metadata'] + + if 'file' in params: + files['file'] = params['file'] + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -390,9 +484,12 @@ class PetApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type(['multipart/form-data']) + # Authentication setting + auth_settings = ['petstore_auth'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py index e973d3a6ba5..bd2fd9b8080 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py @@ -27,9 +27,8 @@ import os # python 2 and python 3 compatibility library from six import iteritems -from ..util import remove_none - -from .. import config +from .. import configuration +from ..api_client import ApiClient class StoreApi(object): @@ -37,7 +36,10 @@ class StoreApi(object): if api_client: self.api_client = api_client else: - self.api_client = config.api_client + if not configuration.api_client: + configuration.api_client = ApiClient('http://petstore.swagger.io/v2') + self.api_client = configuration.api_client + def get_inventory(self, **kwargs): """ @@ -60,13 +62,17 @@ class StoreApi(object): resource_path = '/store/inventory'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -75,9 +81,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = ['api_key'] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='map(String, int)') + response='map(String, int)', auth_settings=auth_settings) return response @@ -103,13 +112,20 @@ class StoreApi(object): resource_path = '/store/order'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -118,9 +134,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order') + response='Order', auth_settings=auth_settings) return response @@ -150,13 +169,20 @@ class StoreApi(object): resource_path = '/store/order/{orderId}'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict(orderId=params.get('order_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'order_id' in params: + path_params['orderId'] = params['order_id'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -165,9 +191,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='Order') + response='Order', auth_settings=auth_settings) return response @@ -197,13 +226,20 @@ class StoreApi(object): resource_path = '/store/order/{orderId}'.replace('{format}', 'json') method = 'DELETE' - path_params = remove_none(dict(orderId=params.get('order_id'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'order_id' in params: + path_params['orderId'] = params['order_id'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -212,9 +248,12 @@ class StoreApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py index 82874000d59..5aca93818d0 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py @@ -27,9 +27,8 @@ import os # python 2 and python 3 compatibility library from six import iteritems -from ..util import remove_none - -from .. import config +from .. import configuration +from ..api_client import ApiClient class UserApi(object): @@ -37,7 +36,10 @@ class UserApi(object): if api_client: self.api_client = api_client else: - self.api_client = config.api_client + if not configuration.api_client: + configuration.api_client = ApiClient('http://petstore.swagger.io/v2') + self.api_client = configuration.api_client + def create_user(self, **kwargs): """ @@ -61,13 +63,20 @@ class UserApi(object): resource_path = '/user'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -76,9 +85,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def create_users_with_array_input(self, **kwargs): """ @@ -102,13 +114,20 @@ class UserApi(object): resource_path = '/user/createWithArray'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -117,9 +136,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def create_users_with_list_input(self, **kwargs): """ @@ -143,13 +165,20 @@ class UserApi(object): resource_path = '/user/createWithList'.replace('{format}', 'json') method = 'POST' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -158,9 +187,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def login_user(self, **kwargs): """ @@ -185,13 +217,23 @@ class UserApi(object): resource_path = '/user/login'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict()) - query_params = remove_none(dict(username=params.get('username'), password=params.get('password'))) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + query_params = {} + + if 'username' in params: + query_params['username'] = params['username'] + + if 'password' in params: + query_params['password'] = params['password'] + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -200,9 +242,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='str') + response='str', auth_settings=auth_settings) return response @@ -227,13 +272,17 @@ class UserApi(object): resource_path = '/user/logout'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict()) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -242,9 +291,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def get_user_by_name(self, username, **kwargs): """ @@ -272,13 +324,20 @@ class UserApi(object): resource_path = '/user/{username}'.replace('{format}', 'json') method = 'GET' - path_params = remove_none(dict(username=params.get('username'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'username' in params: + path_params['username'] = params['username'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -287,9 +346,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response='User') + response='User', auth_settings=auth_settings) return response @@ -320,13 +382,23 @@ class UserApi(object): resource_path = '/user/{username}'.replace('{format}', 'json') method = 'PUT' - path_params = remove_none(dict(username=params.get('username'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) - body_params = params.get('body') - + path_params = {} + + if 'username' in params: + path_params['username'] = params['username'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + + body_params = None + + if 'body' in params: + body_params = params['body'] + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -335,9 +407,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) def delete_user(self, username, **kwargs): """ @@ -365,13 +440,20 @@ class UserApi(object): resource_path = '/user/{username}'.replace('{format}', 'json') method = 'DELETE' - path_params = remove_none(dict(username=params.get('username'))) - query_params = remove_none(dict()) - header_params = remove_none(dict()) - form_params = remove_none(dict()) - files = remove_none(dict()) + path_params = {} + + if 'username' in params: + path_params['username'] = params['username'] + + query_params = {} + + header_params = {} + + form_params = {} + files = {} + body_params = None - + # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept(['application/json', 'application/xml']) if not header_params['Accept']: @@ -380,9 +462,12 @@ class UserApi(object): # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type([]) + # Authentication setting + auth_settings = [] + response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, body=body_params, post_params=form_params, files=files, - response=None) + response=None, auth_settings=auth_settings) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py deleted file mode 100644 index 6e158eedd70..00000000000 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/config.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import absolute_import - -from .swagger import ApiClient - -# Configuration variables - -api_client = ApiClient("http://petstore.swagger.io/v2") - diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/configuration.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/configuration.py new file mode 100644 index 00000000000..b5bd0a64e0a --- /dev/null +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/configuration.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import +import base64 +import urllib3 + +def get_api_key_with_prefix(key): + global api_key + global api_key_prefix + + if api_key.get(key) and api_key_prefix.get(key): + return api_key_prefix[key] + ' ' + api_key[key] + elif api_key.get(key): + return api_key[key] + +def get_basic_auth_token(): + global username + global password + + return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization') + +def auth_settings(): + return { + 'api_key': { + 'type': 'api_key', + 'in': 'header', + 'key': 'api_key', + 'value': get_api_key_with_prefix('api_key') + }, + + } + +# Default Base url +host = "http://petstore.swagger.io/v2" + +# Default api client +api_client = None + +# Authentication settings + +api_key = {} +api_key_prefix = {} +username = '' +password = '' + + diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py index da99abc2493..508f3d6693a 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py @@ -1,4 +1,10 @@ # coding: utf-8 + +""" +Credit: this file (rest.py) is modified based on rest.py in Dropbox Python SDK: +https://www.dropbox.com/developers/core/sdks/python +""" + import sys import io import json @@ -120,7 +126,7 @@ class RESTClientObject(object): r = RESTResponse(r) if r.status not in range(200, 206): - raise ErrorResponse(r) + raise ApiException(r) return self.process_response(r) @@ -157,7 +163,7 @@ class RESTClientObject(object): return self.request("PATCH", url, headers=headers, post_params=post_params, body=body) -class ErrorResponse(Exception): +class ApiException(Exception): """ Non-2xx HTTP response """ @@ -184,7 +190,10 @@ class ErrorResponse(Exception): """ Custom error response messages """ - return "({0})\nReason: {1}\nHeader: {2}\nBody: {3}\n".\ + return "({0})\n"\ + "Reason: {1}\n"\ + "HTTP response headers: {2}\n"\ + "HTTP response body: {3}\n".\ format(self.status, self.reason, self.headers, self.body) class RESTClient(object): diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/util.py b/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/util.py deleted file mode 100644 index 1137a5d2d23..00000000000 --- a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/util.py +++ /dev/null @@ -1,17 +0,0 @@ -from six import iteritems - -def remove_none(obj): - if isinstance(obj, (list, tuple, set)): - return type(obj)(remove_none(x) for x in obj if x is not None) - elif isinstance(obj, dict): - return type(obj)((remove_none(k), remove_none(v)) - for k, v in iteritems(obj) if k is not None and v is not None) - else: - return obj - - -def inspect_vars(obj): - if not hasattr(obj, '__dict__'): - return obj - else: - return {k: inspect_vars(getattr(obj, k)) for k in dir(obj)} diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py index 5243430a93a..0ef4314d0f4 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py @@ -12,6 +12,7 @@ import time import unittest import SwaggerPetstore +import SwaggerPetstore.configuration HOST = 'http://petstore.swagger.io/v2' @@ -21,6 +22,31 @@ class ApiClientTests(unittest.TestCase): def setUp(self): self.api_client = SwaggerPetstore.ApiClient(HOST) + def test_configuration(self): + SwaggerPetstore.configuration.api_key['api_key'] = '123456' + SwaggerPetstore.configuration.api_key_prefix['api_key'] = 'PREFIX' + SwaggerPetstore.configuration.username = 'test_username' + SwaggerPetstore.configuration.password = 'test_password' + + header_params = {'test1': 'value1'} + query_params = {'test2': 'value2'} + auth_settings = ['api_key', 'unknown'] + + # test prefix + self.assertEqual('PREFIX', SwaggerPetstore.configuration.api_key_prefix['api_key']) + + # update parameters based on auth setting + self.api_client.update_params_for_auth(header_params, query_params, auth_settings) + + # test api key auth + self.assertEqual(header_params['test1'], 'value1') + self.assertEqual(header_params['api_key'], 'PREFIX 123456') + self.assertEqual(query_params['test2'], 'value2') + + # test basic auth + self.assertEqual('test_username', SwaggerPetstore.configuration.username) + self.assertEqual('test_password', SwaggerPetstore.configuration.password) + def test_select_header_accept(self): accepts = ['APPLICATION/JSON', 'APPLICATION/XML'] accept = self.api_client.select_header_accept(accepts) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py new file mode 100644 index 00000000000..d1b786241e8 --- /dev/null +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py @@ -0,0 +1,76 @@ +# coding: utf-8 + +""" +Run the tests. +$ pip install nose (optional) +$ cd SwaggerPetstore-python +$ nosetests -v +""" + +import os +import time +import unittest + +import SwaggerPetstore +from SwaggerPetstore.rest import ApiException + + +class ApiExceptionTests(unittest.TestCase): + + def setUp(self): + self.api_client = SwaggerPetstore.ApiClient() + self.pet_api = SwaggerPetstore.PetApi(self.api_client) + self.setUpModels() + + def setUpModels(self): + self.category = SwaggerPetstore.Category() + self.category.id = int(time.time()) + self.category.name = "dog" + self.tag = SwaggerPetstore.Tag() + self.tag.id = int(time.time()) + self.tag.name = "blank" + self.pet = SwaggerPetstore.Pet() + self.pet.id = int(time.time()) + self.pet.name = "hello kity" + self.pet.photo_urls = ["http://foo.bar.com/1", "http://foo.bar.com/2"] + self.pet.status = "sold" + self.pet.category = self.category + self.pet.tags = [self.tag] + + def tearDown(self): + time.sleep(1) + + def test_404_error(self): + self.pet_api.add_pet(body=self.pet) + self.pet_api.delete_pet(pet_id=self.pet.id) + + with self.assertRaisesRegexp(ApiException, "Pet not found"): + self.pet_api.get_pet_by_id(pet_id=self.pet.id) + + try: + self.pet_api.get_pet_by_id(pet_id=self.pet.id) + except ApiException as e: + self.assertEqual(e.status, 404) + self.assertEqual(e.reason, "Not Found") + self.assertDictEqual(e.body, {'message': 'Pet not found', 'code': 1, 'type': 'error'}) + + def test_500_error(self): + self.pet_api.add_pet(body=self.pet) + + with self.assertRaisesRegexp(ApiException, "Internal Server Error"): + self.pet_api.upload_file( + pet_id=self.pet.id, + additional_metadata="special", + file=None + ) + + try: + self.pet_api.upload_file( + pet_id=self.pet.id, + additional_metadata="special", + file=None + ) + except ApiException as e: + self.assertEqual(e.status, 500) + self.assertEqual(e.reason, "Internal Server Error") + self.assertRegexpMatches(e.body, "Error 500 Internal Server Error") diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py index ee8c5dde14e..3bf18607729 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py +++ b/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py @@ -12,8 +12,7 @@ import time import unittest import SwaggerPetstore -from SwaggerPetstore.rest import ErrorResponse -from SwaggerPetstore import config +from SwaggerPetstore.rest import ApiException HOST = 'http://petstore.swagger.io/v2' @@ -62,11 +61,11 @@ class PetApiTests(unittest.TestCase): # same default api client self.assertEqual(pet_api.api_client, pet_api2.api_client) # confirm using the default api client in the config module - self.assertEqual(pet_api.api_client, config.api_client) + self.assertEqual(pet_api.api_client, SwaggerPetstore.configuration.api_client) # 2 different api clients are not the same self.assertNotEqual(api_client3, api_client4) # customized pet api not using the default api client - self.assertNotEqual(pet_api3.api_client, config.api_client) + self.assertNotEqual(pet_api3.api_client, SwaggerPetstore.configuration.api_client) # customized pet api not using the old pet api's api client self.assertNotEqual(pet_api3.api_client, pet_api2.api_client) @@ -126,7 +125,7 @@ class PetApiTests(unittest.TestCase): additional_metadata=additional_metadata, file=self.foo ) - except ErrorResponse as e: + except ApiException as e: self.fail("upload_file() raised {0} unexpectedly".format(type(e))) def test_delete_pet(self): @@ -136,7 +135,7 @@ class PetApiTests(unittest.TestCase): try: self.pet_api.get_pet_by_id(pet_id=self.pet.id) raise "expected an error" - except ErrorResponse as e: + except ApiException as e: self.assertEqual(404, e.status) if __name__ == '__main__':