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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::{convert::TryInto, str::FromStr};
use crate::headers::{HeaderName, HeaderValue, Headers, CONTENT_TYPE};
use crate::Mime;
#[derive(Debug)]
pub struct ContentType {
media_type: Mime,
}
impl ContentType {
pub fn new<U>(media_type: U) -> Self
where
U: TryInto<Mime>,
U::Error: std::fmt::Debug,
{
Self {
media_type: media_type
.try_into()
.expect("could not convert into a valid Mime type"),
}
}
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
let headers = match headers.as_ref().get(CONTENT_TYPE) {
Some(headers) => headers,
None => return Ok(None),
};
let ctation = headers.iter().last().unwrap();
let media_type = Mime::from_str(ctation.as_str()).map_err(|mut e| {
e.set_status(400);
e
})?;
Ok(Some(Self { media_type }))
}
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
headers.as_mut().insert(self.name(), self.value());
}
pub fn name(&self) -> HeaderName {
CONTENT_TYPE
}
pub fn value(&self) -> HeaderValue {
let output = format!("{}", self.media_type);
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
}
}
impl PartialEq<Mime> for ContentType {
fn eq(&self, other: &Mime) -> bool {
&self.media_type == other
}
}
impl PartialEq<&Mime> for ContentType {
fn eq(&self, other: &&Mime) -> bool {
&&self.media_type == other
}
}
impl From<Mime> for ContentType {
fn from(media_type: Mime) -> Self {
Self { media_type }
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::headers::Headers;
#[test]
fn smoke() -> crate::Result<()> {
let ct = ContentType::new(Mime::from_str("text/*")?);
let mut headers = Headers::new();
ct.apply(&mut headers);
let ct = ContentType::from_headers(headers)?.unwrap();
assert_eq!(
ct.value(),
format!("{}", Mime::from_str("text/*")?).as_str()
);
Ok(())
}
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(CONTENT_TYPE, "<nori ate the tag. yum.>");
let err = ContentType::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}
}