Skip to content

Commit

Permalink
Implement missing http verbs
Browse files Browse the repository at this point in the history
  • Loading branch information
Jens Zettelmeyer committed Nov 19, 2023
1 parent 88ec615 commit 9e12ce9
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.cjbooms.fabrikt.generators.client.ClientGeneratorUtils.simpleClientNa
import com.cjbooms.fabrikt.generators.client.ClientGeneratorUtils.toClientReturnType
import com.cjbooms.fabrikt.model.*
import com.cjbooms.fabrikt.util.KaizenParserExtensions.routeToPaths
import com.cjbooms.fabrikt.util.toUpperCase
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.javaparser.utils.CodeGenerationUtils
import com.reprezen.kaizen.oasparser.model3.Operation
Expand Down Expand Up @@ -129,15 +130,28 @@ data class SimpleJDKClientOperationStatement(
this.add("\nval requestBuilder: %T.Builder = HttpRequest.newBuilder()", "HttpRequest".toClassName(httpBasePackage))
this.add("\n.uri(httpUri)")

/*when (val op = verb.toUpperCase()) {
"PUT" -> this.addRequestSerializerStatement("put")
"POST" -> this.addRequestSerializerStatement("post")
"PATCH" -> this.addRequestSerializerStatement("patch")
"HEAD" -> this.add("\n.head()")
"GET" -> this.add("\n.get()")
"DELETE" -> this.add("\n.delete()")
when (val op = verb.toUpperCase()) {
"PUT" -> {
parameters.filterIsInstance<BodyParameter>().firstOrNull()?.let {
this.add("\n.PUT(Publishers.jsonBodyPublisher(%N))", it.name)
}
}
"POST" -> {
parameters.filterIsInstance<BodyParameter>().firstOrNull()?.let {
this.add("\n.POST(Publishers.jsonBodyPublisher(%N))", it.name)
}
}
"PATCH" -> {
parameters.filterIsInstance<BodyParameter>().firstOrNull()?.let {
this.add("\n.method(\"PATCH\", Publishers.jsonBodyPublisher(%N))", it.name)
}
}
"HEAD" -> this.add("\n.method(\"HEAD\", %T.noBody())", "BodyPublishers".toClassName("$httpBasePackage.HttpRequest"))
"GET" -> this.add("\n.GET()")
"DELETE" -> this.add("\n.DELETE()")
else -> throw NotImplementedError("API operation $op is not supported")
}*/
}

return this
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/resources/templates/jdk-client-code/http-util.kt.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package {{ client }}

import com.fasterxml.jackson.databind.ObjectMapper
import jdk.internal.net.http.RequestPublishers
import java.io.IOException
import java.io.InputStream
import java.io.UncheckedIOException
Expand Down Expand Up @@ -55,3 +56,10 @@ class JsonBodyHandler<W>(val wClass: Class<W>) : BodyHandler<Supplier<W>> {
return asJSON(wClass)
}
}

object Publishers {
fun <W> jsonBodyPublisher(obj: W) : HttpRequest.BodyPublisher {
val data = ObjectMapper().writeValueAsBytes(obj)
return RequestPublishers.ByteArrayPublisher(data)
}
}
32 changes: 31 additions & 1 deletion src/test/resources/examples/httpClient/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,22 @@ paths:
responses:
204:
description: "Operation successful"
delete:
summary: "DELETE example path 3"
response:
200:
description: "Operation successful"

/example-path-3/{path_param}/subresource/name:
patch:
summary: "PATCH example path 3"
parameters:
- $ref: "#/components/parameters/PathParam"
requestBody:
$ref: "#/components/requestBodies/PatchBody"
responses:
204:
description: "Operation successful"

components:
parameters:
Expand Down Expand Up @@ -224,7 +240,12 @@ components:
application/json:
schema:
$ref: "#/components/schemas/FirstModel"

PatchBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schema/FirstModelPatch"

schemas:
QueryResult:
Expand Down Expand Up @@ -290,11 +311,20 @@ components:
second_model: "#/components/schemas/SecondModel"
third_model: "#/components/schemas/ThirdModel"

FirstModelPatch:
- type: "object"
properties:
name:
description: "Same random name"
type: string
FirstModel:
allOf:
- $ref: "#/components/schemas/Content"
- type: "object"
properties:
name:
description: "Same random name"
type: string
extra_first_attr:
description: "The attribute 1 for model 1"
type: array
Expand Down
65 changes: 65 additions & 0 deletions src/test/resources/examples/httpClient/client/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.String
Expand Down Expand Up @@ -247,4 +248,68 @@ public class ExamplePath3SubresourceClient(

return request.execute(client, objectMapper, jacksonTypeRef())
}

