Closed LeIgHlEe closed 10 months ago
我剛才看一下源碼 io.ktor.server.engine.BaseApplicationEngine 如果沒辦法 resolve route 而且你自己也沒設定 response status,就會依序回應 RoutingFailureStatusCode 及 HttpStatusCode.NotFound (404)
private fun Application.installDefaultInterceptors() {
intercept(ApplicationCallPipeline.Fallback) {
if (call.isHandled) return@intercept
val status = call.response.status()
?: call.attributes.getOrNull(RoutingFailureStatusCode)
?: HttpStatusCode.NotFound
call.respond(status)
}
intercept(ApplicationCallPipeline.Call) {
verifyHostHeader()
}
}
在 Route.txt 源碼 如果沒辦法 resolve ,就設置 resolveResult.errorStatusCode,預設值也是 404
public suspend fun interceptor(context: PipelineContext<Unit, ApplicationCall>) {
val resolveContext = RoutingResolveContext(this, context.call, tracers)
when (val resolveResult = resolveContext.resolve()) {
is RoutingResolveResult.Success ->
executeResult(context, resolveResult.route, resolveResult.parameters)
is RoutingResolveResult.Failure ->
context.call.attributes.put(RoutingFailureStatusCode, resolveResult.errorStatusCode)
}
}
執行順序應該是 Route -> Authentication -> ApplicationCallPipeline.Call 所以如果 Route 沒辦法 resolve,就不會進入 Authentication 及 ApplicationCallPipeline.Call 直接回傳 404
除非你自已設置 call.attributes.put(RoutingFailureStatusCode) 或是嚐試在 StatusPages 覆寫你想要的 status code (我沒試過)
這是官方文件範例
install(StatusPages) {
status(HttpStatusCode.NotFound) { call, status ->
call.respondText(text = "404: Page Not Found", status = status)
}
}
非常感谢你的回答,我通过你给的代码示例和官方文件,从感性的角度来理解的话,大概是: 不管你有没有别人想要的东西,只要别人来拿,你就得验身。 而不是别人来拿的时候,你先帮忙看一眼有没有,没有的时候还亲切得告诉对方。 所以如果一个没有权限的请求进来,访问一个不存在的资源,也是优先提示没有权限。 再次感谢。
Routing 是对整个 ApplicationCallPipeline.Call 做 intercept,而 Authentication 我大概看了下源码,都是在 ApplicationCallPipeline.Call 之前的,也就是鉴权动作会放在选取路由的前面。 那是否意味着,如果访问一个不存在的路径,其实报错不是因为404,而是因为没有访问权限?