[Kotlin] client improvement / remove WildCards in client/server (#2862)

This commit is contained in:
Vincent Devos 2019-05-11 05:42:11 +02:00 committed by William Cheng
parent 9323cad06b
commit ef26ce68d4
58 changed files with 656 additions and 340 deletions

4
.gitignore vendored
View File

@ -175,12 +175,14 @@ samples/client/petstore/typescript-angular/tsd-debug.log
# aspnetcore
samples/server/petstore/aspnetcore/.vs/
effective.pom
# kotlin
samples/client/petstore/kotlin/src/main/kotlin/test/
samples/client/petstore/kotlin-threetenbp/build
samples/client/petstore/kotlin-string/build
samples/server/petstore/kotlin-server/ktor/build
samples/openapi3/client/petstore/kotlin/build
samples/server/petstore/kotlin-server/ktor/build
samples/server/petstore/kotlin-springboot/build
\?
# haskell

View File

@ -8,14 +8,14 @@ sidebar_label: kotlin-server
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|sourceFolder|source folder for generated code| |src/main/kotlin|
|packageName|Generated artifact package name.| |org.openapitools|
|packageName|Generated artifact package name.| |org.openapitools.server|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |kotlin-server|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|library|library template (sub-template) to use|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dl>|ktor|
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dl>|ktor|
|featureAutoHead|Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.| |true|
|featureConditionalHeaders|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |false|
|featureHSTS|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |true|

View File

@ -11,7 +11,7 @@ sidebar_label: kotlin-spring
|packageName|Generated artifact package name.| |org.openapitools|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |openapi-spring|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle &quot;@Parcelize&quot; for generated models| |null|
@ -26,4 +26,4 @@ sidebar_label: kotlin-spring
|serviceInterface|generate service interfaces to go alongside controllers. In most cases this option would be used to update an existing project, so not to override implementations. Useful to help facilitate the generation gap pattern| |false|
|serviceImplementation|generate stub service implementations that extends service interfaces. If this is set to true service interfaces will also be generated| |false|
|useBeanValidation|Use BeanValidation API annotations to validate data types| |true|
|library|library template (sub-template) to use|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dl>|spring-boot|
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dl>|spring-boot|

View File

@ -8,12 +8,12 @@ sidebar_label: kotlin
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|sourceFolder|source folder for generated code| |src/main/kotlin|
|packageName|Generated artifact package name.| |org.openapitools|
|packageName|Generated artifact package name.| |org.openapitools.client|
|apiSuffix|suffix for api classes| |Api|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactId|Generated artifact id (name of jar).| |kotlin-client|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|parcelizeModels|toggle &quot;@Parcelize&quot; for generated models| |null|
|dateLibrary|Option. Date library to use|<dl><dt>**string**</dt><dd>String</dd><dt>**java8**</dt><dd>Java 8 native JSR310</dd><dt>**threetenbp**</dt><dd>Threetenbp</dd><dl>|null|
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd><dl>|null|
|dateLibrary|Option. Date library to use|<dl><dt>**string**</dt><dd>String</dd><dt>**java8**</dt><dd>Java 8 native JSR310</dd><dt>**threetenbp**</dt><dd>Threetenbp</dd><dl>|java8|
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd><dl>|array|

View File

@ -102,7 +102,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
apiPackage = "org.openapitools.client.api";
modelPackage = "org.openapitools.client.model";
// clioOptions default redifinition need to be updated
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.INVOKER_PACKAGE, this.getInvokerPackage());
updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId());
updateOption(CodegenConstants.API_PACKAGE, apiPackage);

View File

@ -21,8 +21,6 @@ import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.HashMap;
@ -32,7 +30,6 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
public static final String DATE_LIBRARY = "dateLibrary";
public static final String COLLECTION_TYPE = "collectionType";
private static final Logger LOGGER = LoggerFactory.getLogger(KotlinClientCodegen.class);
protected String dateLibrary = DateLibrary.JAVA8.value;
protected String collectionType = CollectionType.ARRAY.value;
@ -69,6 +66,10 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
artifactId = "kotlin-client";
packageName = "org.openapitools.client";
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);
outputFolder = "generated-code" + File.separator + "kotlin-client";
modelTemplateFiles.put("model.mustache", ".kt");
apiTemplateFiles.put("api.mustache", ".kt");
@ -78,14 +79,13 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
apiPackage = packageName + ".apis";
modelPackage = packageName + ".models";
enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use");
Map<String, String> dateOptions = new HashMap<>();
dateOptions.put(DateLibrary.THREETENBP.value, "Threetenbp");
dateOptions.put(DateLibrary.STRING.value, "String");
dateOptions.put(DateLibrary.JAVA8.value, "Java 8 native JSR310");
dateLibrary.setEnum(dateOptions);
dateLibrary.setDefault(this.dateLibrary);
cliOptions.add(dateLibrary);
CliOption collectionType = new CliOption(COLLECTION_TYPE, "Option. Collection type to use");
@ -93,6 +93,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
collectionOptions.put(CollectionType.ARRAY.value, "kotlin.Array");
collectionOptions.put(CollectionType.LIST.value, "kotlin.collections.List");
collectionType.setEnum(collectionOptions);
collectionType.setDefault(this.collectionType);
cliOptions.add(collectionType);
}

View File