/**
* DELETE example path 3
*/
@Throws(ApiException::class)
public fun deleteExamplePath3PathParamSubresource(
additionalHeaders: Map<String, String> =
emptyMap(),
): ApiResponse<Unit> {
val httpUrl: HttpUrl = "$baseUrl/example-path-3/{path_param}/subresource"
.toHttpUrl()
.newBuilder()
.build()

val headerBuilder = Headers.Builder()
additionalHeaders.forEach { headerBuilder.header(it.key, it.value) }
val httpHeaders: Headers = headerBuilder.build()

val request: Request = Request.Builder()
.url(httpUrl)
.headers(httpHeaders)
.delete()
.build()

return request.execute(client, objectMapper, jacksonTypeRef())
}
}

@Suppress("unused")
public class ExamplePath3SubresourceNameClient(
private val objectMapper: ObjectMapper,
private val baseUrl: String,
private val client: OkHttpClient,
) {
/**
* PATCH example path 3
*
* @param firstModelPatch
* @param pathParam The resource id
*/
@Throws(ApiException::class)
public fun patchExamplePath3PathParamSubresourceName(
firstModelPatch: Any,
pathParam: String,
additionalHeaders: Map<String, String> = emptyMap(),
): ApiResponse<Unit> {
val httpUrl: HttpUrl = "$baseUrl/example-path-3/{path_param}/subresource/name"
.pathParam("{path_param}" to pathParam)
.toHttpUrl()
.newBuilder()
.build()

val headerBuilder = Headers.Builder()
additionalHeaders.forEach { headerBuilder.header(it.key, it.value) }
val httpHeaders: Headers = headerBuilder.build()

val request: Request = Request.Builder()
.url(httpUrl)
.headers(httpHeaders)
.patch(objectMapper.writeValueAsString(firstModelPatch).toRequestBody("application/json".toMediaType()))
.build()

return request.execute(client, objectMapper, jacksonTypeRef())
}
}
41 changes: 41 additions & 0 deletions src/test/resources/examples/httpClient/client/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import examples.httpClient.models.FirstModel
import examples.httpClient.models.QueryResult
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry
import okhttp3.OkHttpClient
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.String
Expand Down Expand Up @@ -143,4 +144,44 @@ public class ExamplePath3SubresourceService(
withCircuitBreaker(circuitBreakerRegistry, circuitBreakerName) {
apiClient.putExamplePath3PathParamSubresource(firstModel, pathParam, ifMatch, csvListQueryParam, additionalHeaders)
}

@Throws(ApiException::class)
public fun deleteExamplePath3PathParamSubresource(
additionalHeaders: Map<String, String> =
emptyMap(),
): ApiResponse<Unit> =
withCircuitBreaker(circuitBreakerRegistry, circuitBreakerName) {
apiClient.deleteExamplePath3PathParamSubresource(additionalHeaders)
}
}

