我正在使用ktor(2.1.0)创建一个小型API。在这样做的同时,我正在尝试利用Ktor-server很酷的功能,包括RequestValidation。
话虽如此,它不起作用,我无法弄清楚为什么,因为在我看来它非常接近文档中的示例。
这是我的服务器配置:
embeddedServer(Netty, port = 8080) {
routing {
post("/stock") {
val dto = call.receive<CreateStockRequest>()
call.respond(HttpStatusCode.NoContent)
}
}
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
})
}
install(StatusPages) {
exception<RequestValidationException> { call, cause ->
call.respond(HttpStatusCode.BadRequest, cause.reasons.joinToString())
}
}
install(RequestValidation) {
validate<CreateStockRequest> { request ->
if (request.name.isBlank())
ValidationResult.Invalid("Stock must have a name")
if (request.symbol.isBlank())
ValidationResult.Invalid("Symbol must have a name")
ValidationResult.Valid
}
}
}
这是正在"接收"的请求对象:
@Serializable
data class CreateStockRequest(val name: String, val symbol: String)
这是正在发送的身体:
{
"name": "",
"symbol": "something"
}
我本以为会得到BadRequest
的回复,但我得到了NoContent
的回应,好像这个请求一切都很好。
我做错了什么吗?
在您的示例中,仅当"name"和"symbol"均为空时,服务器才会响应BadRequest
。您可以将验证逻辑替换为when
表达式:
validate<CreateStockRequest> { request ->
when {
request.name.isBlank() -> ValidationResult.Invalid("Stock must have a name")
request.symbol.isBlank() -> ValidationResult.Invalid("Symbol must have a name")
else -> ValidationResult.Valid
}
}
我发现接受的答案是一个更干净的代码解决方案,这就是为什么它是公认的答案。
话虽如此,通过理解编译器与作用域混淆,可以更好地解释我遇到的实际问题。 在每个"if"子句上,我需要返回验证结果,但编译器没有它。
其原因是它与我的返回声明所指的背景混淆了。 我的解决方案是使用"@"表示法来指定返回的范围:
validate<CreateStockRequest> { request ->
if (request.name.isBlank())
return@validate ValidationResult.Invalid("Stock must have a name")
if (request.symbol.isBlank())
return@validate ValidationResult.Invalid("Symbol must have a name")
return@validate ValidationResult.Valid
}
}