qiniu_multipart/client/
hyper.rs

1// Copyright 2016 `multipart` Crate Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7//! Client-side integration with [Hyper](https://github.com/hyperium/hyper). 
8//! Enabled with the `hyper` feature (on by default).
9//!
10//! Contains `impl HttpRequest for Request<Fresh>` and `impl HttpStream for Request<Streaming>`.
11//!
12//! Also see: [`lazy::Multipart::client_request()`](../lazy/struct.Multipart.html#method.client_request)
13//! and [`lazy::Multipart::client_request_mut()`](../lazy/struct.Multipart.html#method.client_request_mut)
14//! (adaptors for `hyper::client::RequestBuilder`).
15use hyper::client::request::Request;
16use hyper::client::response::Response;
17use hyper::header::{ContentType, ContentLength};
18use hyper::method::Method;
19use hyper::net::{Fresh, Streaming};
20
21use hyper::Error as HyperError;
22
23use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
24
25use super::{HttpRequest, HttpStream};
26
27/// #### Feature: `hyper`
28impl HttpRequest for Request<Fresh> {
29    type Stream = Request<Streaming>;
30    type Error = HyperError;
31
32    /// # Panics
33    /// If `self.method() != Method::Post`.
34    fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
35        if self.method() != Method::Post {
36            error!(
37                "Expected Hyper request method to be `Post`, was actually `{:?}`",
38                self.method()
39            );
40
41            return false;
42        }
43
44        let headers = self.headers_mut();
45
46        headers.set(ContentType(multipart_mime(boundary)));
47
48        if let Some(size) = content_len {
49            headers.set(ContentLength(size));   
50        }
51
52        debug!("Hyper headers: {}", headers); 
53
54        true
55    }
56
57    fn open_stream(self) -> Result<Self::Stream, Self::Error> {
58        self.start()
59    }
60} 
61
62/// #### Feature: `hyper`
63impl HttpStream for Request<Streaming> {
64    type Request = Request<Fresh>;
65    type Response = Response;
66    type Error = HyperError;
67
68    fn finish(self) -> Result<Self::Response, Self::Error> {
69        self.send()
70    }
71}
72
73/// Create a `Content-Type: multipart/form-data;boundary={bound}`
74pub fn content_type(bound: &str) -> ContentType {
75    ContentType(multipart_mime(bound))
76}
77
78fn multipart_mime(bound: &str) -> Mime {
79    Mime(
80        TopLevel::Multipart, SubLevel::Ext("form-data".into()),
81        vec![(Attr::Ext("boundary".into()), Value::Ext(bound.into()))]
82    )         
83}