/**
* The circuit breaker registry should have the proper configuration to correctly action on circuit
* breaker transitions based on the client exceptions [ApiClientException], [ApiServerException] and
* [IOException].
*
* @see ApiClientException
* @see ApiServerException
*/
@Suppress("unused")
public class ExamplePath3SubresourceNameService(
private val circuitBreakerRegistry: CircuitBreakerRegistry,
objectMapper: ObjectMapper,
baseUrl: String,
client: OkHttpClient,
) {
public var circuitBreakerName: String = "examplePath3SubresourceNameClient"

private val apiClient: ExamplePath3SubresourceNameClient =
ExamplePath3SubresourceNameClient(objectMapper, baseUrl, client)

@Throws(ApiException::class)
public fun patchExamplePath3PathParamSubresourceName(
firstModelPatch: Any,
pathParam: String,
additionalHeaders: Map<String, String> = emptyMap(),
): ApiResponse<Unit> =
withCircuitBreaker(circuitBreakerRegistry, circuitBreakerName) {
apiClient.patchExamplePath3PathParamSubresourceName(firstModelPatch, pathParam, additionalHeaders)
}
}
51 changes: 51 additions & 0 deletions src/test/resources/examples/httpClient/client/jdk/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import examples.httpClient.jdk.models.QueryResult
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpRequest.BodyPublishers
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.String
Expand Down Expand Up @@ -37,6 +39,7 @@ public class ExamplePath1Client(
val httpUri: URI = URI.create("$baseUrl/example-path-1")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.GET()
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand All @@ -56,6 +59,7 @@ public class ExamplePath1Client(
val httpUri: URI = URI.create("$baseUrl/example-path-1")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.POST(Publishers.jsonBodyPublisher(content))
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand Down Expand Up @@ -86,6 +90,7 @@ public class ExamplePath2Client(
val httpUri: URI = URI.create("$baseUrl/example-path-2/{path_param}")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.GET()
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand All @@ -107,6 +112,7 @@ public class ExamplePath2Client(
val httpUri: URI = URI.create("$baseUrl/example-path-2/{path_param}")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.method("HEAD", BodyPublishers.noBody())
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand All @@ -128,6 +134,7 @@ public class ExamplePath2Client(
val httpUri: URI = URI.create("$baseUrl/example-path-2/{path_param}")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.PUT(Publishers.jsonBodyPublisher(firstModel))
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand Down Expand Up @@ -158,6 +165,50 @@ public class ExamplePath3SubresourceClient(
val httpUri: URI = URI.create("$baseUrl/example-path-3/{path_param}/subresource")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.PUT(Publishers.jsonBodyPublisher(firstModel))
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}

/**
* DELETE example path 3
*/
@Throws(ApiException::class)
public fun deleteExamplePath3PathParamSubresource(
additionalHeaders: Map<String, String> =
emptyMap(),
): ApiResponse<Unit> {
val httpUri: URI = URI.create("$baseUrl/example-path-3/{path_param}/subresource")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.DELETE()
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
}

@Suppress("unused")
public class ExamplePath3SubresourceNameClient(
private val objectMapper: ObjectMapper,
private val baseUrl: String,
private val client: HttpClient,
) {
/**
* PATCH example path 3
*
* @param firstModelPatch
* @param pathParam The resource id
*/
@Throws(ApiException::class)
public fun patchExamplePath3PathParamSubresourceName(
firstModelPatch: Any,
pathParam: String,
additionalHeaders: Map<String, String> = emptyMap(),
): ApiResponse<Unit> {
val httpUri: URI = URI.create("$baseUrl/example-path-3/{path_param}/subresource/name")
val requestBuilder: HttpRequest.Builder = HttpRequest.newBuilder()
.uri(httpUri)
.method("PATCH", Publishers.jsonBodyPublisher(firstModelPatch))
additionalHeaders.forEach { requestBuilder.header(it.key, it.value) }
return client.execute(requestBuilder.build())
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/resources/examples/httpClient/client/jdk/HttpUtil.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package examples.httpClient.jdk.client

import com.fasterxml.jackson.databind.ObjectMapper
import jdk.internal.net.http.RequestPublishers
import java.io.IOException
import java.io.InputStream
import java.io.UncheckedIOException
Expand Down Expand Up @@ -55,3 +56,10 @@ class JsonBodyHandler<W>(val wClass: Class<W>) : BodyHandler<Supplier<W>> {
return asJSON(wClass)
}
}

object Publishers {
fun <W> jsonBodyPublisher(obj: W) : HttpRequest.BodyPublisher {
val data = ObjectMapper().writeValueAsBytes(obj)
return RequestPublishers.ByteArrayPublisher(data)
}
}
3 changes: 3 additions & 0 deletions src/test/resources/examples/httpClient/models/Models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ public data class FirstModel(
@param:JsonProperty("etag")
@get:JsonProperty("etag")
override val etag: String? = null,
@param:JsonProperty("name")
@get:JsonProperty("name")
public val name: String? = null,
@param:JsonProperty("extra_first_attr")
@get:JsonProperty("extra_first_attr")
public val extraFirstAttr: List<String>? = null,
Expand Down
3 changes: 3 additions & 0 deletions src/test/resources/examples/httpClient/models/jdk/Models.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ public data class FirstModel(
@param:JsonProperty("etag")
@get:JsonProperty("etag")
override val etag: String? = null,
@param:JsonProperty("name")
@get:JsonProperty("name")
public val name: String? = null,
@param:JsonProperty("extra_first_attr")
@get:JsonProperty("extra_first_attr")
public val extraFirstAttr: List<String>? = null,
Expand Down
Loading

0 comments on commit 9e12ce9

Please sign in to comment.