Skip to content

Commit

Permalink
fix bug: incorrect handling of rootHostPath
Browse files Browse the repository at this point in the history
  • Loading branch information
SMILEY4 committed Jan 13, 2024
1 parent 1cc0a31 commit e966f72
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 43 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.gitlab.arturbosch.detekt.Detekt
object Meta {
const val groupId = "io.github.smiley4"
const val artifactId = "ktor-swagger-ui"
const val version = "2.7.3"
const val version = "2.7.4"
const val name = "Ktor Swagger-UI"
const val description = "Ktor plugin to document routes and provide Swagger UI"
const val licenseName = "The Apache License, Version 2.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ class SwaggerController(
private fun Route.setup() {
route(getSubUrl()) {
get {
call.respondRedirect("${call.request.uri}/index.html")
val rootHostPath = if (pluginConfig.swaggerUI.rootHostPath.isNotBlank()) {
ControllerUtils.dropSlashes("/${pluginConfig.swaggerUI.rootHostPath}")
} else ""
call.respondRedirect("$rootHostPath${call.request.uri}/index.html")
}
get("{filename}") {
serveStaticResource(call.parameters["filename"]!!, call)
Expand Down Expand Up @@ -108,17 +111,17 @@ class SwaggerController(
}

private fun getRootUrl(appConfig: ApplicationConfig): String {
return "${ControllerUtils.getRootPath(appConfig)}${getSubUrl()}"
return "${ControllerUtils.getRootPath(appConfig)}${getSubUrl(true)}"
}

private fun getSubUrl(): String {
return "/" + listOf(
pluginConfig.swaggerUI.rootHostPath,
private fun getSubUrl(withRootHostPath: Boolean = false): String {
return "/" + listOfNotNull(
if (withRootHostPath) pluginConfig.swaggerUI.rootHostPath else null,
pluginConfig.swaggerUI.swaggerUrl,
specName
)
.filter { !it.isNullOrBlank() }
.map { ControllerUtils.dropSlashes(it!!) }
.filter { it.isNotBlank() }
.map { ControllerUtils.dropSlashes(it) }
.joinToString("/")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ import io.github.smiley4.ktorswaggerui.dsl.get
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotBeEmpty
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.contentType
import io.ktor.http.withCharset
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.auth.Authentication
import io.ktor.server.auth.UserIdPrincipal
import io.ktor.server.auth.basic
import io.ktor.server.response.respondText
import io.ktor.server.routing.routing
import io.ktor.server.testing.ApplicationTestBuilder
import io.ktor.server.testing.testApplication
import kotlin.test.Test

Expand Down Expand Up @@ -58,35 +57,36 @@ class ApplicationTests {


@Test
fun customRootHost() = swaggerUITestApplication({
swagger {
rootHostPath = "my-root"
}
}) {
fun customRootHost() = swaggerUITestApplication(
{
swagger {
rootHostPath = "my-root"
}
},
followRedirects = false,
) {
get("hello").also {
it.status shouldBe HttpStatusCode.OK
it.body shouldBe "Hello Test"
}
get("/").also {
it.status shouldBe HttpStatusCode.NotFound
}
get("my-root/swagger-ui").also {
it.status shouldBe HttpStatusCode.OK
it.contentType shouldBe ContentType.Text.Html
it.body.shouldNotBeEmpty()
get("swagger-ui").also {
it.status shouldBe HttpStatusCode.Found
it.redirect shouldBe "my-root/swagger-ui/index.html"
}
get("my-root/swagger-ui/index.html").also {
get("swagger-ui/index.html").also {
it.status shouldBe HttpStatusCode.OK
it.contentType shouldBe ContentType.Text.Html
it.body.shouldNotBeEmpty()
}
get("my-root/swagger-ui/swagger-initializer.js").also {
get("swagger-ui/swagger-initializer.js").also {
it.status shouldBe HttpStatusCode.OK
it.contentType shouldBe ContentType.Application.JavaScript
it.body shouldContain "url: \"/my-root/swagger-ui/api.json\""

}
get("my-root/swagger-ui/api.json").also {
get("swagger-ui/api.json").also {
it.status shouldBe HttpStatusCode.OK
it.contentType shouldBe ContentType.Application.Json
it.body.shouldNotBeEmpty()
Expand Down Expand Up @@ -391,12 +391,19 @@ class ApplicationTests {
}


private fun swaggerUITestApplication(block: suspend ApplicationTestBuilder.() -> Unit) {
swaggerUITestApplication({}, block)
private fun swaggerUITestApplication(followRedirects: Boolean = true, block: suspend TestContext.() -> Unit) {
swaggerUITestApplication({}, followRedirects, block)
}

private fun swaggerUITestApplication(pluginConfig: PluginConfigDsl.() -> Unit, block: suspend ApplicationTestBuilder.() -> Unit) {
private fun swaggerUITestApplication(
pluginConfig: PluginConfigDsl.() -> Unit,
followRedirects: Boolean = true,
block: suspend TestContext.() -> Unit
) {
testApplication {
val client = createClient {
this.followRedirects = followRedirects
}
application {
install(Authentication) {
basic("my-auth") {
Expand Down Expand Up @@ -436,32 +443,39 @@ class ApplicationTests {
}
Thread.sleep(500)
}
block()
TestContext(client).apply { block() }
}
}

private suspend fun ApplicationTestBuilder.get(path: String): GetResult {
return client.get(path)
.let {
GetResult(
path = path,
status = it.status,
contentType = it.contentType(),
body = it.bodyAsText()
)
}
.also { it.print() }
class TestContext(private val client: HttpClient) {

suspend fun get(path: String): GetResult {
return client.get(path)
.let {
GetResult(
path = path,
status = it.status,
contentType = it.contentType(),
body = it.bodyAsText(),
redirect = it.headers["Location"]
)
}
.also { it.print() }
}


private fun GetResult.print() {
println("GET ${this.path} => ${this.status} (${this.contentType}): ${this.body}")
}
}

private data class GetResult(

data class GetResult(
val path: String,
val status: HttpStatusCode,
val contentType: ContentType?,
val body: String,
val redirect: String?
)

private fun GetResult.print() {
println("GET ${this.path} => ${this.status} (${this.contentType}): ${this.body}")
}

}

0 comments on commit e966f72

Please sign in to comment.