You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ktor中/articles端点PUT请求返回404而非405的问题咨询

Ktor Resources插件导致/articles路径PUT请求返回404而非405的解决办法

这是Ktor Resources插件的设计特性:只有当某个资源类存在至少一个对应的路由处理时,Ktor才会将该路径识别为“存在”。根路径因为注册了get<Root>,服务器能识别路径存在,只是PUT方法不被允许,所以返回405;而Articles资源虽然定义了类,但仅配置了GET方法的路由,当请求PUT时,Resources插件未匹配到该资源的任何路由,直接返回404。

以下是几种可行的解决办法:

办法一:为Articles资源显式处理不支持的HTTP方法

直接为Articles资源添加其他HTTP方法的路由,统一返回405并设置Allow头,明确告知允许的方法:

@Resource("/")
internal object Root

@Resource("articles")
internal data class Articles(val parent: Root = Root)

fun main() {
    embeddedServer(CIO, port = 8080){
        install(Resources)
        routing {
            get<Root> {
                call.respondText("articles/")
            }
            get<Articles> {
                call.respondText("articles list")
            }
            // 处理PUT请求返回405
            put<Articles> {
                call.response.headers.append("Allow", "GET")
                call.respond(HttpStatusCode.MethodNotAllowed)
            }
            // 按需添加POST、DELETE等其他不支持的方法
            post<Articles> {
                call.response.headers.append("Allow", "GET")
                call.respond(HttpStatusCode.MethodNotAllowed)
            }
        }
    }.start(true)
}

办法二:用拦截器统一处理资源路径的方法校验

如果有多个资源需要处理,可自定义拦截器,在路由匹配后检查请求方法是否被允许:

@Resource("/")
internal object Root

@Resource("articles")
internal data class Articles(val parent: Root = Root)

fun main() {
    embeddedServer(CIO, port = 8080){
        install(Resources)
        routing {
            // 定义各资源允许的HTTP方法
            val resourceAllowedMethods = mapOf(
                Root::class to setOf(HttpMethod.Get),
                Articles::class to setOf(HttpMethod.Get)
            )

            intercept(ApplicationCallPipeline.Call) {
                val resourceClass = call.attributes.getOrNull(Resources.Attributes.ResourceClass)
                resourceClass?.let { clazz ->
                    val allowedMethods = resourceAllowedMethods[clazz] ?: emptySet()
                    if (!allowedMethods.contains(call.request.httpMethod)) {
                        call.response.headers.append("Allow", allowedMethods.joinToString(", ") { it.value })
                        call.respond(HttpStatusCode.MethodNotAllowed)
                        finish()
                    }
                }
            }

            get<Root> {
                call.respondText("articles/")
            }
            get<Articles> {
                call.respondText("articles list")
            }
        }
    }.start(true)
}

办法三:改用普通路由替代Resources插件

如果不需要Resources的嵌套资源特性,直接使用普通路由定义,Ktor会自动识别路径存在,对不允许的方法返回405:

fun main() {
    embeddedServer(CIO, port = 8080){
        routing {
            get("/") {
                call.respondText("articles/")
            }
            route("/articles") {
                get {
                    call.respondText("articles list")
                }
                // 匹配所有未定义的方法,返回405
                handle {
                    call.response.headers.append("Allow", "GET")
                    call.respond(HttpStatusCode.MethodNotAllowed)
                }
            }
        }
    }.start(true)
}

内容的提问来源于stack exchange,提问作者Vencat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:15:27