1 #![deny(warnings)]
2
3 use bytes::Buf;
4 use futures::TryStreamExt;
5 use warp::Filter;
6
7 #[tokio::test]
matches()8 async fn matches() {
9 let _ = pretty_env_logger::try_init();
10
11 let concat = warp::body::bytes();
12
13 let req = warp::test::request().path("/nothing-matches-me");
14
15 assert!(req.matches(&concat).await);
16
17 let p = warp::path("body");
18 let req = warp::test::request().path("/body");
19
20 let and = p.and(concat);
21
22 assert!(req.matches(&and).await);
23 }
24
25 #[tokio::test]
server_error_if_taking_body_multiple_times()26 async fn server_error_if_taking_body_multiple_times() {
27 let _ = pretty_env_logger::try_init();
28
29 let concat = warp::body::bytes();
30 let double = concat.and(concat).map(|_, _| warp::reply());
31
32 let res = warp::test::request().reply(&double).await;
33
34 assert_eq!(res.status(), 500);
35 assert_eq!(res.body(), "Request body consumed multiple times");
36 }
37
38 #[tokio::test]
content_length_limit()39 async fn content_length_limit() {
40 let _ = pretty_env_logger::try_init();
41
42 let limit = warp::body::content_length_limit(30).map(warp::reply);
43
44 let res = warp::test::request().reply(&limit).await;
45 assert_eq!(res.status(), 411, "missing content-length returns 411");
46
47 let res = warp::test::request()
48 .header("content-length", "999")
49 .reply(&limit)
50 .await;
51 assert_eq!(res.status(), 413, "over limit returns 413");
52
53 let res = warp::test::request()
54 .header("content-length", "2")
55 .reply(&limit)
56 .await;
57 assert_eq!(res.status(), 200, "under limit succeeds");
58 }
59
60 #[tokio::test]
json()61 async fn json() {
62 let _ = pretty_env_logger::try_init();
63
64 let json = warp::body::json::<Vec<i32>>();
65
66 let req = warp::test::request().body("[1, 2, 3]");
67
68 let vec = req.filter(&json).await.unwrap();
69 assert_eq!(vec, &[1, 2, 3]);
70
71 let req = warp::test::request()
72 .header("content-type", "application/json")
73 .body("[3, 2, 1]");
74
75 let vec = req.filter(&json).await.unwrap();
76 assert_eq!(vec, &[3, 2, 1], "matches content-type");
77 }
78
79 #[tokio::test]
json_rejects_bad_content_type()80 async fn json_rejects_bad_content_type() {
81 let _ = pretty_env_logger::try_init();
82
83 let json = warp::body::json::<Vec<i32>>().map(|_| warp::reply());
84
85 let req = warp::test::request()
86 .header("content-type", "text/xml")
87 .body("[3, 2, 1]");
88
89 let res = req.reply(&json).await;
90 assert_eq!(
91 res.status(),
92 415,
93 "bad content-type should be 415 Unsupported Media Type"
94 );
95 }
96
97 #[tokio::test]
json_invalid()98 async fn json_invalid() {
99 let _ = pretty_env_logger::try_init();
100
101 let json = warp::body::json::<Vec<i32>>().map(|vec| warp::reply::json(&vec));
102
103 let res = warp::test::request().body("lol#wat").reply(&json).await;
104 assert_eq!(res.status(), 400);
105 let prefix = b"Request body deserialize error: ";
106 assert_eq!(&res.body()[..prefix.len()], prefix);
107 }
108
109 #[test]
json_size_of()110 fn json_size_of() {
111 let json = warp::body::json::<Vec<i32>>();
112 assert_eq!(std::mem::size_of_val(&json), 0);
113 }
114
115 #[tokio::test]
form()116 async fn form() {
117 let _ = pretty_env_logger::try_init();
118
119 let form = warp::body::form::<Vec<(String, String)>>();
120
121 let req = warp::test::request().body("foo=bar&baz=quux");
122
123 let vec = req.filter(&form).await.unwrap();
124 let expected = vec![
125 ("foo".to_owned(), "bar".to_owned()),
126 ("baz".to_owned(), "quux".to_owned()),
127 ];
128 assert_eq!(vec, expected);
129 }
130
131 #[tokio::test]
form_rejects_bad_content_type()132 async fn form_rejects_bad_content_type() {
133 let _ = pretty_env_logger::try_init();
134
135 let form = warp::body::form::<Vec<(String, String)>>().map(|_| warp::reply());
136
137 let req = warp::test::request()
138 .header("content-type", "application/x-www-form-urlencoded")
139 .body("foo=bar");
140
141 let res = req.reply(&form).await;
142 assert_eq!(res.status(), 200);
143
144 let req = warp::test::request()
145 .header("content-type", "text/xml")
146 .body("foo=bar");
147 let res = req.reply(&form).await;
148 assert_eq!(
149 res.status(),
150 415,
151 "bad content-type should be 415 Unsupported Media Type"
152 );
153 }
154
155 #[tokio::test]
form_allows_charset()156 async fn form_allows_charset() {
157 let _ = pretty_env_logger::try_init();
158
159 let form = warp::body::form::<Vec<(String, String)>>();
160
161 let req = warp::test::request()
162 .header(
163 "content-type",
164 "application/x-www-form-urlencoded; charset=utf-8",
165 )
166 .body("foo=bar");
167
168 let vec = req.filter(&form).await.unwrap();
169 let expected = vec![("foo".to_owned(), "bar".to_owned())];
170 assert_eq!(vec, expected);
171 }
172
173 #[tokio::test]
form_invalid()174 async fn form_invalid() {
175 let _ = pretty_env_logger::try_init();
176
177 let form = warp::body::form::<Vec<i32>>().map(|vec| warp::reply::json(&vec));
178
179 let res = warp::test::request().body("nope").reply(&form).await;
180 assert_eq!(res.status(), 400);
181 let prefix = b"Request body deserialize error: ";
182 assert_eq!(&res.body()[..prefix.len()], prefix);
183 }
184
185 #[tokio::test]
stream()186 async fn stream() {
187 let _ = pretty_env_logger::try_init();
188
189 let stream = warp::body::stream();
190
191 let body = warp::test::request()
192 .body("foo=bar")
193 .filter(&stream)
194 .await
195 .expect("filter() stream");
196
197 let bufs: Result<Vec<_>, warp::Error> = body.try_collect().await;
198 let bufs = bufs.unwrap();
199
200 assert_eq!(bufs.len(), 1);
201 assert_eq!(bufs[0].bytes(), b"foo=bar");
202 }
203