From 21ad242cebeb02eb8bd1c995922e7f2023eb6ab1 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:09:41 +0100 Subject: [PATCH] [kotlin][client] fix temp file name and remove old deprecated jvm-okhttp3 (#19064) * [kotlin][client] fix temp file name and remove old deprecated jvm-okhttp3 * [kotlin][client] fix temp file name and remove old deprecated jvm-okhttp3 * [kotlin][client] fix temp file name and remove old deprecated jvm-okhttp3 --- .../kotlin-client/build.gradle.mustache | 3 - .../libraries/jvm-okhttp/api.mustache | 2 +- .../infrastructure/ApiClient.kt.mustache | 154 +++++++----------- .../ResponseExtensions.kt.mustache | 8 +- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 49 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/SerializerHelper.kt | 14 -- .../org/openapitools/client/models/Order.kt | 70 -------- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- .../client/infrastructure/ApiClient.kt | 47 +++++- 26 files changed, 926 insertions(+), 267 deletions(-) delete mode 100644 samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt delete mode 100644 samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/models/Order.kt diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache index e1baf52e574..1dfe6fd0636 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache @@ -155,9 +155,6 @@ dependencies { implementation "io.ktor:ktor-serialization-jackson:$ktor_version" {{/jackson}} {{/jvm-ktor}} - {{#jvm-okhttp3}} - implementation "com.squareup.okhttp3:okhttp:3.14.9" - {{/jvm-okhttp3}} {{#jvm-okhttp4}} implementation "com.squareup.okhttp3:okhttp:4.12.0" {{/jvm-okhttp4}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache index 9dd4f1664c4..3e3199c5804 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache @@ -243,6 +243,6 @@ import {{packageName}}.infrastructure.toMultiValue {{/operation}} private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = - HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments{{#jvm-okhttp3}}(){{/jvm-okhttp3}}[0] + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] } {{/operations}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache index 9eec195099c..7b691594659 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache @@ -5,36 +5,19 @@ import android.os.Build {{/supportAndroidApiLevel25AndBelow}} import okhttp3.OkHttpClient import okhttp3.RequestBody -{{#jvm-okhttp3}} -import okhttp3.MediaType -{{/jvm-okhttp3}} -{{#jvm-okhttp4}} import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody -{{/jvm-okhttp4}} import okhttp3.FormBody -{{#jvm-okhttp3}} -import okhttp3.HttpUrl -{{/jvm-okhttp3}} -{{#jvm-okhttp4}} import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -{{/jvm-okhttp4}} import okhttp3.ResponseBody -{{#jvm-okhttp4}} import okhttp3.MediaType.Companion.toMediaTypeOrNull -{{/jvm-okhttp4}} import okhttp3.Request import okhttp3.Headers -{{#jvm-okhttp4}} import okhttp3.Headers.Companion.toHeaders -{{/jvm-okhttp4}} import okhttp3.MultipartBody import okhttp3.Call import okhttp3.Callback import okhttp3.Response -{{#jvm-okhttp3}} -import okhttp3.internal.Util.EMPTY_REQUEST -{{/jvm-okhttp3}} import java.io.BufferedWriter import java.io.File import java.io.FileWriter @@ -48,6 +31,7 @@ import java.time.OffsetDateTime import java.time.OffsetTime {{/threetenbp}} import java.util.Locale +import java.util.regex.Pattern {{#useCoroutines}} import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -74,9 +58,7 @@ import com.fasterxml.jackson.core.type.TypeReference import com.squareup.moshi.adapter {{/moshi}} -{{#jvm-okhttp4}} -{{#nonPublicApi}}internal {{/nonPublicApi}} val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() -{{/jvm-okhttp4}} +{{#nonPublicApi}}internal {{/nonPublicApi}}val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() {{#nonPublicApi}}internal {{/nonPublicApi}}open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { {{#nonPublicApi}}internal {{/nonPublicApi}}companion object { @@ -118,12 +100,7 @@ import com.squareup.moshi.adapter protected inline fun requestBody(content: T, mediaType: String?): RequestBody = when { - {{#jvm-okhttp3}} - content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content) - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull()) - {{/jvm-okhttp4}} mediaType == FormDataMediaType -> MultipartBody.Builder() .setType(MultipartBody.FORM) @@ -134,35 +111,18 @@ import com.squareup.moshi.adapter if (part.body is File) { val partHeaders = part.headers.toMutableMap() + ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"") - {{#jvm-okhttp3}} - val fileMediaType = MediaType.parse(guessContentTypeFromFile(part.body)) - addPart( - Headers.of(partHeaders), - RequestBody.create(fileMediaType, part.body) - ) - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull() addPart( partHeaders.toHeaders(), part.body.asRequestBody(fileMediaType) ) - {{/jvm-okhttp4}} } else { val partHeaders = part.headers.toMutableMap() + ("Content-Disposition" to "form-data; name=\"$name\"") - {{#jvm-okhttp3}} - addPart( - Headers.of(partHeaders), - RequestBody.create(null, parameterToString(part.body)) - ) - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} addPart( partHeaders.toHeaders(), parameterToString(part.body).toRequestBody(null) ) - {{/jvm-okhttp4}} } } }.build() @@ -176,27 +136,6 @@ import com.squareup.moshi.adapter }.build() } mediaType == null || mediaType.startsWith("application/") && mediaType.endsWith("json") -> - {{#jvm-okhttp3}} - if (content == null) { - EMPTY_REQUEST - } else { - RequestBody.create( - {{#moshi}} - MediaType.parse(mediaType ?: JsonMediaType), Serializer.moshi.adapter(T::class.java).toJson(content) - {{/moshi}} - {{#gson}} - MediaType.parse(mediaType ?: JsonMediaType), Serializer.gson.toJson(content, T::class.java) - {{/gson}} - {{#jackson}} - MediaType.parse(mediaType ?: JsonMediaType), Serializer.jacksonObjectMapper.writeValueAsString(content) - {{/jackson}} - {{#kotlinx_serialization}} - MediaType.parse(mediaType ?: JsonMediaType), Serializer.kotlinxSerializationJson.encodeToString(content) - {{/kotlinx_serialization}} - ) - } - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} if (content == null) { EMPTY_REQUEST } else { @@ -214,15 +153,9 @@ import com.squareup.moshi.adapter {{/kotlinx_serialization}} .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull()) } - {{/jvm-okhttp4}} mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.") mediaType == OctetMediaType && content is ByteArray -> - {{#jvm-okhttp3}} - RequestBody.create(MediaType.parse(OctetMediaType), content) - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} content.toRequestBody(OctetMediaType.toMediaTypeOrNull()) - {{/jvm-okhttp4}} // TODO: this should be extended with other serializers else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } @@ -230,22 +163,60 @@ import com.squareup.moshi.adapter {{#moshi}} @OptIn(ExperimentalStdlibApi::class) {{/moshi}} - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + {{^supportAndroidApiLevel25AndBelow}} // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.{{packageName}}", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() {{/supportAndroidApiLevel25AndBelow}} {{#supportAndroidApiLevel25AndBelow}} val tempFile = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - java.nio.file.Files.createTempFile("tmp.net.medicineone.teleconsultationandroid.openapi.openapicommon", null).toFile() + java.nio.file.Files.createTempFile(prefix, suffix).toFile() } else { @Suppress("DEPRECATION") - createTempFile("tmp.net.medicineone.teleconsultationandroid.openapi.openapicommon", null) + createTempFile(prefix, suffix) } {{/supportAndroidApiLevel25AndBelow}} tempFile.deleteOnExit() @@ -337,12 +308,7 @@ import com.squareup.moshi.adapter {{/hasAuthMethods}} protected {{#useCoroutines}}suspend {{/useCoroutines}}inline fun request(requestConfig: RequestConfig): ApiResponse { - {{#jvm-okhttp3}} - val httpUrl = HttpUrl.parse(baseUrl) ?: throw IllegalStateException("baseUrl is invalid.") - {{/jvm-okhttp3}} - {{#jvm-okhttp4}} val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.") - {{/jvm-okhttp4}} {{#hasAuthMethods}} // take authMethod from operation @@ -416,30 +382,30 @@ import com.squareup.moshi.adapter return response.use { when { it.isRedirect -> Redirection( - it.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.headers{{#jvm-okhttp3}}(){{/jvm-okhttp3}}.toMultimap() + it.code, + it.headers.toMultimap() ) it.isInformational -> Informational( - it.message{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.headers{{#jvm-okhttp3}}(){{/jvm-okhttp3}}.toMultimap() + it.message, + it.code, + it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, accept), - it.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.headers{{#jvm-okhttp3}}(){{/jvm-okhttp3}}.toMultimap() + responseBody(it, accept), + it.code, + it.headers.toMultimap() ) it.isClientError -> ClientError( - it.message{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.body{{#jvm-okhttp3}}(){{/jvm-okhttp3}}?.string(), - it.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.headers{{#jvm-okhttp3}}(){{/jvm-okhttp3}}.toMultimap() + it.message, + it.body?.string(), + it.code, + it.headers.toMultimap() ) else -> ServerError( - it.message{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.body{{#jvm-okhttp3}}(){{/jvm-okhttp3}}?.string(), - it.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}}, - it.headers{{#jvm-okhttp3}}(){{/jvm-okhttp3}}.toMultimap() + it.message, + it.body?.string(), + it.code, + it.headers.toMultimap() ) } } diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ResponseExtensions.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ResponseExtensions.kt.mustache index d301ca6f23d..8bf8d157f6c 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ResponseExtensions.kt.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ResponseExtensions.kt.mustache @@ -5,20 +5,20 @@ import okhttp3.Response /** * Provides an extension to evaluation whether the response is a 1xx code */ -{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isInformational : Boolean get() = this.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}} in 100..199 +{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isInformational : Boolean get() = this.code in 100..199 /** * Provides an extension to evaluation whether the response is a 3xx code */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER") -{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isRedirect : Boolean get() = this.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}} in 300..399 +{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isRedirect : Boolean get() = this.code in 300..399 /** * Provides an extension to evaluation whether the response is a 4xx code */ -{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isClientError : Boolean get() = this.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}} in 400..499 +{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isClientError : Boolean get() = this.code in 400..499 /** * Provides an extension to evaluation whether the response is a 5xx (Standard) through 999 (non-standard) code */ -{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isServerError : Boolean get() = this.code{{#jvm-okhttp3}}(){{/jvm-okhttp3}} in 500..999 +{{#nonPublicApi}}internal {{/nonPublicApi}}val Response.isServerError : Boolean get() = this.code in 500..999 diff --git a/samples/client/others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/others/kotlin-jvm-okhttp-parameter-tests/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-allOff-discriminator/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-array-simple-string-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-bigdecimal-default-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-default-values-jvm-okhttp4/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-gson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-gson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 8c503760a9b..05ad9375514 100644 --- a/samples/client/petstore/kotlin-gson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-gson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.google.gson.reflect.TypeToken - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -119,14 +120,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -232,7 +271,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-jackson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-jackson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 07124201ed5..8d46482a93d 100644 --- a/samples/client/petstore/kotlin-jackson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-jackson/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.fasterxml.jackson.core.type.TypeReference - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -119,14 +120,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -232,7 +271,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 8bb8b3a658c..cb166a4d2bc 100644 --- a/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-json-request-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -27,10 +27,11 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -121,17 +122,55 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + val tempFile = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - java.nio.file.Files.createTempFile("tmp.net.medicineone.teleconsultationandroid.openapi.openapicommon", null).toFile() + java.nio.file.Files.createTempFile(prefix, suffix).toFile() } else { @Suppress("DEPRECATION") - createTempFile("tmp.net.medicineone.teleconsultationandroid.openapi.openapicommon", null) + createTempFile(prefix, suffix) } tempFile.deleteOnExit() body.byteStream().use { inputStream -> @@ -238,7 +277,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index ad9b3e41d29..f738070af76 100644 --- a/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,12 +26,13 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlinx.coroutines.suspendCancellableCoroutine import com.google.gson.reflect.TypeToken - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -122,14 +123,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -246,7 +285,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-kotlinx-datetime/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-kotlinx-datetime/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin-kotlinx-datetime/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-kotlinx-datetime/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-modelMutable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-modelMutable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin-modelMutable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-modelMutable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-moshi-codegen/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-moshi-codegen/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin-moshi-codegen/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-moshi-codegen/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-name-parameter-mappings/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-name-parameter-mappings/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 077d6634a39..23d0c01273c 100644 --- a/samples/client/petstore/kotlin-name-parameter-mappings/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-name-parameter-mappings/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-nonpublic/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-nonpublic/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index a77cdda9077..856f97f4270 100644 --- a/samples/client/petstore/kotlin-nonpublic/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-nonpublic/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter -internal val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +internal val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() internal open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { internal companion object { @@ -120,14 +121,52 @@ internal open class ApiClient(val baseUrl: String, val client: OkHttpClient = de } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ internal open class ApiClient(val baseUrl: String, val client: OkHttpClient = de it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-nullable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-nullable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin-nullable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-nullable/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt b/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt deleted file mode 100644 index e39a6e70463..00000000000 --- a/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.openapitools.client.infrastructure - -import com.squareup.moshi.Moshi -import com.squareup.moshi.adapters.EnumJsonAdapter - -object SerializerHelper { - fun addEnumUnknownDefaultCase(moshiBuilder: Moshi.Builder): Moshi.Builder { - return moshiBuilder - .add(org.openapitools.client.models.Order.Status::class.java, EnumJsonAdapter.create(org.openapitools.client.models.Order.Status::class.java) - .withUnknownFallback(org.openapitools.client.models.Order.Status.unknown_default_open_api)) - .add(org.openapitools.client.models.Pet.Status::class.java, EnumJsonAdapter.create(org.openapitools.client.models.Pet.Status::class.java) - .withUnknownFallback(org.openapitools.client.models.Pet.Status.unknown_default_open_api)) - } -} diff --git a/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/models/Order.kt b/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/models/Order.kt deleted file mode 100644 index d706c19b9aa..00000000000 --- a/samples/client/petstore/kotlin-okhttp3/src/main/kotlin/org/openapitools/client/models/Order.kt +++ /dev/null @@ -1,70 +0,0 @@ -/** - * - * Please note: - * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * Do not edit this file manually. - * - */ - -@file:Suppress( - "ArrayInDataClass", - "EnumEntryName", - "RemoveRedundantQualifierName", - "UnusedImport" -) - -package org.openapitools.client.models - - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -/** - * An order for a pets from the pet store - * - * @param id - * @param petId - * @param quantity - * @param shipDate - * @param status Order Status - * @param complete - */ - - -data class Order ( - - @Json(name = "id") - val id: kotlin.Long? = null, - - @Json(name = "petId") - val petId: kotlin.Long? = null, - - @Json(name = "quantity") - val quantity: kotlin.Int? = null, - - @Json(name = "shipDate") - val shipDate: java.time.OffsetDateTime? = null, - - /* Order Status */ - @Json(name = "status") - val status: Order.Status? = null, - - @Json(name = "complete") - val complete: kotlin.Boolean? = false - -) { - - /** - * Order Status - * - * Values: placed,approved,delivered,unknown_default_open_api - */ - @JsonClass(generateAdapter = false) - enum class Status(val value: kotlin.String) { - @Json(name = "placed") placed("placed"), - @Json(name = "approved") approved("approved"), - @Json(name = "delivered") delivered("delivered"), - @Json(name = "unknown_default_open_api") unknown_default_open_api("unknown_default_open_api"); - } -} - diff --git a/samples/client/petstore/kotlin-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-string/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-threetenbp/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-threetenbp/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index dc40d76a0c4..13dcea71519 100644 --- a/samples/client/petstore/kotlin-threetenbp/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-threetenbp/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -21,6 +21,7 @@ import java.io.FileWriter import java.io.IOException import java.net.URLConnection import java.util.Locale +import java.util.regex.Pattern import org.threeten.bp.LocalDate import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalTime @@ -28,7 +29,7 @@ import org.threeten.bp.OffsetDateTime import org.threeten.bp.OffsetTime import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index 30c1e87163d..606cc8283d7 100644 --- a/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin-uppercase-enum/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,10 +26,11 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, byte body and File body.") } - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -214,7 +253,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() ) diff --git a/samples/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt index e27795a5c06..7ea62cf6f93 100644 --- a/samples/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +++ b/samples/client/petstore/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -26,9 +26,10 @@ import java.time.LocalTime import java.time.OffsetDateTime import java.time.OffsetTime import java.util.Locale +import java.util.regex.Pattern import com.squareup.moshi.adapter - val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { companion object { @@ -120,14 +121,52 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie } @OptIn(ExperimentalStdlibApi::class) - protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? { + val body = response.body if(body == null) { return null } if (T::class.java == File::class.java) { // return tempFile + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + // Get filename from the Content-Disposition header. + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length < 3) { + prefix = "download" + } + } + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options - val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() tempFile.deleteOnExit() body.byteStream().use { inputStream -> tempFile.outputStream().use { tempFileOutputStream -> @@ -233,7 +272,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie it.headers.toMultimap() ) it.isSuccessful -> Success( - responseBody(it.body, accept), + responseBody(it, accept), it.code, it.headers.toMultimap() )