Merge branch 'develop_2.0' into java-accept-contenttype

Conflicts:
	modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/JavaClientCodegen.java
	modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache
	modules/swagger-codegen/src/main/resources/Java/api.mustache
	samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java
	samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java
	samples/client/petstore/java/src/main/java/io/swagger/client/api/StoreApi.java
	samples/client/petstore/java/src/main/java/io/swagger/client/api/UserApi.java
	samples/client/petstore/java/src/test/java/io/swagger/client/ApiClientTest.java
This commit is contained in:
xhh
2015-06-06 08:46:19 +08:00
86 changed files with 2673 additions and 401 deletions

View File

@@ -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<String>(
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;
}
}

View File

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

View File

@@ -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<String>(
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<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float")
);
}
@Override

View File

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

View File

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

View File

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

View File

@@ -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<String, Client> hostMap = new HashMap<String, Client>();
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private boolean debugging = false;
private String basePath = "{{basePath}}";
private Map<String, Authentication> 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<String, Authentication>();{{#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<String, Authentication> 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<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType) throws ApiException {
public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> 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<String, String> queryParams, Map<String, String> 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.
*/

View File

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

View File

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

View File

@@ -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<String, String> queryParams, Map<String, String> 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);
}
}
}

View File

@@ -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<String, String> queryParams, Map<String, String> headerParams);
}

View File

@@ -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<String, String> queryParams, Map<String, String> 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);
}
}
}

View File

@@ -0,0 +1,10 @@
package {{invokerPackage}}.auth;
import java.util.Map;
public class OAuth implements Authentication {
@Override
public void applyToParams(Map<String, String> queryParams, Map<String, String> headerParams) {
// TODO: support oauth
}
}

View File

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

View File

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

View File

@@ -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<String, String> defaultHeaderMap = new Dictionary<String, String>();
public Object CallApi(String Path, RestSharp.Method Method, Dictionary<String, String> QueryParams, String PostBody,
public Object CallApi(String Path, RestSharp.Method Method, Dictionary<String, String> QueryParams, String PostBody,
Dictionary<String, String> HeaderParams, Dictionary<String, String> FormParams, Dictionary<String, String> 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<Object> CallApiAsync(String Path, RestSharp.Method Method, Dictionary<String, String> QueryParams, String PostBody,
Dictionary<String, String> HeaderParams, Dictionary<String, String> FormParams, Dictionary<String, String> 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);
}

View File

@@ -11,6 +11,12 @@ namespace {{invokerPackage}} {
/// <value>The error code (HTTP status code).</value>
public int ErrorCode { get; set; }
/// <summary>
/// Gets or sets the error content (body json object)
/// </summary>
/// <value>The error content (Http response body).</value>
public dynamic ErrorContent { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
@@ -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;
}
}
}

View File

@@ -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>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
{{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/operation}}
}
/// <summary>
/// Represents a collection of functions to interact with the API endpoints
/// </summary>
public class {{classname}} {
public class {{classname}} : I{{classname}} {
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// </summary>
@@ -61,8 +82,7 @@ namespace {{package}} {
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}} /// <param name="{{paramName}}">{{description}}</param>
{{/allParams}}
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
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>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
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<String, String>();
var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, String>();
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}}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,56 @@
#import <Foundation/Foundation.h>
@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

View File

@@ -13,4 +13,4 @@
return self;
}
@end
@end

View File

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

View File

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

View File

@@ -4,6 +4,7 @@
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSDictionary *data, NSError *error) {

View File

@@ -5,6 +5,7 @@
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSDictionary *data, NSError *error) {

View File

@@ -4,6 +4,7 @@
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSString *data, NSError *error) {

View File

@@ -3,6 +3,7 @@
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSString *data, NSError *error) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,8 +0,0 @@
from __future__ import absolute_import
from .swagger import ApiClient
# Configuration variables
api_client = ApiClient("{{basePath}}")

View File

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

View File

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

View File

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