【问题标题】:Validate Request in Ktor在 Ktor 中验证请求
【发布时间】:2021-09-21 11:32:31
【问题描述】:

我有一个使用 Ktor 制作的 API,当请求的 som 字段失败时,它返回 500 错误,我想检查所有请求数据并返回,在本例中为 422。

请求类:

@Serializable
data class LoginRequest (
    val email: String,
    val password: String
)

路由

route("v1/auth/login") {
    post {
        val loginRequest = call.receive<LoginRequest>()
        //LOGIN METHOD
    }
}

现在Ktor显示的错误是:

[eventLoopGroupProxy-4-1] ERROR Application - Unhandled: POST - /v1/auth/login
kotlinx.serialization.MissingFieldException: Field 'password' is required for type with serial name

确保系统不会失败并以 BadRequest 响应的最佳方法是什么?

【问题讨论】:

    标签: validation kotlin request ktor


    【解决方案1】:

    如果你想在特定的地方捕获异常,你可以使用try/catch:

    try {
        val loginRequest = call.receive<LoginRequest>()
        ...
    } catch (e: SerializationException) {
        // serialization exceptions
        call.respond(HttpStatusCode.UnprocessableEntity)
    } catch (t: Throwable) {
        // other exceptions
        call.respond(HttpStatusCode.InternalServerError)
    }
    

    如果你想要一些全局的try/catch,Ktor 有StatusPages 功能来处理这种情况:它会在调用处理过程中捕获所有异常。

    try/catch 相同,您可以捕获特定异常,例如SerializationException,或使用Exception/Throwable 处理任何其他异常。

    install(StatusPages) {
        exception<SerializationException> { cause ->
            // serialization exceptions
            call.respond(HttpStatusCode.UnprocessableEntity)
        }
        exception<Throwable> { cause ->
            // other exceptions
            call.respond(HttpStatusCode.InternalServerError)
        }
    }
    

    【讨论】:

    • 第二个选项对我有用!谢谢!
    【解决方案2】:

    您可以使用默认的null 值使字段可为空,在遇到未知属性时忽略错误并手动验证结果对象。这是一个例子:

    import io.ktor.application.*
    import io.ktor.features.*
    import io.ktor.http.*
    import io.ktor.request.*
    import io.ktor.response.*
    import io.ktor.routing.*
    import io.ktor.serialization.*
    import io.ktor.server.engine.*
    import io.ktor.server.netty.*
    import kotlinx.serialization.Serializable
    import kotlinx.serialization.json.Json
    
    @Serializable
    data class LoginRequest (
        val email: String? = null,
        val password: String? = null
    )
    
    suspend fun main() {
        embeddedServer(Netty, port = 8080) {
            install(ContentNegotiation) {
                json(Json {
                    ignoreUnknownKeys = true
                })
            }
    
            routing {
                post("/") {
                    val request = call.receive<LoginRequest>()
    
                    if (request.email == null || request.password == null) {
                        call.respond(HttpStatusCode.UnprocessableEntity)
                        return@post
                    }
    
                    call.respond(HttpStatusCode.OK)
                }
            }
        }.start()
    }
    

    【讨论】:

      【解决方案3】:
      post {
          try {
              val customer = call.receive<Customer>()
              customerStorage.add(customer)
              call.respondText("Customer stored correctly", status = HttpStatusCode.Created)
          } catch (e: SerializationException) {
              call.respondText(e.localizedMessage, status = HttpStatusCode.UnprocessableEntity)
          } catch (e: Exception) {
              call.respondText(e.localizedMessage, status = HttpStatusCode.InternalServerError)
          }
      }
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2019-06-09
      • 2018-06-10
      • 2021-03-05
      • 2021-12-11
      • 1970-01-01
      • 2018-02-19
      • 2017-06-02
      • 2018-10-18
      • 2018-03-12
      相关资源
      最近更新 更多