Skip to content

Instantly share code, notes, and snippets.

@elizabetht
Created February 23, 2021 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elizabetht/93f251f8b4bc1f783dd292931f361357 to your computer and use it in GitHub Desktop.
Save elizabetht/93f251f8b4bc1f783dd292931f361357 to your computer and use it in GitHub Desktop.
OpenAPI contracts/routing
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package com.test.openapi
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.test.openapi.Jackson.auto
import org.http4k.contract.contract
import org.http4k.contract.div
import org.http4k.contract.meta
import org.http4k.contract.openapi.ApiInfo
import org.http4k.contract.openapi.v3.OpenApi3
import org.http4k.contract.openapi.v3.OpenApi3ApiRenderer
import org.http4k.contract.security.ApiKeySecurity
import org.http4k.core.Body
import org.http4k.core.Filter
import org.http4k.core.HttpHandler
import org.http4k.core.HttpTransaction
import org.http4k.core.Method
import org.http4k.core.Response
import org.http4k.core.Status.Companion.OK
import org.http4k.core.then
import org.http4k.core.with
import org.http4k.filter.CorsPolicy
import org.http4k.filter.ResponseFilters
import org.http4k.filter.ServerFilters
import org.http4k.format.ConfigurableJackson
import org.http4k.format.asConfigurable
import org.http4k.format.withStandardMappings
import org.http4k.lens.Path
import org.http4k.lens.Query
import org.http4k.lens.int
import org.http4k.routing.bind
import org.http4k.routing.routes
import org.http4k.server.Jetty
import org.http4k.server.asServer
import java.time.Clock
class App {
val greeting: String
get() {
return "Hello world."
}
}
object Jackson : ConfigurableJackson(
KotlinModule()
.asConfigurable()
.withStandardMappings()
.done()
.deactivateDefaultTyping()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
.configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, true)
)
data class SumResult(val sum: Int)
val sumResponseBody = Body.auto<SumResult>().toLens()
fun main(args: Array<String>) {
fun add(value1: Int, value2: Int): HttpHandler = {
Response(OK).with(
sumResponseBody of SumResult(value1 + value2)
)
}
val filter: Filter = ResponseFilters.ReportHttpTransaction(Clock.systemUTC()) { tx: HttpTransaction ->
println(tx.labels.toString() + " took " + tx.duration)
}
val mySecurity = ApiKeySecurity(Query.int().required("apiKey"), { it == 42 })
val contract = contract {
renderer = OpenApi3(ApiInfo("my great api", "v1.0"), Jackson, emptyList(), OpenApi3ApiRenderer(Jackson))
descriptionPath = "/docs/swagger.json"
security = mySecurity
routes += "/add" / Path.int().of("value1") / Path.int().of("value2") meta {
summary = "add"
description = "Adds 2 numbers together"
returning(OK, sumResponseBody to SumResult(55))
} bindContract Method.GET to ::add
}
val handler = routes(
"/context" bind filter.then(contract),
"/" bind contract {
renderer = OpenApi3(ApiInfo("my great super api", "v1.0"), Jackson, emptyList(), OpenApi3ApiRenderer(Jackson))
}
)
ServerFilters.Cors(CorsPolicy.UnsafeGlobalPermissive).then(handler).asServer(Jetty(8000)).start()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment