any 模块只有一个方法,就是 any 方法,它可以匹配任何路由的过滤器。我们可以使用 any 方法将一些可克隆的资源转换成一个过滤器,从而允许轻松地将它与其他 Filter 结合在一起。当然也可以使用 any 方法创建适用于多个 Filter 的末尾调用的 Reply。例如:
use warp::Filter;
let route = warp::any()
.map(|| {
"I always return this string!"
});
这个例子将会匹配任何路由,然后返回 “I always return this string!” 。 文档中的另一个例子是
use std::sync::Arc;
use warp::Filter;
let state = Arc::new(vec![33, 41]);
let with_state = warp::any().map(move || state.clone());
// Now we could `and` with any other filter:
let route = warp::path::param()
.and(with_state)
.map(|param_id: u32, db: Arc<Vec<u32>>| {
db.contains(¶m_id)
});
通过 any,我们将 state 成功转换成为一个 Filter,然后我们就能将 state 和其他 Filter 结合起来使用。
body 模块用来提取请求中的 body, 它提供了一些方法,如下所示:
不过,现代的web api通常只使用 json 来进行通信。文件上传,下载之类的可能会交给专门的文件服务系统,因此可能也很少使用 form,stream,bytes,aggregate。如果需要使用,可以自行查看文档。而限制请求体的大小,我们更多可能是通过反向代理服务器来进行限制,而不是使用 content_length_limit。
因此,我们通常需要使用的方法只剩下一个,那就是 json, 使用 json 方法可以提取json 反序列化后的内容,前提是我们需要安装 serde_json 来提供反序列化的能力。在第一篇的时候,我们已经安装了 serde 和 serde_json
在 compression 模块,提供了 brotli,gzip,default 三种压缩方式的方法。如下所示:
压缩功能通常由静态服务器实现。当客户端向服务器请求静态资源(如HTML、CSS、JavaScript文件)时,服务器可以应用压缩算法对这些文件进行压缩,并将压缩后的文件发送给客户端。这样可以减少传输的数据量,加快页面加载速度,并降低带宽消耗。
动态服务器主要负责处理动态内容的生成和响应,例如处理用户提交的表单数据、执行数据库查询等。压缩静态资源一般是在静态服务器层面进行的,因为静态资源在每次请求时都可以使用相同的压缩版本,而动态内容则根据每个请求的不同而生成,无法事先进行压缩。
因此,如果你只在 warp 中实现 web api,那么是无需关心压缩问题的。如果你使用模板渲染,前后端不分离的模式,也是可以进行预处理压缩,然后交给静态服务器代理。因此这个问题主要是由静态服务器解决。如果需要使用 compression,可以参考文档。
cookie 模块有两个方法,可以用于获取HTTP 请求中的携带的cookie,而不是操作响应中的 cookie。
这两个方法的功能是显而易见的,cookie 方法可以从请求中根据 cookie 名称获取相应的 cookie 值,这个值是必须的,否则将会产生一个 warp::reject::Rejection;而 optional 方法则不要求这个 cookie 是必须的,如果找到,则提取 cookie 的值,否则将继续请求。
cors 模块只有一个方法,就是 cors 方法,使用它可以产生一个 cors 对象,通过该对象,我们可以设置允许的跨域请求方法,允许的跨域来源。
文档中的 demo 如下所示:
use warp::Filter;
let cors = warp::cors()
.allow_origin("https://hyper.rs")
.allow_methods(vec!["GET", "POST", "DELETE"]);
let route = warp::any()
.map(warp::reply)
.with(cors);
如果你想允许所有请求来源,那么可以这样:
use warp::Filter;
let cors = warp::cors()
.allow_any_origin();
这是 warp 给我们提供的跨域处理。你可以选择使用它,或者也可以在反向代理服务器(例如:Nginx, Apache)处进行跨域的处理。毕竟解决跨域的方式比较多,实际中常用的可能是在反向代理处处置跨域。
这个模块的作用未知,翻看了一下 warp 的源码,发现了下面的使用方式,但是现在版本的 warp 根本没有这个 set 方法。
#![deny(warnings)]
extern crate warp;
use warp::Filter;
#[derive(Clone, Debug, PartialEq)]
struct Ext1(i32);
#[test]
fn set_and_get() {
let ext = warp::any()
.map(|| {
warp::ext::set(Ext1(55));
})
.untuple_one()
.and(warp::ext::get::<Ext1>());
let extracted = warp::test::request().filter(&ext).unwrap();
assert_eq!(extracted, Ext1(55));
}
#[test]
fn get_missing() {
let ext = warp::ext::get().map(|e: Ext1| e.0.to_string());
let res = warp::test::request().reply(&ext);
assert_eq!(res.status(), 500);
assert_eq!(res.body(), "Missing request extension");
}
#[test]
#[should_panic]
fn set_outside_of_filter_should_panic() {
warp::ext::set(Ext1(55));
}
从这个例子来看,就是可以设置一个值,然后获取。这就导致该模块实际上没什么用,因为我们可以通过 Filter 的 Extract 来带回一个值,然后传递给 map 或者 and_then 中的方法。因此有没有 ext 模块并不影响我们使用 warp。
该模块用来返回一个 file response,在较小的项目下通常是有用的,因为这个时候我们可能不会使用专门的文件系统来存储文件,而是直接在我们的后端 API 中进行处理。(即使是动态生成文件,例如导出Excel,也应该将生成的文件存储在专门的文件系统中。)另外一点就是通常我们都是由静态服务器来处理静态文件的,而不是由动态服务器处理。
它提供的方法如下所示:
文档中的示例如下所示,都是处理静态文件的。
use warp::Filter;
// Matches requests that start with `/static`,
// and then uses the rest of that path to lookup
// and serve a file from `/www/static`.
let route = warp::path("static")
.and(warp::fs::dir("/www/static"));
// For example:
// - `GET /static/app.js` would serve the file `/www/static/app.js`
// - `GET /static/css/app.css` would serve the file `/www/static/css/app.css`
// Always serves this file from the file system.
let route = warp::fs::file("/www/static/app.js");