1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::fmt;
use std::ascii::AsciiExt;
use hyper::header::{Header, HeaderFormat, parsing};
use hyper::error::Error as HyperError;
#[derive(Debug,Clone,PartialEq)]
pub struct ContentDispositionFormData {
pub name: Option<String>,
pub filename: Option<String>,
}
impl Header for ContentDispositionFormData {
fn header_name() -> &'static str {
"Content-Disposition"
}
fn parse_header(raw: &[Vec<u8>]) -> Result<ContentDispositionFormData,HyperError> {
parsing::from_one_raw_str(raw).and_then(|s: String| {
let mut sections = s.split(';');
match sections.next() {
None => return Err(HyperError::Header),
Some(s) => {
if &s.trim().to_ascii_lowercase() != "form-data" {
return Err(HyperError::Header)
}
}
};
let mut cd = ContentDispositionFormData { name: None, filename: None };
for section in sections {
let mut parts = section.split('=');
if parts.clone().count() != 2 { continue; }
let key = parts.next().unwrap().trim().to_ascii_lowercase();
let mut val = parts.next().unwrap().trim();
if val.chars().next()==Some('"') && val.chars().rev().next()==Some('"') {
val = &val[1..val.len()-1];
}
match &*key {
"name" => cd.name = Some(val.to_string()),
"filename" => cd.filename = Some(val.to_string()),
_ => {}
}
}
Ok(cd)
})
}
}
impl HeaderFormat for ContentDispositionFormData {
fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("form-data")
}
}
#[cfg(test)]
mod tests {
use super::ContentDispositionFormData;
use hyper::header::Header;
use hyper::error::Error as HyperError;
#[test]
fn parse_header() {
let a: ContentDispositionFormData =
ContentDispositionFormData::parse_header(
[b"form-data; dummy=3; name=upload;\r\n filename=\"sample.png\"".to_vec()].as_ref() )
.unwrap();
let b = ContentDispositionFormData {
name: Some("upload".to_string()),
filename: Some("sample.png".to_string()),
};
assert_eq!(a, b);
match ContentDispositionFormData::parse_header([b"".to_vec()].as_ref()) {
Ok(_) => assert!(false, "Empty header was parsed as ok!"),
Err(HyperError::Header) => assert!(true),
Err(_) => assert!(false, "Empty header parsed with wrong error"),
}
}
}