Source code

Revision control

Copy as Markdown

Other Tools

#![deny(warnings)]
#[macro_use]
extern crate warp;
use futures_util::future;
use warp::Filter;
#[tokio::test]
async fn path() {
let _ = pretty_env_logger::try_init();
let foo = warp::path("foo");
let bar = warp::path(String::from("bar"));
let foo_bar = foo.and(bar.clone());
// /foo
let foo_req = || warp::test::request().path("/foo");
assert!(foo_req().matches(&foo).await);
assert!(!foo_req().matches(&bar).await);
assert!(!foo_req().matches(&foo_bar).await);
// /foo/bar
let foo_bar_req = || warp::test::request().path("/foo/bar");
assert!(foo_bar_req().matches(&foo).await);
assert!(!foo_bar_req().matches(&bar).await);
assert!(foo_bar_req().matches(&foo_bar).await);
}
#[tokio::test]
async fn param() {
let _ = pretty_env_logger::try_init();
let num = warp::path::param::<u32>();
let req = warp::test::request().path("/321");
assert_eq!(req.filter(&num).await.unwrap(), 321);
let s = warp::path::param::<String>();
let req = warp::test::request().path("/warp");
assert_eq!(req.filter(&s).await.unwrap(), "warp");
// u32 doesn't extract a non-int
let req = warp::test::request().path("/warp");
assert!(!req.matches(&num).await);
let combo = num.map(|n| n + 5).and(s);
let req = warp::test::request().path("/42/vroom");
assert_eq!(req.filter(&combo).await.unwrap(), (47, "vroom".to_string()));
// empty segments never match
let req = warp::test::request();
assert!(
!req.matches(&s).await,
"param should never match an empty segment"
);
}
#[tokio::test]
async fn end() {
let _ = pretty_env_logger::try_init();
let foo = warp::path("foo");
let end = warp::path::end();
let foo_end = foo.and(end);
assert!(
warp::test::request().path("/").matches(&end).await,
"end() matches /"
);
assert!(
warp::test::request()
.matches(&end)
.await,
"end() matches /"
);
assert!(
warp::test::request()
.matches(&end)
.await,
"end() matches empty path"
);
assert!(
warp::test::request()
.path("localhost:1234")
.matches(&end)
.await,
"end() matches authority-form"
);
assert!(
!warp::test::request().path("/foo").matches(&end).await,
"end() doesn't match /foo"
);
assert!(
warp::test::request().path("/foo").matches(&foo_end).await,
"path().and(end()) matches /foo"
);
assert!(
warp::test::request().path("/foo/").matches(&foo_end).await,
"path().and(end()) matches /foo/"
);
}
#[tokio::test]
async fn tail() {
let tail = warp::path::tail();
// matches full path
let ex = warp::test::request()
.path("/42/vroom")
.filter(&tail)
.await
.unwrap();
assert_eq!(ex.as_str(), "42/vroom");
// matches index
let ex = warp::test::request().path("/").filter(&tail).await.unwrap();
assert_eq!(ex.as_str(), "");
// doesn't include query
let ex = warp::test::request()
.path("/foo/bar?baz=quux")
.filter(&tail)
.await
.unwrap();
assert_eq!(ex.as_str(), "foo/bar");
// doesn't include previously matched prefix
let and = warp::path("foo").and(tail);
let ex = warp::test::request()
.path("/foo/bar")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "bar");
// sets unmatched path index to end
let m = tail.and(warp::path("foo"));
assert!(!warp::test::request().path("/foo/bar").matches(&m).await);
let m = tail.and(warp::path::end());
assert!(warp::test::request().path("/foo/bar").matches(&m).await);
let ex = warp::test::request()
.path("localhost")
.filter(&tail)
.await
.unwrap();
assert_eq!(ex.as_str(), "/");
}
#[tokio::test]
async fn or() {
let _ = pretty_env_logger::try_init();
// /foo/bar OR /foo/baz
let foo = warp::path("foo");
let bar = warp::path("bar");
let baz = warp::path("baz");
let p = foo.and(bar.or(baz));
// /foo/bar
let req = warp::test::request().path("/foo/bar");
assert!(req.matches(&p).await);
// /foo/baz
let req = warp::test::request().path("/foo/baz");
assert!(req.matches(&p).await);
// deeper nested ORs
// /foo/bar/baz OR /foo/baz/bar OR /foo/bar/bar
let p = foo
.and(bar.and(baz).map(|| panic!("shouldn't match")))
.or(foo.and(baz.and(bar)).map(|| panic!("shouldn't match")))
.or(foo.and(bar.and(bar)));
// /foo/baz
let req = warp::test::request().path("/foo/baz/baz");
assert!(!req.matches(&p).await);
// /foo/bar/bar
let req = warp::test::request().path("/foo/bar/bar");
assert!(req.matches(&p).await);
}
#[tokio::test]
async fn or_else() {
let _ = pretty_env_logger::try_init();
let foo = warp::path("foo");
let bar = warp::path("bar");
let p = foo.and(bar.or_else(|_| future::ok::<_, std::convert::Infallible>(())));
// /foo/bar
let req = warp::test::request().path("/foo/nope");
assert!(req.matches(&p).await);
}
#[tokio::test]
async fn path_macro() {
let _ = pretty_env_logger::try_init();
let req = warp::test::request().path("/foo/bar");
let p = path!("foo" / "bar");
assert!(req.matches(&p).await);
let req = warp::test::request().path("/foo/bar");
let p = path!(String / "bar");
assert_eq!(req.filter(&p).await.unwrap(), "foo");
let req = warp::test::request().path("/foo/bar");
let p = path!("foo" / String);
assert_eq!(req.filter(&p).await.unwrap(), "bar");
// Requires path end
let req = warp::test::request().path("/foo/bar/baz");
let p = path!("foo" / "bar");
assert!(!req.matches(&p).await);
let req = warp::test::request().path("/foo/bar/baz");
let p = path!("foo" / "bar").and(warp::path("baz"));
assert!(!req.matches(&p).await);
// Prefix syntax
let req = warp::test::request().path("/foo/bar/baz");
let p = path!("foo" / "bar" / ..);
assert!(req.matches(&p).await);
let req = warp::test::request().path("/foo/bar/baz");
let p = path!("foo" / "bar" / ..).and(warp::path!("baz"));
assert!(req.matches(&p).await);
// Empty
let req = warp::test::request().path("/");
let p = path!();
assert!(req.matches(&p).await);
let req = warp::test::request().path("/foo");
let p = path!();
assert!(!req.matches(&p).await);
}
#[tokio::test]
async fn full_path() {
let full_path = warp::path::full();
let foo = warp::path("foo");
let bar = warp::path("bar");
let param = warp::path::param::<u32>();
// matches full request path
let ex = warp::test::request()
.path("/42/vroom")
.filter(&full_path)
.await
.unwrap();
assert_eq!(ex.as_str(), "/42/vroom");
// matches index
let ex = warp::test::request()
.path("/")
.filter(&full_path)
.await
.unwrap();
assert_eq!(ex.as_str(), "/");
// does not include query
let ex = warp::test::request()
.path("/foo/bar?baz=quux")
.filter(&full_path)
.await
.unwrap();
assert_eq!(ex.as_str(), "/foo/bar");
// includes previously matched prefix
let and = foo.and(full_path);
let ex = warp::test::request()
.path("/foo/bar")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "/foo/bar");
// includes following matches
let and = full_path.and(foo);
let ex = warp::test::request()
.path("/foo/bar")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "/foo/bar");
// includes previously matched param
let and = foo.and(param).and(full_path);
let (_, ex) = warp::test::request()
.path("/foo/123")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "/foo/123");
// does not modify matching
let m = full_path.and(foo).and(bar);
assert!(warp::test::request().path("/foo/bar").matches(&m).await);
// doesn't panic on authority-form
let ex = warp::test::request()
.path("localhost:1234")
.filter(&full_path)
.await
.unwrap();
assert_eq!(ex.as_str(), "/");
}
#[tokio::test]
async fn peek() {
let peek = warp::path::peek();
let foo = warp::path("foo");
let bar = warp::path("bar");
let param = warp::path::param::<u32>();
// matches full request path
let ex = warp::test::request()
.path("/42/vroom")
.filter(&peek)
.await
.unwrap();
assert_eq!(ex.as_str(), "42/vroom");
// matches index
let ex = warp::test::request().path("/").filter(&peek).await.unwrap();
assert_eq!(ex.as_str(), "");
// does not include query
let ex = warp::test::request()
.path("/foo/bar?baz=quux")
.filter(&peek)
.await
.unwrap();
assert_eq!(ex.as_str(), "foo/bar");
// does not include previously matched prefix
let and = foo.and(peek);
let ex = warp::test::request()
.path("/foo/bar")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "bar");
// includes following matches
let and = peek.and(foo);
let ex = warp::test::request()
.path("/foo/bar")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "foo/bar");
// does not include previously matched param
let and = foo.and(param).and(peek);
let (_, ex) = warp::test::request()
.path("/foo/123")
.filter(&and)
.await
.unwrap();
assert_eq!(ex.as_str(), "");
// does not modify matching
let and = peek.and(foo).and(bar);
assert!(warp::test::request().path("/foo/bar").matches(&and).await);
}
#[tokio::test]
async fn peek_segments() {
let peek = warp::path::peek();
// matches full request path
let ex = warp::test::request()
.path("/42/vroom")
.filter(&peek)
.await
.unwrap();
assert_eq!(ex.segments().collect::<Vec<_>>(), &["42", "vroom"]);
// matches index
let ex = warp::test::request().path("/").filter(&peek).await.unwrap();
let segs = ex.segments().collect::<Vec<_>>();
assert_eq!(segs, Vec::<&str>::new());
}