use finchers::endpoint::syntax; use finchers::endpoint::IntoEndpointExt; use finchers::endpoints::{body, query}; use finchers::test; use http::Request; use serde::de; use serde::de::IntoDeserializer; use std::fmt; use std::iter::FromIterator; use std::marker::PhantomData; #[allow(missing_debug_implementations)] struct CSVSeqVisitor { _marker: PhantomData (I, T)>, } impl<'de, I, T> de::Visitor<'de> for CSVSeqVisitor where I: FromIterator, T: de::Deserialize<'de>, { type Value = I; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("a string") } fn visit_str(self, s: &str) -> Result where E: de::Error, { s.split(',') .map(|s| de::Deserialize::deserialize(s.into_deserializer())) .collect() } } fn from_csv<'de, D, I, T>(de: D) -> Result where D: de::Deserializer<'de>, I: FromIterator, T: de::Deserialize<'de>, { de.deserialize_str(CSVSeqVisitor { _marker: PhantomData, }) } #[derive(Debug, Deserialize, PartialEq)] struct Param { query: String, count: Option, #[serde(deserialize_with = "from_csv", default)] tags: Vec, } #[test] fn test_or_strict() { let query_str = "query=rustlang&count=42&tags=tokio,hyper"; let mut runner = test::runner({ let query = syntax::verb::get().and(query::required::()); let form = syntax::verb::post().and(body::urlencoded::()); query.or_strict(form) }); assert_matches!( runner.apply(format!("/?{}", query_str)), Ok(ref param) if *param == Param { query: "rustlang".into(), count: Some(42), tags: vec!["tokio".into(), "hyper".into()] } ); assert_matches!( runner.apply(Request::post("/") .header("content-type", "application/x-www-form-urlencoded") .body(query_str)), Ok(ref param) if *param == Param { query: "rustlang".into(), count: Some(42), tags: vec!["tokio".into(), "hyper".into()] } ); assert_matches!( runner.apply("/"), Err(ref e) if e.status_code().as_u16() == 400 ); assert_matches!( runner.apply(Request::delete(format!("/?{}", query_str))), Err(ref e) if e.status_code().as_u16() == 405 ); assert_matches!( runner.apply(Request::put("/") .header("content-type", "application/x-www-form-urlencoded") .body(query_str)), Err(ref e) if e.status_code().as_u16() == 405 ); }