Added OpenAPI doc page, as well as miscellaneous fixes

This commit is contained in:
Anthony Cicchetti 2019-08-29 18:50:15 -04:00
parent 02c29bfb1b
commit e75559e112
5 changed files with 101 additions and 16 deletions

View file

@ -19,6 +19,10 @@ dependencies {
implementation(Libs.javalin) implementation(Libs.javalin)
implementation(Libs.slf4j_simple) implementation(Libs.slf4j_simple)
implementation(Libs.jackson_databind) implementation(Libs.jackson_databind)
implementation(Libs.jackson_module_kotlin)
implementation(Libs.swagger_core)
implementation(Libs.kotlin_openapi3_dsl)
implementation(Libs.swagger_ui)
testImplementation(Libs.junit_jupiter) testImplementation(Libs.junit_jupiter)
} }

View file

@ -7,12 +7,24 @@ import kotlin.String
* `$ ./gradlew buildSrcVersions` * `$ ./gradlew buildSrcVersions`
*/ */
object Libs { object Libs {
/**
* https://github.com/derveloper/kotlin-openapi3-dsl
*/
const val kotlin_openapi3_dsl: String = "cc.vileda:kotlin-openapi3-dsl:" +
Versions.kotlin_openapi3_dsl
/** /**
* http://github.com/FasterXML/jackson * http://github.com/FasterXML/jackson
*/ */
const val jackson_databind: String = "com.fasterxml.jackson.core:jackson-databind:" + const val jackson_databind: String = "com.fasterxml.jackson.core:jackson-databind:" +
Versions.jackson_databind Versions.jackson_databind
/**
* https://github.com/FasterXML/jackson-module-kotlin
*/
const val jackson_module_kotlin: String = "com.fasterxml.jackson.module:jackson-module-kotlin:" +
Versions.jackson_module_kotlin
const val com_github_johnrengelman_shadow_gradle_plugin: String = const val com_github_johnrengelman_shadow_gradle_plugin: String =
"com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:" + "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:" +
Versions.com_github_johnrengelman_shadow_gradle_plugin Versions.com_github_johnrengelman_shadow_gradle_plugin
@ -26,6 +38,11 @@ object Libs {
*/ */
const val javalin: String = "io.javalin:javalin:" + Versions.javalin const val javalin: String = "io.javalin:javalin:" + Versions.javalin
/**
* https://github.com/swagger-api/swagger-core
*/
const val swagger_core: String = "io.swagger.core.v3:swagger-core:" + Versions.swagger_core
const val org_jetbrains_kotlin_jvm_gradle_plugin: String = const val org_jetbrains_kotlin_jvm_gradle_plugin: String =
"org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:" + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:" +
Versions.org_jetbrains_kotlin_jvm_gradle_plugin Versions.org_jetbrains_kotlin_jvm_gradle_plugin
@ -51,4 +68,9 @@ object Libs {
* http://www.slf4j.org * http://www.slf4j.org
*/ */
const val slf4j_simple: String = "org.slf4j:slf4j-simple:" + Versions.slf4j_simple const val slf4j_simple: String = "org.slf4j:slf4j-simple:" + Versions.slf4j_simple
/**
* http://webjars.org
*/
const val swagger_ui: String = "org.webjars:swagger-ui:" + Versions.swagger_ui
} }

View file

@ -12,14 +12,20 @@ import org.gradle.plugin.use.PluginDependencySpec
* YOU are responsible for updating manually the dependency version. * YOU are responsible for updating manually the dependency version.
*/ */
object Versions { object Versions {
const val kotlin_openapi3_dsl: String = "0.20.2"
const val jackson_databind: String = "2.10.0.pr1" const val jackson_databind: String = "2.10.0.pr1"
const val jackson_module_kotlin: String = "2.10.0.pr1"
const val com_github_johnrengelman_shadow_gradle_plugin: String = "5.1.0" const val com_github_johnrengelman_shadow_gradle_plugin: String = "5.1.0"
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.4.2" const val de_fayard_buildsrcversions_gradle_plugin: String = "0.4.2"
const val javalin: String = "3.4.1" const val javalin: String = "3.4.1"
const val swagger_core: String = "2.0.9"
const val org_jetbrains_kotlin_jvm_gradle_plugin: String = "1.3.50" const val org_jetbrains_kotlin_jvm_gradle_plugin: String = "1.3.50"
const val org_jetbrains_kotlin: String = "1.3.50" const val org_jetbrains_kotlin: String = "1.3.50"
@ -28,6 +34,8 @@ object Versions {
const val slf4j_simple: String = "1.7.28" const val slf4j_simple: String = "1.7.28"
const val swagger_ui: String = "3.23.5"
/** /**
* *
* See issue 19: How to update Gradle itself? * See issue 19: How to update Gradle itself?

View file

@ -5,30 +5,68 @@ import com.anthonycicchetti.slackbot.utility.RespObj
import com.anthonycicchetti.slackbot.utility.TextResponse import com.anthonycicchetti.slackbot.utility.TextResponse
import io.javalin.http.Context import io.javalin.http.Context
import io.javalin.Javalin import io.javalin.Javalin
import io.javalin.plugin.openapi.OpenApiOptions
import io.javalin.plugin.openapi.OpenApiPlugin
import io.javalin.plugin.openapi.dsl.document
import io.javalin.plugin.openapi.dsl.documented
import io.javalin.plugin.openapi.ui.SwaggerOptions
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.info.Info
import io.swagger.v3.oas.models.servers.Server
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import kotlin.math.roundToInt
fun main() { fun main() {
val logger = LoggerFactory.getLogger("main") val logger = LoggerFactory.getLogger("main")
val app = Javalin.create().start(7000) val app = Javalin.create { config ->
config.registerPlugin(OpenApiPlugin(createOpenApiOptions()))
config.enableCorsForAllOrigins()
config.requestLogger {ctx, ms ->
logger.info("Took ${ms.roundToInt()} to process ${ctx.req.requestURL}")
}
}.start(7000)
with(app) { with(app) {
get("/") { ctx -> ctx.result("Hello World") } options("/*", documented(document().ignore()) {})
get("/", documented(document().ignore()) { ctx -> ctx.result("Hello World") })
post("/slack/receive") { ctx -> post("/slack/receive", documented(document().operation {
it.description = "NOT DOCUMENTED. Required for slack usage"
it.summary = "NOT DOCUMENTED. Required for slack usage"
}.ignore()) { ctx ->
logger.info("Received request from ${ctx.req.requestURL}")
handleSlackEvent(ctx) handleSlackEvent(ctx)
} })
post("/api/v1/spongebob") { ctx -> post("/api/v1/spongebob", documented(document().operation {
it.description = "Responds with the ${"spongemocked".toSpongemock()} version of the string posted"
it.summary = "POST for ${"spongemocking".toSpongemock()}"
}.body<String>().json<TextResponse>("200")) { ctx ->
logger.info("Spongemock: Received request from ${ctx.req.requestURL}")
ctx.json(TextResponse(200, ctx.body().toSpongemock())) ctx.json(TextResponse(200, ctx.body().toSpongemock()))
} })
post("/api/v1/uppercase") { ctx -> post("/api/v1/uppercase", documented(document().operation {
it.description = "Responds with the UPPERCASED version of the string posted"
it.summary = "POST for UPPERCASING"
}.body<String>().json<TextResponse>("200")) { ctx ->
logger.info("Uppercase: Received request from ${ctx.req.requestURL}")
ctx.json(TextResponse(200, ctx.body().toUpperCase())) ctx.json(TextResponse(200, ctx.body().toUpperCase()))
} })
}
Runtime.getRuntime().addShutdownHook(Thread {
app.stop()
})
app.events { event ->
event.serverStopping { logger.info("Server stopping") }
event.serverStopped { logger.info("Server stopped") }
} }
} }
fun handleSlackEvent(ctx: Context) { private fun handleSlackEvent(ctx: Context) {
// Short circuit for ssl check // Short circuit for ssl check
if ((ctx.formParam("ssl_check") ?: "0") == "1") { if ((ctx.formParam("ssl_check") ?: "0") == "1") {
ctx.status(200) ctx.status(200)
@ -36,11 +74,11 @@ fun handleSlackEvent(ctx: Context) {
} }
val responseObj = RespObj( val responseObj = RespObj(
command = ctx.formParamMap().get("command")?.get(0).processToCommand(), command = ctx.formParamMap()["command"]?.get(0).processToCommand(),
text = ctx.formParamMap().get("text")?.get(0) ?: "", text = ctx.formParamMap()["text"]?.get(0) ?: "",
response_url = ctx.formParamMap().get("response_url")?.get(0) ?: "", response_url = ctx.formParamMap()["response_url"]?.get(0) ?: "",
team_id = ctx.formParamMap().get("team_id")?.get(0) ?: "", team_id = ctx.formParamMap()["team_id"]?.get(0) ?: "",
channel_id = ctx.formParamMap().get("channel_id")?.get(0) ?: "" channel_id = ctx.formParamMap()["channel_id"]?.get(0) ?: ""
) )
sendResponse(ctx, responseObj) sendResponse(ctx, responseObj)
@ -54,7 +92,7 @@ private fun String?.processToCommand(): Commands {
} }
} }
fun sendResponse(ctx: Context, respObj: RespObj) { private fun sendResponse(ctx: Context, respObj: RespObj) {
val returnMap = mutableMapOf<String, String>() val returnMap = mutableMapOf<String, String>()
with(returnMap) { with(returnMap) {
when (respObj.command) { when (respObj.command) {
@ -71,4 +109,17 @@ fun sendResponse(ctx: Context, respObj: RespObj) {
} }
ctx.json(returnMap) ctx.json(returnMap)
}
private fun createOpenApiOptions(): OpenApiOptions {
val o = {
OpenAPI()
.info(Info().version("0.1.2").description("Slackbot Open API documentation"))
.addServersItem(Server().url("https://acicchetti.dev/"))
.addServersItem(Server().url("http://localhost:7000/"))
}
return OpenApiOptions(o)
.path("/swagger-docs")
.swagger(SwaggerOptions("/swagger").title("Slackbot Swagger Docs"))
} }

View file

@ -1,3 +1,3 @@
package com.anthonycicchetti.slackbot.utility package com.anthonycicchetti.slackbot.utility
data class TextResponse(val status: Int, val response: String) data class TextResponse(val status: Int = 200, val response: String)