@ -62,6 +62,11 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen {
artifactId = "kotlin-server";
packageName = "org.openapitools.server";
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);
outputFolder = "generated-code" + File.separator + "kotlin-server";
modelTemplateFiles.put("model.mustache", ".kt");
apiTemplateFiles.put("api.mustache", ".kt");
@ -69,10 +74,10 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen {
apiPackage = packageName + ".apis";
modelPackage = packageName + ".models";
supportedLibraries.put("ktor", "ktor framework");
supportedLibraries.put(Constants.KTOR, "ktor framework");
// TODO: Configurable server engine. Defaults to netty in build.gradle.
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
CliOption library = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
library.setDefault(DEFAULT_LIBRARY);
library.setEnum(supportedLibraries);
@ -147,9 +152,9 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen {
// set default library to "ktor"
if (StringUtils.isEmpty(library)) {
this.setLibrary("ktor");
additionalProperties.put(CodegenConstants.LIBRARY, "ktor");
LOGGER.info("`library` option is empty. Default to 'ktor'.");
this.setLibrary(DEFAULT_LIBRARY);
additionalProperties.put(CodegenConstants.LIBRARY, DEFAULT_LIBRARY);
LOGGER.info("`library` option is empty. Default to " + DEFAULT_LIBRARY);
}
if (additionalProperties.containsKey(Constants.AUTOMATIC_HEAD_REQUESTS)) {
@ -182,7 +187,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen {
additionalProperties.put(Constants.COMPRESSION, getCompressionFeatureEnabled());
}
Boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean)additionalProperties.get(CodegenConstants.GENERATE_APIS);
boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean)additionalProperties.get(CodegenConstants.GENERATE_APIS);
String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);
String resourcesFolder = "src/main/resources"; // not sure this can be user configurable.
@ -226,7 +231,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen {
if (objs.containsKey("lambda")) {
LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " +
"You'll likely need to use a custom template, " +
"see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. "); // TODO: update the URL
"see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md. ");
objs.put("_lambda", lambdas);
} else {
objs.put("lambda", lambdas);

View File

@ -87,6 +87,9 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
apiPackage = "org.openapitools.api";
modelPackage = "org.openapitools.model";
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
// Use lists instead of arrays
typeMapping.put("array", "List");
typeMapping.put("string", "String");
@ -149,7 +152,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
setLibrary(SPRING_BOOT);
CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
cliOpt.setDefault(SPRING_BOOT);
cliOpt.setEnum(supportedLibraries);
cliOptions.add(cliOpt);

View File

@ -2,7 +2,7 @@
## Requires
* Kotlin 1.3.20
* Kotlin 1.3.31
* Gradle 4.9
## Build

View File

@ -4,7 +4,17 @@ package {{apiPackage}}
{{#imports}}import {{import}}
{{/imports}}
import {{packageName}}.infrastructure.*
import {{packageName}}.infrastructure.ApiClient
import {{packageName}}.infrastructure.ClientException
import {{packageName}}.infrastructure.ClientError
import {{packageName}}.infrastructure.ServerException
import {{packageName}}.infrastructure.ServerError
import {{packageName}}.infrastructure.MultiValueMap
import {{packageName}}.infrastructure.RequestConfig
import {{packageName}}.infrastructure.RequestMethod
import {{packageName}}.infrastructure.ResponseType
import {{packageName}}.infrastructure.Success
import {{packageName}}.infrastructure.toMultiValue
{{#threetenbp}}
import org.threeten.bp.LocalDateTime
{{/threetenbp}}
@ -23,7 +33,7 @@ class {{classname}}(basePath: kotlin.String = "{{{basePath}}}") : ApiClient(base
fun {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{^required}}?{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) : {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}} {
val localVariableBody: kotlin.Any? = {{#hasBodyParam}}{{#bodyParams}}{{paramName}}{{/bodyParams}}{{/hasBodyParam}}{{^hasBodyParam}}{{^hasFormParams}}null{{/hasFormParams}}{{#hasFormParams}}mapOf({{#formParams}}"{{{baseName}}}" to "${{paramName}}"{{#hasMore}}, {{/hasMore}}{{/formParams}}){{/hasFormParams}}{{/hasBodyParam}}
val localVariableQuery: MultiValueMap = {{^hasQueryParams}}mapOf(){{/hasQueryParams}}{{#hasQueryParams}}mapOf({{#queryParams}}"{{paramName}}" to {{#isContainer}}toMultiValue({{paramName}}.toList(), "{{collectionFormat}}"){{/isContainer}}{{^isContainer}}listOf("${{paramName}}"){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/queryParams}}){{/hasQueryParams}}
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf({{#hasFormParams}}"Content-Type" to "multipart/form-data"{{/hasFormParams}}{{^hasHeaderParams}}){{/hasHeaderParams}}{{#hasHeaderParams}}{{#hasFormParams}}, {{/hasFormParams}}{{#headerParams}}"{{baseName}}" to {{#isContainer}}{{paramName}}.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}{{paramName}}.toString(){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/headerParams}}){{/hasHeaderParams}}
val localVariableHeaders: MutableMap<String, String> = mutableMapOf({{#hasFormParams}}"Content-Type" to {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{MediaType}}"{{/consumes.0}}{{/hasFormParams}}{{^hasHeaderParams}}){{/hasHeaderParams}}{{#hasHeaderParams}}{{#hasFormParams}}, {{/hasFormParams}}{{#headerParams}}"{{baseName}}" to {{#isContainer}}{{paramName}}.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}{{paramName}}.toString(){{/isContainer}}{{#hasMore}}, {{/hasMore}}{{/headerParams}}){{/hasHeaderParams}}
val localVariableConfig = RequestConfig(
RequestMethod.{{httpMethod}},
"{{path}}"{{#pathParams}}.replace("{"+"{{baseName}}"+"}", "${{paramName}}"){{/pathParams}},

View File

@ -7,7 +7,7 @@ wrapper {
}
buildscript {
ext.kotlin_version = '1.3.20'
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
@ -32,7 +32,7 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "com.squareup.moshi:moshi-kotlin:1.5.0"
compile "com.squareup.moshi:moshi-adapters:1.5.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
compile "org.threeten:threetenbp:1.3.6"
compile "com.squareup.okhttp3:okhttp:3.14.0"
compile "org.threeten:threetenbp:1.3.8"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
}

View File

@ -3,9 +3,15 @@ package {{packageName}}.infrastructure
import com.squareup.moshi.FromJson
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import okhttp3.*
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.MediaType
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.ResponseBody
import okhttp3.Request
import java.io.File
import java.util.*
import java.util.UUID
open class ApiClient(val baseUrl: String) {
companion object {
@ -13,6 +19,7 @@ open class ApiClient(val baseUrl: String) {
protected const val Accept = "Accept"
protected const val JsonMediaType = "application/json"
protected const val FormDataMediaType = "multipart/form-data"
protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded"
protected const val XmlMediaType = "application/xml"
@JvmStatic
@ -22,38 +29,38 @@ open class ApiClient(val baseUrl: String) {
@JvmStatic
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
@JvmStatic
var defaultHeaders: Map<String, String> by ApplicationDelegates.setOnce(mapOf(ContentType to JsonMediaType, Accept to JsonMediaType))
@JvmStatic
val jsonHeaders: Map<String, String> = mapOf(ContentType to JsonMediaType, Accept to JsonMediaType)
}
protected inline fun <reified T> requestBody(content: T, mediaType: String = JsonMediaType): RequestBody =
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType || mediaType == FormUrlEncMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String = JsonMediaType): T? {
if(body == null) return null
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? {
if(body == null) {
return null
}
val bodyContent = body.string()
if (bodyContent.length == 0) {
return null
}
return when(mediaType) {
JsonMediaType -> Moshi.Builder().add(object {
@ToJson
@ -62,8 +69,8 @@ open class ApiClient(val baseUrl: String) {
fun fromJson(s: String) = UUID.fromString(s)
})
.add(ByteArrayAdapter())
.build().adapter(T::class.java).fromJson(body.source())
else -> TODO()
.build().adapter(T::class.java).fromJson(bodyContent)
else -> TODO("responseBody currently only supports JSON body.")
}
}
@ -80,7 +87,15 @@ open class ApiClient(val baseUrl: String) {
}
val url = urlBuilder.build()
val headers = requestConfig.headers + defaultHeaders
// take content-type/accept from spec or set to default (application/json) if not defined
if (requestConfig.headers[ContentType].isNullOrEmpty()) {
requestConfig.headers.put(ContentType, JsonMediaType)
}
if (requestConfig.headers[Accept].isNullOrEmpty()) {
requestConfig.headers.put(Accept, JsonMediaType)
}
val headers = requestConfig.headers
if(headers[ContentType] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Content-Type header. This is required.")
@ -90,9 +105,8 @@ open class ApiClient(val baseUrl: String) {
throw kotlin.IllegalStateException("Missing Accept header. This is required.")
}
// TODO: support multiple contentType,accept options here.
// TODO: support multiple contentType options here.
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val accept = (headers[Accept] as String).substringBefore(";").toLowerCase()
var request : Request.Builder = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
@ -108,6 +122,7 @@ open class ApiClient(val baseUrl: String) {
val realRequest = request.build()
val response = client.newCall(realRequest).execute()
val accept = response.header(ContentType)?.substringBefore(";")?.toLowerCase()
// TODO: handle specific mapping types. e.g. Map<int, Class<?>>
when {

View File

@ -11,6 +11,6 @@ package {{packageName}}.infrastructure
data class RequestConfig(
val method: RequestMethod,
val path: String,
val headers: Map<String, String> = mapOf(),
val headers: MutableMap<String, String> = mutableMapOf(),
val query: Map<String, List<String>> = mapOf()
)

View File

@ -2,8 +2,15 @@ package {{packageName}}.infrastructure
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.auth.*
import io.ktor.http.auth.*
import io.ktor.auth.Authentication
import io.ktor.auth.AuthenticationFailedCause
import io.ktor.auth.AuthenticationPipeline
import io.ktor.auth.AuthenticationProvider
import io.ktor.auth.Credential
import io.ktor.auth.Principal
import io.ktor.auth.UnauthorizedResponse
import io.ktor.http.auth.HeaderValueEncoding
import io.ktor.http.auth.HttpAuthHeader
import io.ktor.request.ApplicationRequest
import io.ktor.response.respond

View File

@ -1,29 +1,36 @@
package {{packageName}}
import com.codahale.metrics.*
import com.codahale.metrics.Slf4jReporter
import com.typesafe.config.ConfigFactory
import io.ktor.application.*
import io.ktor.application.Application
import io.ktor.application.ApplicationStopping
import io.ktor.application.install
import io.ktor.application.log
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.config.HoconApplicationConfig
import io.ktor.features.*
import io.ktor.features.AutoHeadResponse
import io.ktor.features.Compression
import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders
import io.ktor.features.HSTS
import io.ktor.gson.GsonConverter
import io.ktor.http.ContentType
import io.ktor.locations.*
import io.ktor.metrics.*
import io.ktor.routing.*
import java.util.concurrent.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Locations
import io.ktor.metrics.Metrics
import io.ktor.routing.Routing
import java.util.concurrent.TimeUnit
{{#hasAuthMethods}}
import io.ktor.auth.*
import io.ktor.auth.Authentication
import io.ktor.auth.oauth
import io.ktor.util.KtorExperimentalAPI
import org.openapitools.server.infrastructure.*
import org.openapitools.server.infrastructure.ApiKeyCredential
import org.openapitools.server.infrastructure.ApiPrincipal
import org.openapitools.server.infrastructure.apiKeyAuth
{{/hasAuthMethods}}
{{#generateApis}}
import {{apiPackage}}.*
{{/generateApis}}
{{#imports}}import {{import}}
{{/imports}}
{{#generateApis}}{{#apiInfo}}{{#apis}}import {{apiPackage}}.{{classname}}
{{/apis}}{{/apiInfo}}{{/generateApis}}
@KtorExperimentalAPI
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))

View File

@ -2,8 +2,12 @@ package {{packageName}}
// Use this file to hold package-level internal functions that return receiver object passed to the `install` method.
import io.ktor.auth.OAuthServerSettings
import io.ktor.features.*
import io.ktor.http.*
import io.ktor.features.Compression
import io.ktor.features.HSTS
import io.ktor.features.deflate
import io.ktor.features.gzip
import io.ktor.features.minimumSize
import io.ktor.http.HttpMethod
import io.ktor.util.KtorExperimentalAPI
import java.time.Duration
import java.util.concurrent.Executors

View File

@ -1,11 +1,9 @@
{{>licenseInfo}}
package {{packageName}}
import io.ktor.locations.*
import {{modelPackage}}.*
{{#imports}}
import {{import}}
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
{{#imports}}import {{import}}
{{/imports}}
{{#apiInfo}}

View File

@ -10,10 +10,15 @@ import io.ktor.auth.OAuthAccessTokenResponse
import io.ktor.auth.OAuthServerSettings
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.locations.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.delete
import io.ktor.locations.get
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.*
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.routing.put
import io.ktor.routing.route
import {{packageName}}.Paths
import {{packageName}}.infrastructure.ApiPrincipal

View File

@ -3,7 +3,13 @@ package {{package}}
{{#imports}}import {{import}}
{{/imports}}
{{#swaggerAnnotations}}
import io.swagger.annotations.*
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import io.swagger.annotations.ApiResponse
import io.swagger.annotations.ApiResponses
import io.swagger.annotations.Authorization
import io.swagger.annotations.AuthorizationScope
{{/swaggerAnnotations}}
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
@ -24,7 +30,13 @@ import org.springframework.beans.factory.annotation.Autowired
{{#useBeanValidation}}
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
{{/useBeanValidation}}
import kotlin.collections.List

View File

@ -4,8 +4,13 @@ import java.util.Objects
{{#imports}}import {{import}}
{{/imports}}
{{#useBeanValidation}}
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
{{/useBeanValidation}}
{{#swaggerAnnotations}}
import io.swagger.annotations.ApiModelProperty

View File

@ -2,7 +2,7 @@
## Requires
* Kotlin 1.3.20
* Kotlin 1.3.31
* Gradle 4.9
## Build

View File

@ -7,7 +7,7 @@ wrapper {
}
buildscript {
ext.kotlin_version = '1.3.20'
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
@ -32,7 +32,7 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "com.squareup.moshi:moshi-kotlin:1.5.0"
compile "com.squareup.moshi:moshi-adapters:1.5.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
compile "org.threeten:threetenbp:1.3.6"
compile "com.squareup.okhttp3:okhttp:3.14.0"
compile "org.threeten:threetenbp:1.3.8"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
}

View File

@ -14,7 +14,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.ApiResponse
import org.openapitools.client.models.Pet
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -27,7 +37,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun addPet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet",
@ -58,7 +68,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("api_key" to apiKey.toString())
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("api_key" to apiKey.toString())
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -89,7 +99,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByStatus(status: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("status" to toMultiValue(status.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByStatus",
@ -120,7 +130,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByTags(tags: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("tags" to toMultiValue(tags.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByTags",
@ -151,7 +161,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun getPetById(petId: kotlin.Long) : Pet {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -181,7 +191,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/pet",
@ -213,7 +223,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePetWithForm(petId: kotlin.Long, name: kotlin.String?, status: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = mapOf("name" to "$name", "status" to "$status")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -246,7 +256,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: java.io.File?) : ApiResponse {
val localVariableBody: kotlin.Any? = mapOf("additionalMetadata" to "$additionalMetadata", "file" to "$file")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}/uploadImage".replace("{"+"petId"+"}", "$petId"),

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.Order
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -26,7 +36,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun deleteOrder(orderId: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -56,7 +66,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getInventory() : kotlin.collections.Map<kotlin.String, kotlin.Int> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/inventory",
@ -87,7 +97,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getOrderById(orderId: kotlin.Long) : Order {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -118,7 +128,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun placeOrder(body: Order) : Order {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/store/order",

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.User
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -26,7 +36,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUser(body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user",
@ -56,7 +66,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithArrayInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithArray",
@ -86,7 +96,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithListInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithList",
@ -116,7 +126,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun deleteUser(username: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -147,7 +157,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun getUserByName(username: kotlin.String) : User {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -179,7 +189,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun loginUser(username: kotlin.String, password: kotlin.String) : kotlin.String {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("username" to listOf("$username"), "password" to listOf("$password"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/login",
@ -208,7 +218,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun logoutUser() : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/logout",
@ -239,7 +249,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun updateUser(username: kotlin.String, body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/user/{username}".replace("{"+"username"+"}", "$username"),

View File

@ -3,9 +3,15 @@ package org.openapitools.client.infrastructure
import com.squareup.moshi.FromJson
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import okhttp3.*
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.MediaType
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.ResponseBody
import okhttp3.Request
import java.io.File
import java.util.*
import java.util.UUID
open class ApiClient(val baseUrl: String) {
companion object {
@ -13,6 +19,7 @@ open class ApiClient(val baseUrl: String) {
protected const val Accept = "Accept"
protected const val JsonMediaType = "application/json"
protected const val FormDataMediaType = "multipart/form-data"
protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded"
protected const val XmlMediaType = "application/xml"
@JvmStatic
@ -22,38 +29,38 @@ open class ApiClient(val baseUrl: String) {
@JvmStatic
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
@JvmStatic
var defaultHeaders: Map<String, String> by ApplicationDelegates.setOnce(mapOf(ContentType to JsonMediaType, Accept to JsonMediaType))
@JvmStatic
val jsonHeaders: Map<String, String> = mapOf(ContentType to JsonMediaType, Accept to JsonMediaType)
}
protected inline fun <reified T> requestBody(content: T, mediaType: String = JsonMediaType): RequestBody =
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType || mediaType == FormUrlEncMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String = JsonMediaType): T? {
if(body == null) return null
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? {
if(body == null) {
return null
}
val bodyContent = body.string()
if (bodyContent.length == 0) {
return null
}
return when(mediaType) {
JsonMediaType -> Moshi.Builder().add(object {
@ToJson
@ -62,8 +69,8 @@ open class ApiClient(val baseUrl: String) {
fun fromJson(s: String) = UUID.fromString(s)
})
.add(ByteArrayAdapter())
.build().adapter(T::class.java).fromJson(body.source())
else -> TODO()
.build().adapter(T::class.java).fromJson(bodyContent)
else -> TODO("responseBody currently only supports JSON body.")
}
}
@ -80,7 +87,15 @@ open class ApiClient(val baseUrl: String) {
}
val url = urlBuilder.build()
val headers = requestConfig.headers + defaultHeaders
// take content-type/accept from spec or set to default (application/json) if not defined
if (requestConfig.headers[ContentType].isNullOrEmpty()) {
requestConfig.headers.put(ContentType, JsonMediaType)
}
if (requestConfig.headers[Accept].isNullOrEmpty()) {
requestConfig.headers.put(Accept, JsonMediaType)
}
val headers = requestConfig.headers
if(headers[ContentType] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Content-Type header. This is required.")
@ -90,9 +105,8 @@ open class ApiClient(val baseUrl: String) {
throw kotlin.IllegalStateException("Missing Accept header. This is required.")
}
// TODO: support multiple contentType,accept options here.
// TODO: support multiple contentType options here.
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val accept = (headers[Accept] as String).substringBefore(";").toLowerCase()
var request : Request.Builder = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
@ -108,6 +122,7 @@ open class ApiClient(val baseUrl: String) {
val realRequest = request.build()
val response = client.newCall(realRequest).execute()
val accept = response.header(ContentType)?.substringBefore(";")?.toLowerCase()
// TODO: handle specific mapping types. e.g. Map<int, Class<?>>
when {

View File

@ -11,6 +11,6 @@ package org.openapitools.client.infrastructure
data class RequestConfig(
val method: RequestMethod,
val path: String,
val headers: Map<String, String> = mapOf(),
val headers: MutableMap<String, String> = mutableMapOf(),
val query: Map<String, List<String>> = mapOf()
)

View File

@ -2,7 +2,7 @@
## Requires
* Kotlin 1.3.20
* Kotlin 1.3.31
* Gradle 4.9
## Build

View File

@ -7,7 +7,7 @@ wrapper {
}
buildscript {
ext.kotlin_version = '1.3.20'
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
@ -32,7 +32,7 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "com.squareup.moshi:moshi-kotlin:1.5.0"
compile "com.squareup.moshi:moshi-adapters:1.5.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
compile "org.threeten:threetenbp:1.3.6"
compile "com.squareup.okhttp3:okhttp:3.14.0"
compile "org.threeten:threetenbp:1.3.8"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
}

View File

@ -14,7 +14,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.ApiResponse
import org.openapitools.client.models.Pet
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
import org.threeten.bp.LocalDateTime
class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -28,7 +38,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun addPet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet",
@ -59,7 +69,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("api_key" to apiKey.toString())
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("api_key" to apiKey.toString())
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -90,7 +100,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByStatus(status: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("status" to toMultiValue(status.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByStatus",
@ -121,7 +131,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByTags(tags: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("tags" to toMultiValue(tags.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByTags",
@ -152,7 +162,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun getPetById(petId: kotlin.Long) : Pet {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -182,7 +192,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/pet",
@ -214,7 +224,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePetWithForm(petId: kotlin.Long, name: kotlin.String?, status: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = mapOf("name" to "$name", "status" to "$status")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -247,7 +257,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: java.io.File?) : ApiResponse {
val localVariableBody: kotlin.Any? = mapOf("additionalMetadata" to "$additionalMetadata", "file" to "$file")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}/uploadImage".replace("{"+"petId"+"}", "$petId"),

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.Order
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
import org.threeten.bp.LocalDateTime
class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -27,7 +37,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun deleteOrder(orderId: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -57,7 +67,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getInventory() : kotlin.collections.Map<kotlin.String, kotlin.Int> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/inventory",
@ -88,7 +98,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getOrderById(orderId: kotlin.Long) : Order {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -119,7 +129,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun placeOrder(body: Order) : Order {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/store/order",

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.User
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
import org.threeten.bp.LocalDateTime
class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -27,7 +37,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUser(body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user",
@ -57,7 +67,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithArrayInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithArray",
@ -87,7 +97,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithListInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithList",
@ -117,7 +127,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun deleteUser(username: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -148,7 +158,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun getUserByName(username: kotlin.String) : User {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -180,7 +190,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun loginUser(username: kotlin.String, password: kotlin.String) : kotlin.String {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("username" to listOf("$username"), "password" to listOf("$password"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/login",
@ -209,7 +219,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun logoutUser() : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/logout",
@ -240,7 +250,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun updateUser(username: kotlin.String, body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/user/{username}".replace("{"+"username"+"}", "$username"),

View File

@ -3,9 +3,15 @@ package org.openapitools.client.infrastructure
import com.squareup.moshi.FromJson
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import okhttp3.*
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.MediaType
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.ResponseBody
import okhttp3.Request
import java.io.File
import java.util.*
import java.util.UUID
open class ApiClient(val baseUrl: String) {
companion object {
@ -13,6 +19,7 @@ open class ApiClient(val baseUrl: String) {
protected const val Accept = "Accept"
protected const val JsonMediaType = "application/json"
protected const val FormDataMediaType = "multipart/form-data"
protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded"
protected const val XmlMediaType = "application/xml"
@JvmStatic
@ -22,38 +29,38 @@ open class ApiClient(val baseUrl: String) {
@JvmStatic
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
@JvmStatic
var defaultHeaders: Map<String, String> by ApplicationDelegates.setOnce(mapOf(ContentType to JsonMediaType, Accept to JsonMediaType))
@JvmStatic
val jsonHeaders: Map<String, String> = mapOf(ContentType to JsonMediaType, Accept to JsonMediaType)
}
protected inline fun <reified T> requestBody(content: T, mediaType: String = JsonMediaType): RequestBody =
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType || mediaType == FormUrlEncMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String = JsonMediaType): T? {
if(body == null) return null
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? {
if(body == null) {
return null
}
val bodyContent = body.string()
if (bodyContent.length == 0) {
return null
}
return when(mediaType) {
JsonMediaType -> Moshi.Builder().add(object {
@ToJson
@ -62,8 +69,8 @@ open class ApiClient(val baseUrl: String) {
fun fromJson(s: String) = UUID.fromString(s)
})
.add(ByteArrayAdapter())
.build().adapter(T::class.java).fromJson(body.source())
else -> TODO()
.build().adapter(T::class.java).fromJson(bodyContent)
else -> TODO("responseBody currently only supports JSON body.")
}
}
@ -80,7 +87,15 @@ open class ApiClient(val baseUrl: String) {
}
val url = urlBuilder.build()
val headers = requestConfig.headers + defaultHeaders
// take content-type/accept from spec or set to default (application/json) if not defined
if (requestConfig.headers[ContentType].isNullOrEmpty()) {
requestConfig.headers.put(ContentType, JsonMediaType)
}
if (requestConfig.headers[Accept].isNullOrEmpty()) {
requestConfig.headers.put(Accept, JsonMediaType)
}
val headers = requestConfig.headers
if(headers[ContentType] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Content-Type header. This is required.")
@ -90,9 +105,8 @@ open class ApiClient(val baseUrl: String) {
throw kotlin.IllegalStateException("Missing Accept header. This is required.")
}
// TODO: support multiple contentType,accept options here.
// TODO: support multiple contentType options here.
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val accept = (headers[Accept] as String).substringBefore(";").toLowerCase()
var request : Request.Builder = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
@ -108,6 +122,7 @@ open class ApiClient(val baseUrl: String) {
val realRequest = request.build()
val response = client.newCall(realRequest).execute()
val accept = response.header(ContentType)?.substringBefore(";")?.toLowerCase()
// TODO: handle specific mapping types. e.g. Map<int, Class<?>>
when {

View File

@ -11,6 +11,6 @@ package org.openapitools.client.infrastructure
data class RequestConfig(
val method: RequestMethod,
val path: String,
val headers: Map<String, String> = mapOf(),
val headers: MutableMap<String, String> = mutableMapOf(),
val query: Map<String, List<String>> = mapOf()
)

View File

@ -2,7 +2,7 @@
## Requires
* Kotlin 1.3.20
* Kotlin 1.3.31
* Gradle 4.9
## Build

View File

@ -7,7 +7,7 @@ wrapper {
}
buildscript {
ext.kotlin_version = '1.3.20'
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
@ -32,7 +32,7 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
compile "com.squareup.moshi:moshi-kotlin:1.5.0"
compile "com.squareup.moshi:moshi-adapters:1.5.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"
compile "org.threeten:threetenbp:1.3.6"
compile "com.squareup.okhttp3:okhttp:3.14.0"
compile "org.threeten:threetenbp:1.3.8"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.1.0"
}

View File

@ -14,7 +14,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.ApiResponse
import org.openapitools.client.models.Pet
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -27,7 +37,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun addPet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet",
@ -58,7 +68,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun deletePet(petId: kotlin.Long, apiKey: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("api_key" to apiKey.toString())
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("api_key" to apiKey.toString())
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -89,7 +99,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByStatus(status: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("status" to toMultiValue(status.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByStatus",
@ -120,7 +130,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun findPetsByTags(tags: kotlin.Array<kotlin.String>) : kotlin.Array<Pet> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("tags" to toMultiValue(tags.toList(), "csv"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/findByTags",
@ -151,7 +161,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun getPetById(petId: kotlin.Long) : Pet {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -181,7 +191,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePet(body: Pet) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/pet",
@ -213,7 +223,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun updatePetWithForm(petId: kotlin.Long, name: kotlin.String?, status: kotlin.String?) : Unit {
val localVariableBody: kotlin.Any? = mapOf("name" to "$name", "status" to "$status")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}".replace("{"+"petId"+"}", "$petId"),
@ -246,7 +256,7 @@ class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCli
fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: java.io.File?) : ApiResponse {
val localVariableBody: kotlin.Any? = mapOf("additionalMetadata" to "$additionalMetadata", "file" to "$file")
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf("Content-Type" to "multipart/form-data")
val localVariableHeaders: MutableMap<String, String> = mutableMapOf("Content-Type" to "")
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/pet/{petId}/uploadImage".replace("{"+"petId"+"}", "$petId"),

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.Order
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -26,7 +36,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun deleteOrder(orderId: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -56,7 +66,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getInventory() : kotlin.collections.Map<kotlin.String, kotlin.Int> {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/inventory",
@ -87,7 +97,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun getOrderById(orderId: kotlin.Long) : Order {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"),
@ -118,7 +128,7 @@ class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiC
fun placeOrder(body: Order) : Order {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/store/order",

View File

@ -13,7 +13,17 @@ package org.openapitools.client.apis
import org.openapitools.client.models.User
import org.openapitools.client.infrastructure.*
import org.openapitools.client.infrastructure.ApiClient
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.infrastructure.ClientError
import org.openapitools.client.infrastructure.ServerException
import org.openapitools.client.infrastructure.ServerError
import org.openapitools.client.infrastructure.MultiValueMap
import org.openapitools.client.infrastructure.RequestConfig
import org.openapitools.client.infrastructure.RequestMethod
import org.openapitools.client.infrastructure.ResponseType
import org.openapitools.client.infrastructure.Success
import org.openapitools.client.infrastructure.toMultiValue
class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) {
@ -26,7 +36,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUser(body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user",
@ -56,7 +66,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithArrayInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithArray",
@ -86,7 +96,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun createUsersWithListInput(body: kotlin.Array<User>) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/user/createWithList",
@ -116,7 +126,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun deleteUser(username: kotlin.String) : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -147,7 +157,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun getUserByName(username: kotlin.String) : User {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/{username}".replace("{"+"username"+"}", "$username"),
@ -179,7 +189,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun loginUser(username: kotlin.String, password: kotlin.String) : kotlin.String {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf("username" to listOf("$username"), "password" to listOf("$password"))
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/login",
@ -208,7 +218,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun logoutUser() : Unit {
val localVariableBody: kotlin.Any? = null
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/user/logout",
@ -239,7 +249,7 @@ class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiCl
fun updateUser(username: kotlin.String, body: User) : Unit {
val localVariableBody: kotlin.Any? = body
val localVariableQuery: MultiValueMap = mapOf()
val localVariableHeaders: kotlin.collections.Map<kotlin.String,kotlin.String> = mapOf()
val localVariableHeaders: MutableMap<String, String> = mutableMapOf()
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/user/{username}".replace("{"+"username"+"}", "$username"),

View File

@ -3,9 +3,15 @@ package org.openapitools.client.infrastructure
import com.squareup.moshi.FromJson
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import okhttp3.*
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.MediaType
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.ResponseBody
import okhttp3.Request
import java.io.File
import java.util.*
import java.util.UUID
open class ApiClient(val baseUrl: String) {
companion object {
@ -13,6 +19,7 @@ open class ApiClient(val baseUrl: String) {
protected const val Accept = "Accept"
protected const val JsonMediaType = "application/json"
protected const val FormDataMediaType = "multipart/form-data"
protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded"
protected const val XmlMediaType = "application/xml"
@JvmStatic
@ -22,38 +29,38 @@ open class ApiClient(val baseUrl: String) {
@JvmStatic
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
@JvmStatic
var defaultHeaders: Map<String, String> by ApplicationDelegates.setOnce(mapOf(ContentType to JsonMediaType, Accept to JsonMediaType))
@JvmStatic
val jsonHeaders: Map<String, String> = mapOf(ContentType to JsonMediaType, Accept to JsonMediaType)
}
protected inline fun <reified T> requestBody(content: T, mediaType: String = JsonMediaType): RequestBody =
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
when {
content is File -> RequestBody.create(
MediaType.parse(mediaType), content
)
mediaType == FormDataMediaType || mediaType == FormUrlEncMediaType -> {
var builder = FormBody.Builder()
// content's type *must* be Map<String, Any>
@Suppress("UNCHECKED_CAST")
(content as Map<String,String>).forEach { key, value ->
builder = builder.add(key, value)
}
builder.build()
}
mediaType == JsonMediaType -> RequestBody.create(
MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content)
)
mediaType == XmlMediaType -> TODO("xml not currently supported.")
// TODO: this should be extended with other serializers
else -> TODO("requestBody currently only supports JSON body and File body.")
}
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String = JsonMediaType): T? {
if(body == null) return null
protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? {
if(body == null) {
return null
}
val bodyContent = body.string()
if (bodyContent.length == 0) {
return null
}
return when(mediaType) {
JsonMediaType -> Moshi.Builder().add(object {
@ToJson
@ -62,8 +69,8 @@ open class ApiClient(val baseUrl: String) {
fun fromJson(s: String) = UUID.fromString(s)
})
.add(ByteArrayAdapter())
.build().adapter(T::class.java).fromJson(body.source())
else -> TODO()
.build().adapter(T::class.java).fromJson(bodyContent)
else -> TODO("responseBody currently only supports JSON body.")
}
}
@ -80,7 +87,15 @@ open class ApiClient(val baseUrl: String) {
}
val url = urlBuilder.build()
val headers = requestConfig.headers + defaultHeaders
// take content-type/accept from spec or set to default (application/json) if not defined
if (requestConfig.headers[ContentType].isNullOrEmpty()) {
requestConfig.headers.put(ContentType, JsonMediaType)
}
if (requestConfig.headers[Accept].isNullOrEmpty()) {
requestConfig.headers.put(Accept, JsonMediaType)
}
val headers = requestConfig.headers
if(headers[ContentType] ?: "" == "") {
throw kotlin.IllegalStateException("Missing Content-Type header. This is required.")
@ -90,9 +105,8 @@ open class ApiClient(val baseUrl: String) {
throw kotlin.IllegalStateException("Missing Accept header. This is required.")
}
// TODO: support multiple contentType,accept options here.
// TODO: support multiple contentType options here.
val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase()
val accept = (headers[Accept] as String).substringBefore(";").toLowerCase()
var request : Request.Builder = when (requestConfig.method) {
RequestMethod.DELETE -> Request.Builder().url(url).delete()
@ -108,6 +122,7 @@ open class ApiClient(val baseUrl: String) {
val realRequest = request.build()
val response = client.newCall(realRequest).execute()
val accept = response.header(ContentType)?.substringBefore(";")?.toLowerCase()
// TODO: handle specific mapping types. e.g. Map<int, Class<?>>
when {

View File

@ -11,6 +11,6 @@ package org.openapitools.client.infrastructure
data class RequestConfig(
val method: RequestMethod,
val path: String,
val headers: Map<String, String> = mapOf(),
val headers: MutableMap<String, String> = mutableMapOf(),
val query: Map<String, List<String>> = mapOf()
)

View File

@ -2,8 +2,11 @@ package org.openapitools.client
import io.kotlintest.shouldBe
import io.kotlintest.matchers.numerics.shouldBeGreaterThan
import io.kotlintest.matchers.string.shouldContain
import io.kotlintest.shouldThrow
import io.kotlintest.specs.ShouldSpec
import org.openapitools.client.apis.PetApi
import org.openapitools.client.infrastructure.ClientException
import org.openapitools.client.models.Category
import org.openapitools.client.models.Pet
import org.openapitools.client.models.Tag
@ -11,8 +14,11 @@ import org.openapitools.client.models.Tag
class PetApiTest : ShouldSpec() {
init {
val petId:Long = 10006
val api = PetApi()
should("add a pet") {
val petId:Long = 10006
val pet = Pet(
id = petId,
name = "kotlin client test",
@ -20,15 +26,11 @@ class PetApiTest : ShouldSpec() {
category = Category(petId, "test kotlin category"),
tags = arrayOf(Tag(petId, "test kotlin tag"))
)
val api = PetApi()
api.addPet(pet)
}
should("get pet by id") {
val petId: Long = 10006
val api = PetApi()
val result = api.getPetById(petId)
result.id shouldBe (petId)
@ -42,7 +44,6 @@ class PetApiTest : ShouldSpec() {
}
should("find pet by status") {
val api = PetApi()
val result = api.findPetsByStatus(arrayOf("available"))
result.size.shouldBeGreaterThan(0)
@ -58,15 +59,12 @@ class PetApiTest : ShouldSpec() {
}
should("update a pet") {
val petId:Long = 10007
val pet = Pet(
id = petId,
name = "kotlin client updatePet",
status = Pet.Status.pending,
photoUrls = arrayOf("http://test_kotlin_unit_test.com")
)
val api = PetApi()
api.updatePet(pet)
// verify updated Pet
@ -77,14 +75,10 @@ class PetApiTest : ShouldSpec() {
}
//TODO the test fail cause client doesn't support other JSON contentType/Accept
/*
should("update a pet with form") {
val petId:Long = 10007
val name = "kotlin client updatePet with Form"
val status = "pending"
val api = PetApi()
api.updatePetWithForm(petId, name, status)
// verify updated Pet
@ -94,7 +88,16 @@ class PetApiTest : ShouldSpec() {
result.status shouldBe (Pet.Status.pending)
}
*/
should("delete a pet") {
api.deletePet(petId, "apiKey")
// verify updated Pet
val exception = shouldThrow<ClientException> {
api.getPetById(petId)
}
exception.message?.shouldContain("Pet not found")
}
}

View File

@ -1,22 +1,35 @@
package org.openapitools.server
import com.codahale.metrics.*
import com.codahale.metrics.Slf4jReporter
import com.typesafe.config.ConfigFactory
import io.ktor.application.*
import io.ktor.application.Application
import io.ktor.application.ApplicationStopping
import io.ktor.application.install
import io.ktor.application.log
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.config.HoconApplicationConfig
import io.ktor.features.*
import io.ktor.features.AutoHeadResponse
import io.ktor.features.Compression
import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders
import io.ktor.features.HSTS
import io.ktor.gson.GsonConverter
import io.ktor.http.ContentType
import io.ktor.locations.*
import io.ktor.metrics.*
import io.ktor.routing.*
import java.util.concurrent.*
import io.ktor.auth.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Locations
import io.ktor.metrics.Metrics
import io.ktor.routing.Routing
import java.util.concurrent.TimeUnit
import io.ktor.auth.Authentication
import io.ktor.auth.oauth
import io.ktor.util.KtorExperimentalAPI
import org.openapitools.server.infrastructure.*
import org.openapitools.server.apis.*
import org.openapitools.server.infrastructure.ApiKeyCredential
import org.openapitools.server.infrastructure.ApiPrincipal
import org.openapitools.server.infrastructure.apiKeyAuth
import org.openapitools.server.apis.PetApi
import org.openapitools.server.apis.StoreApi
import org.openapitools.server.apis.UserApi
@KtorExperimentalAPI

View File

@ -2,8 +2,12 @@ package org.openapitools.server
// Use this file to hold package-level internal functions that return receiver object passed to the `install` method.
import io.ktor.auth.OAuthServerSettings
import io.ktor.features.*
import io.ktor.http.*
import io.ktor.features.Compression
import io.ktor.features.HSTS
import io.ktor.features.deflate
import io.ktor.features.gzip
import io.ktor.features.minimumSize
import io.ktor.http.HttpMethod
import io.ktor.util.KtorExperimentalAPI
import java.time.Duration
import java.util.concurrent.Executors

View File

@ -11,9 +11,8 @@
*/
package org.openapitools.server
import io.ktor.locations.*
import org.openapitools.server.models.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
object Paths {
/**

View File

@ -20,10 +20,15 @@ import io.ktor.auth.OAuthAccessTokenResponse
import io.ktor.auth.OAuthServerSettings
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.locations.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.delete
import io.ktor.locations.get
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.*
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.routing.put
import io.ktor.routing.route
import org.openapitools.server.Paths
import org.openapitools.server.infrastructure.ApiPrincipal

View File

@ -20,10 +20,15 @@ import io.ktor.auth.OAuthAccessTokenResponse
import io.ktor.auth.OAuthServerSettings
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.locations.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.delete
import io.ktor.locations.get
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.*
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.routing.put
import io.ktor.routing.route
import org.openapitools.server.Paths
import org.openapitools.server.infrastructure.ApiPrincipal

View File

@ -20,10 +20,15 @@ import io.ktor.auth.OAuthAccessTokenResponse
import io.ktor.auth.OAuthServerSettings
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.locations.*
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.delete
import io.ktor.locations.get
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.*
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.routing.put
import io.ktor.routing.route
import org.openapitools.server.Paths
import org.openapitools.server.infrastructure.ApiPrincipal

View File

@ -2,8 +2,15 @@ package org.openapitools.server.infrastructure
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.auth.*
import io.ktor.http.auth.*
import io.ktor.auth.Authentication
import io.ktor.auth.AuthenticationFailedCause
import io.ktor.auth.AuthenticationPipeline
import io.ktor.auth.AuthenticationProvider
import io.ktor.auth.Credential
import io.ktor.auth.Principal
import io.ktor.auth.UnauthorizedResponse
import io.ktor.http.auth.HeaderValueEncoding
import io.ktor.http.auth.HttpAuthHeader
import io.ktor.request.ApplicationRequest
import io.ktor.response.respond

View File

@ -2,7 +2,13 @@ package org.openapitools.api
import org.openapitools.model.ModelApiResponse
import org.openapitools.model.Pet
import io.swagger.annotations.*
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import io.swagger.annotations.ApiResponse
import io.swagger.annotations.ApiResponses
import io.swagger.annotations.Authorization
import io.swagger.annotations.AuthorizationScope
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
@ -19,7 +25,13 @@ import org.springframework.web.context.request.NativeWebRequest
import org.springframework.beans.factory.annotation.Autowired
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import kotlin.collections.List
import kotlin.collections.Map

View File

@ -1,7 +1,13 @@
package org.openapitools.api
import org.openapitools.model.Order
import io.swagger.annotations.*
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import io.swagger.annotations.ApiResponse
import io.swagger.annotations.ApiResponses
import io.swagger.annotations.Authorization
import io.swagger.annotations.AuthorizationScope
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
@ -18,7 +24,13 @@ import org.springframework.web.context.request.NativeWebRequest
import org.springframework.beans.factory.annotation.Autowired
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import kotlin.collections.List
import kotlin.collections.Map

View File

@ -1,7 +1,13 @@
package org.openapitools.api
import org.openapitools.model.User
import io.swagger.annotations.*
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import io.swagger.annotations.ApiResponse
import io.swagger.annotations.ApiResponses
import io.swagger.annotations.Authorization
import io.swagger.annotations.AuthorizationScope
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
@ -18,7 +24,13 @@ import org.springframework.web.context.request.NativeWebRequest
import org.springframework.beans.factory.annotation.Autowired
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import kotlin.collections.List
import kotlin.collections.Map

View File

@ -2,8 +2,13 @@ package org.openapitools.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**

View File

@ -2,8 +2,13 @@ package org.openapitools.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**

View File

@ -3,8 +3,13 @@ package org.openapitools.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**

View File

@ -5,8 +5,13 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
import org.openapitools.model.Category
import org.openapitools.model.Tag
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**

View File

@ -2,8 +2,13 @@ package org.openapitools.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**

View File

@ -2,8 +2,13 @@ package org.openapitools.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import javax.validation.Valid
import javax.validation.constraints.*
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import io.swagger.annotations.ApiModelProperty
/**