Closed x2d7751347m closed 8 months ago
Hi, i'm having issues reproducing the problem. My attempt currently looks like this:
import io.github.smiley4.ktorswaggerui.SwaggerUI
import io.github.smiley4.ktorswaggerui.dsl.post
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.Application
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.server.response.respond
import io.ktor.server.routing.routing
fun main() {
embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true)
}
private fun Application.myModule() {
data class MyClass(
val id: Int,
val name: String,
val tag: String
)
install(SwaggerUI)
routing {
post({
response {
HttpStatusCode.Created to { // text/plain
description = "Created"
body<String>()
}
HttpStatusCode.BadRequest to { // application/json
description = "Bad Request"
body<MyClass>()
}
}
}) {
call.respond("Hello")
}
}
}
... though this does not throw any errors.
Could you maybe post a fully runnable example showcasing the error ?
routing {
post({
request {
queryParameter<Boolean>("bool") {
required = true
}
}
response {
HttpStatusCode.Created to { // text/plain
description = "Created"
body<String>()
}
HttpStatusCode.BadRequest to { // application/json
description = "Bad Request"
body<MyClass>()
}
}
}) {
val bool = call.parameters["bool"].toBoolean()
//It works
if(bool) call.respond("Hello")
// It occurs 406
else call.respond(MyClass(1, "name", "tag"))
}
}
Thank you. This does not seem like a problem with the swagger-ui plugin. Can you check if you have the ContentNegotiation plugin installed and configured and add if it not? You can find more information here: https://ktor.io/docs/serialization.html.
Sure. This is my plugin settings.
install(ContentNegotiation) {
json(
Json {
prettyPrint = true
isLenient = true
encodeDefaults = true
}
)
}
I hope this may help you.
The accept header of the request is causing this problem. It is fixed to the first response type in Swagger.
// First Example
routing {
post("test", {
request {
queryParameter<Boolean>("bool") {
required = true
}
}
// It works with json
response {
HttpStatusCode.Created to { // application/json
description = "Created"
body<MyClass>()
}
HttpStatusCode.BadRequest to { // text/plain
description = "Bad Request"
body<String>()
}
}
}) {
val bool = call.parameters["bool"].toBoolean()
if (bool) call.respond("Hello")
else call.respond(MyClass(1, "name", "tag"))
}
}
In swagger
Accept header of this curl request is application/json, And the content type of the response is text/plain. But it works.
And of course, It works.
// Second Example
routing {
// Separate path from first example
post("test2", {
request {
queryParameter<Boolean>("bool") {
required = true
}
}
// Here is the difference.
// It does not work with json response
response {
HttpStatusCode.Created to { // text/plain
description = "Created"
body<String>()
}
HttpStatusCode.BadRequest to { // application/json
description = "Bad Request"
body<MyClass>()
}
}
// Below is the same as the first example.
}) {
val bool = call.parameters["bool"].toBoolean()
if (bool) call.respond("Hello")
else call.respond(MyClass(1, "name", "tag"))
}
}
In swagger
And with this second example
Thanks, i understand the issue now. I think swagger chooses the accept header of the 2xx response to send with the request. So this
response {
HttpStatusCode.BadRequest to {
description = "Bad Request"
body<String>()
}
HttpStatusCode.Created to { // 2xx http code -> application/json
description = "Created"
body<MyClass>()
}
}
technically works aswell, independent of the order.
I'll look into it more.
Setting multiple types in response to the Accept header is the best solution. but I don't know if Swagger can do it.
Hi, sorry for the late response. As far as i know, swagger automatically chooses the Accept-Header based on the defined responses (i think always one of the 2xx responses). Unfortunately, i dont think this behaviour can be changed or the header overwritten - so there isn't much i can do here. I'd be interested to know however, how other people solved/overcame this issue/limitation.
Hello!
Not Acceptable error occurs when the response has multiple response media types. In my case, text-plain and application.json.
here is the flow.