Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| // Copyright 2016 `multipart` Crate Developers | |
| // | |
| // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or | |
| // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or | |
| // http://opensource.org/licenses/MIT>, at your option. This file may not be | |
| // copied, modified, or distributed except according to those terms. | |
| //! Server-side integration with [Hyper](https://github.com/hyperium/hyper). | |
| //! Enabled with the `hyper` feature (on by default). | |
| //! | |
| //! Also contains an implementation of [`HttpRequest`](../trait.HttpRequest.html) | |
| //! for `hyper::server::Request` and `&mut hyper::server::Request`. | |
| use hyper::net::Fresh; | |
| use hyper::header::ContentType; | |
| use hyper::method::Method; | |
| use hyper::server::{Handler, Request, Response}; | |
| pub use hyper::server::Request as HyperRequest; | |
| use hyper::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, 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 HyperRequest<'a, 'b> { | |
| type Body = Self; | |
| fn multipart_boundary(&self) -> Option<&str> { | |
| if self.method != Method::Post { | |
| return None; | |
| } | |
| self.headers.get::<ContentType>().and_then(|ct| { | |
| let ContentType(ref mime) = *ct; | |
| let params = match *mime { | |
| Mime(TopLevel::Multipart, SubLevel::FormData, ref params) => params, | |
| _ => return None, | |
| }; | |
| params.iter().find(|&&(ref name, _)| | |
| match *name { | |
| Attr::Boundary => true, | |
| _ => false, | |
| } | |
| ).and_then(|&(_, ref val)| | |
| match *val { | |
| Value::Ext(ref val) => Some(&**val), | |
| _ => None, | |
| } | |
| ) | |
| }) | |
| } | |
| fn body(self) -> Self { | |
| self | |
| } | |
| } | |
| impl<'r, 'a, 'b> HttpRequest for &'r mut HyperRequest<'a, 'b> { | |
| type Body = Self; | |
| fn multipart_boundary(&self) -> Option<&str> { | |
| if self.method != Method::Post { | |
| return None; | |
| } | |
| self.headers.get::<ContentType>().and_then(|ct| { | |
| let ContentType(ref mime) = *ct; | |
| let params = match *mime { | |
| Mime(TopLevel::Multipart, SubLevel::FormData, ref params) => params, | |
| _ => return None, | |
| }; | |
| params.iter().find(|&&(ref name, _)| | |
| match *name { | |
| Attr::Boundary => true, | |
| _ => false, | |
| } | |
| ).and_then(|&(_, ref val)| | |
| match *val { | |
| Value::Ext(ref val) => Some(&**val), | |
| _ => None, | |
| } | |
| ) | |
| }) | |
| } | |
| fn body(self) -> Self::Body { | |
| self | |
| } | |
| } | |