This repository has been archived by the owner on Feb 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 90
/
hyper.rs
98 lines (85 loc) · 3.22 KB
/
hyper.rs
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
//! Server-side integration with [Hyper](https://github.com/hyperium/hyper).
//! Enabled with the `hyper` feature.
use hyper::net::Fresh;
use hyper::header::ContentType;
use hyper::method::Method;
use hyper::server::{Handler, Request, Response};
use mime::{Mime, TopLevel, SubLevel, Attr, Value};
use super::{Multipart, HttpRequest};
/// A container that implements `hyper::server::Handler` which will switch
/// the handler implementation depending on if the incoming request is multipart or not.
///
/// Create an instance with `new()` and pass it to `hyper::server::Server::listen()` where
/// you would normally pass a `Handler` instance.
///
/// A convenient wrapper for `Multipart::from_request()`.
pub struct Switch<H, M> {
normal: H,
multipart: M,
}
impl<H, M> Switch<H, M> where H: Handler, M: MultipartHandler {
/// Create a new `Switch` instance where
/// `normal` handles normal Hyper requests and `multipart` handles Multipart requests
pub fn new(normal: H, multipart: M) -> Switch<H, M> {
Switch {
normal: normal,
multipart: multipart,
}
}
}
impl<H, M> Handler for Switch<H, M> where H: Handler, M: MultipartHandler {
fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) {
match Multipart::from_request(req) {
Ok(multi) => self.multipart.handle_multipart(multi, res),
Err(req) => self.normal.handle(req, res),
}
}
}
/// A trait defining a type that can handle an incoming multipart request.
///
/// Extends to closures of the type `Fn(Multipart<Request>, Response<Fresh>)`,
/// and subsequently static functions.
pub trait MultipartHandler: Send + Sync {
/// Generate a response from this multipart request.
fn handle_multipart<'a, 'k>(&self,
multipart: Multipart<Request<'a, 'k>>,
response: Response<'a, Fresh>);
}
impl<F> MultipartHandler for F
where F: Fn(Multipart<Request>, Response<Fresh>), F: Send + Sync {
fn handle_multipart<'a, 'k>(&self,
multipart: Multipart<Request<'a, 'k>>,
response: Response<'a, Fresh>) {
(*self)(multipart, response);
}
}
impl<'a, 'b> HttpRequest for Request<'a, 'b> {
fn is_multipart(&self) -> bool {
self.method == Method::Post &&
self.headers.get::<ContentType>().map_or(false, |ct| {
let ContentType(ref mime) = *ct;
debug!("Content-Type: {}", mime);
match *mime {
Mime(TopLevel::Multipart, SubLevel::FormData, _) => true,
_ => false,
}
})
}
fn boundary(&self) -> Option<&str> {
self.headers.get::<ContentType>().and_then(|ct| {
let ContentType(ref mime) = *ct;
let Mime(_, _, ref params) = *mime;
params.iter().find(|&&(ref name, _)|
match *name {
Attr::Ext(ref name) => "boundary" == name,
_ => false,
}
).and_then(|&(_, ref val)|
match *val {
Value::Ext(ref val) => Some(&**val),
_ => None,
}
)
})
}
}