qiniu_multipart/server/
hyper.rs1use hyper::net::Fresh;
13use hyper::header::ContentType;
14use hyper::method::Method;
15use hyper::server::{Handler, Request, Response};
16
17pub use hyper::server::Request as HyperRequest;
18
19use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
20
21use super::{Multipart, HttpRequest};
22
23pub struct Switch<H, M> {
31 normal: H,
32 multipart: M,
33}
34
35impl<H, M> Switch<H, M> where H: Handler, M: MultipartHandler {
36 pub fn new(normal: H, multipart: M) -> Switch<H, M> {
39 Switch { normal, multipart }
40 }
41}
42
43impl<H, M> Handler for Switch<H, M> where H: Handler, M: MultipartHandler {
44 fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) {
45 match Multipart::from_request(req) {
46 Ok(multi) => self.multipart.handle_multipart(multi, res),
47 Err(req) => self.normal.handle(req, res),
48 }
49 }
50}
51
52pub trait MultipartHandler: Send + Sync {
57 fn handle_multipart<'a, 'k>(&self,
59 multipart: Multipart<Request<'a, 'k>>,
60 response: Response<'a, Fresh>);
61}
62
63impl<F> MultipartHandler for F
64where F: Fn(Multipart<Request>, Response<Fresh>), F: Send + Sync {
65 fn handle_multipart<'a, 'k>(&self,
66 multipart: Multipart<Request<'a, 'k>>,
67 response: Response<'a, Fresh>) {
68 (*self)(multipart, response);
69 }
70}
71
72impl<'a, 'b> HttpRequest for HyperRequest<'a, 'b> {
73 type Body = Self;
74
75 fn multipart_boundary(&self) -> Option<&str> {
76 if self.method != Method::Post {
77 return None;
78 }
79
80 self.headers.get::<ContentType>().and_then(|ct| {
81 let ContentType(ref mime) = *ct;
82 let params = match *mime {
83 Mime(TopLevel::Multipart, SubLevel::FormData, ref params) => params,
84 _ => return None,
85 };
86
87 params.iter().find(|&&(ref name, _)|
88 match *name {
89 Attr::Boundary => true,
90 _ => false,
91 }
92 ).and_then(|&(_, ref val)|
93 match *val {
94 Value::Ext(ref val) => Some(&**val),
95 _ => None,
96 }
97 )
98 })
99 }
100
101 fn body(self) -> Self {
102 self
103 }
104}
105
106impl<'r, 'a, 'b> HttpRequest for &'r mut HyperRequest<'a, 'b> {
107 type Body = Self;
108
109 fn multipart_boundary(&self) -> Option<&str> {
110 if self.method != Method::Post {
111 return None;
112 }
113
114 self.headers.get::<ContentType>().and_then(|ct| {
115 let ContentType(ref mime) = *ct;
116 let params = match *mime {
117 Mime(TopLevel::Multipart, SubLevel::FormData, ref params) => params,
118 _ => return None,
119 };
120
121 params.iter().find(|&&(ref name, _)|
122 match *name {
123 Attr::Boundary => true,
124 _ => false,
125 }
126 ).and_then(|&(_, ref val)|
127 match *val {
128 Value::Ext(ref val) => Some(&**val),
129 _ => None,
130 }
131 )
132 })
133 }
134
135 fn body(self) -> Self::Body {
136 self
137 }
138}
139