mirror of https://github.com/rwf2/Rocket.git
Parse and test params in ContentType.
This commit is contained in:
parent
254f03fa4e
commit
0cc379b82f
|
@ -204,6 +204,16 @@ fn is_valid_char(c: char) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_valid_token(string: &str) -> bool {
|
||||
if string.len() < 1 {
|
||||
return false;
|
||||
}
|
||||
|
||||
string.chars().take(1).all(is_valid_first_char)
|
||||
&& string.chars().skip(1).all(is_valid_char)
|
||||
}
|
||||
|
||||
|
||||
impl FromStr for ContentType {
|
||||
type Err = &'static str;
|
||||
|
||||
|
@ -250,8 +260,8 @@ impl FromStr for ContentType {
|
|||
};
|
||||
|
||||
let top_s = &raw[..slash];
|
||||
let (sub_s, _rest) = match raw.find(';') {
|
||||
Some(j) => (&raw[(slash + 1)..j], Some(&raw[(j + 1)..])),
|
||||
let (sub_s, params) = match raw.find(';') {
|
||||
Some(j) => (raw[(slash + 1)..j].trim_right(), Some(raw[(j + 1)..].trim_left())),
|
||||
None => (&raw[(slash + 1)..], None),
|
||||
};
|
||||
|
||||
|
@ -259,20 +269,36 @@ impl FromStr for ContentType {
|
|||
return Err("Empty string.");
|
||||
}
|
||||
|
||||
if !is_valid_first_char(top_s.chars().next().unwrap())
|
||||
|| !is_valid_first_char(sub_s.chars().next().unwrap()) {
|
||||
return Err("Invalid first char.");
|
||||
if !is_valid_token(top_s) || !is_valid_token(sub_s) {
|
||||
return Err("Invalid characters in type or subtype.");
|
||||
}
|
||||
|
||||
if top_s.contains(|c| !is_valid_char(c))
|
||||
|| sub_s.contains(|c| !is_valid_char(c)) {
|
||||
return Err("Invalid character in string.");
|
||||
let mut trimmed_params = vec![];
|
||||
for param in params.into_iter().flat_map(|p| p.split(";")) {
|
||||
let param = param.trim_left();
|
||||
for (i, split) in param.split("=").enumerate() {
|
||||
if split.trim() != split {
|
||||
return Err("Whitespace not allowed around = character.");
|
||||
}
|
||||
|
||||
let (top_s, sub_s) = (top_s.to_lowercase(), sub_s.to_lowercase());
|
||||
match i {
|
||||
0 => if !is_valid_token(split) {
|
||||
return Err("Invalid parameter name.");
|
||||
},
|
||||
1 => if !((split.starts_with('"') && split.ends_with('"'))
|
||||
|| is_valid_token(split)) {
|
||||
return Err("Invalid parameter value.");
|
||||
},
|
||||
_ => return Err("Malformed parameter.")
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Use `rest` to find params.
|
||||
Ok(ContentType::new(top_s, sub_s))
|
||||
trimmed_params.push(param);
|
||||
}
|
||||
|
||||
let (ttype, subtype) = (top_s.to_lowercase(), sub_s.to_lowercase());
|
||||
let params = params.map(|_| trimmed_params.join(";"));
|
||||
Ok(ContentType::with_params(ttype, subtype, params))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,7 +357,10 @@ mod test {
|
|||
macro_rules! assert_parse {
|
||||
($string:expr) => ({
|
||||
let result = ContentType::from_str($string);
|
||||
assert!(result.is_ok());
|
||||
if let Err(e) = result {
|
||||
println!("{:?} failed to parse: {}", $string, e);
|
||||
}
|
||||
|
||||
result.unwrap()
|
||||
});
|
||||
|
||||
|
@ -339,6 +368,7 @@ mod test {
|
|||
let c = assert_parse!($string);
|
||||
assert_eq!(c.ttype, $ct.ttype);
|
||||
assert_eq!(c.subtype, $ct.subtype);
|
||||
assert_eq!(c.params, $ct.params);
|
||||
c
|
||||
})
|
||||
}
|
||||
|
@ -347,27 +377,35 @@ mod test {
|
|||
fn test_simple() {
|
||||
assert_parse!("application/json", ContentType::JSON);
|
||||
assert_parse!("*/json", ContentType::new("*", "json"));
|
||||
assert_parse!("text/html", ContentType::HTML);
|
||||
assert_parse!("TEXT/html", ContentType::HTML);
|
||||
assert_parse!("text/html;charset=utf-8", ContentType::HTML);
|
||||
assert_parse!("text/html ; charset=utf-8", ContentType::HTML);
|
||||
assert_parse!("text/html ;charset=utf-8", ContentType::HTML);
|
||||
assert_parse!("TEXT/html;charset=utf-8", ContentType::HTML);
|
||||
assert_parse!("*/*", ContentType::Any);
|
||||
assert_parse!("application/*", ContentType::new("application", "*"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_params() {
|
||||
// TODO: Test these.
|
||||
assert_parse!("application/json; charset=utf-8", ContentType::JSON);
|
||||
assert_parse!("*/*;", ContentType::Any);
|
||||
assert_parse!("*/*;a=1;b=2;c=3;d=4",
|
||||
ContentType::with_params("*", "*", Some("a=1;b=2;c=3;d=4")));
|
||||
assert_parse!("*/*; a=1; b=2; c=3;d=4",
|
||||
ContentType::with_params("*", "*", Some("a=1;b=2;c=3;d=4")));
|
||||
assert_parse!("application/*;else=1",
|
||||
ContentType::with_params("application", "*", Some("else=1")));
|
||||
assert_parse!("*/*;charset=utf8;else=1",
|
||||
assert_parse!("*/*;charset=utf-8;else=1",
|
||||
ContentType::with_params("*", "*", Some("charset=utf-8;else=1")));
|
||||
assert_parse!("*/*; charset=utf-8; else=1",
|
||||
ContentType::with_params("*", "*", Some("charset=utf-8;else=1")));
|
||||
assert_parse!("*/*; charset=\"utf-8\"; else=1",
|
||||
ContentType::with_params("*", "*", Some("charset=\"utf-8\";else=1")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_parses() {
|
||||
assert_no_parse!("application//json");
|
||||
assert_no_parse!("application///json");
|
||||
assert_no_parse!("*&_/*)()");
|
||||
assert_no_parse!("/json");
|
||||
assert_no_parse!("text/");
|
||||
assert_no_parse!("text//");
|
||||
|
@ -376,5 +414,15 @@ mod test {
|
|||
assert_no_parse!("/*");
|
||||
assert_no_parse!("///");
|
||||
assert_no_parse!("");
|
||||
assert_no_parse!("*/*;");
|
||||
assert_no_parse!("*/*;a=");
|
||||
assert_no_parse!("*/*;a= ");
|
||||
assert_no_parse!("*/*;a=@#$%^&*()");
|
||||
assert_no_parse!("*/*;;");
|
||||
assert_no_parse!("*/*;=;");
|
||||
assert_no_parse!("*/*=;");
|
||||
assert_no_parse!("*/*=;=");
|
||||
assert_no_parse!("*/*; a=b;");
|
||||
assert_no_parse!("*/*; a = b");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue