为啥 warp 会为输入错误的参数返回 HTTP 405 Method Not Allowed?

Posted

技术标签:

【中文标题】为啥 warp 会为输入错误的参数返回 HTTP 405 Method Not Allowed?【英文标题】:Why does warp return HTTP 405 Method Not Allowed for incorrectly typed parameters?为什么 warp 会为输入错误的参数返回 HTTP 405 Method Not Allowed? 【发布时间】:2021-05-27 12:20:23 【问题描述】:

在 warp 中考虑以下路由规范:

let read_book_route = warp::path!("book" / Address)
        .and(warp::get())
        .and(warp::any().map(move || read_book_state.clone()))
        .and_then(handler::read_book_handler);

如果 URL 中提供了非Address,warp 会自动返回 HTTP 405 Method Not Allowed 状态码:

$ curl -i http://example.com/book/not_a_valid_address
HTTP/1.1 405 Method Not Allowed
content-type: text/plain; charset=utf-8
content-length: 23
date: Thu, 25 Feb 2021 06:22:20 GMT

HTTP method not allowed

为什么是 HTTP 405?为什么不是 HTTP 400 或任何其他客户端错误?

【问题讨论】:

向您回馈您的问题:您会发现status codes 中的哪一个更合适以及为什么 @SteffenUllrich 在我看来,404 可能更合适:资源不存在,该方法不适用于不存在的资源是相当次要的。 @SteffenUllrich 400,也许?鉴于请求在技术上无效(诚然在应用程序级别)。 @sporejack: 400 从 HTTP 协议的角度来看是一个畸形的请求,因此它不是一个很好的匹配。一般来说,虽然没有完全匹配问题的错误 - 实际上,使用什么确切的错误代码并不相关,只要它清楚地意味着首先发生了错误并且客户应该为此负责(即 4xx代码与 5xx 代码)。 【参考方案1】:

不确定 100%(缺少某些上下文),但可能与此问题有关:https://github.com/seanmonstar/warp/issues/77(还提出了一些可能的解决方法)

由于过滤器形成一棵树,如果一个分支因拒绝而失败,也可以尝试相邻分支。 Warp 具有拒绝的优先级。与NotFound 相比,MethodNotAllowed 具有更高的优先级。因此,如果路径与 NotFound 的一个分支不匹配,因为使用不同的参数类型,warp 将尝试其他路径 - 并用 MethodNotAllowed 覆盖拒绝,因为其他分支有其他方法。

您可以使用RUST_LOG=trace cargo run 运行具有跟踪日志级别的服务器,并检查过滤器匹配是如何执行的。

【讨论】:

【参考方案2】:

path!可以理解为path()param()的序列,由end()加盖(默认),根据param()的文档:

如果无法解析该值,则使用 404 Not Found 拒绝。

然而 AFAIK 这是一个Rejection,这意味着warp 将尝试下一个过滤器or-ed 并得到它的 拒绝。

由于您没有提供最小复制示例,也没有显示所有代码,我希望会有其他过滤器,我不太了解扭曲过程是如何组合的拒绝,我也不知道你是否有例如一个中间 recover 可以拦截 param() 将产生的 not_found,并让另一个拒绝优先。

【讨论】:

以上是关于为啥 warp 会为输入错误的参数返回 HTTP 405 Method Not Allowed?的主要内容,如果未能解决你的问题,请参考以下文章

为啥当参数以(.pl)结尾时,Spring MVC @RequestMapping 会为映射(/user/username:.+)抛出 406 错误

为啥当 Debug 设置为 False 时,Django 会为静态媒体生成 HTTP 500 错误?

CUDA - 为啥基于扭曲的并行减少速度较慢?

为啥 GCM 会为某些 android 设备返回空的注册 ID?

为啥没有返回语句时没有编译器错误?

为啥要费心去了解 CUDA Warps?