Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make multipart an optional feature (default off) #1128

Merged
merged 1 commit into from Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Expand Up @@ -63,6 +63,7 @@ jobs:
- "feat.: gzip"
- "feat.: brotli"
- "feat.: json"
- "feat.: multipart"
- "feat.: stream"
- "feat.: socks/default-tls"
- "feat.: socks/rustls-tls"
Expand All @@ -84,21 +85,21 @@ jobs:
- name: windows / stable-x86_64-msvc
os: windows-latest
target: x86_64-pc-windows-msvc
features: "--features blocking,gzip,brotli,json"
features: "--features blocking,gzip,brotli,json,multipart"
- name: windows / stable-i686-msvc
os: windows-latest
target: i686-pc-windows-msvc
features: "--features blocking,gzip,brotli,json"
features: "--features blocking,gzip,brotli,json,multipart"
- name: windows / stable-x86_64-gnu
os: windows-latest
rust: stable-x86_64-pc-windows-gnu
target: x86_64-pc-windows-gnu
features: "--features blocking,gzip,brotli,json"
features: "--features blocking,gzip,brotli,json,multipart"
- name: windows / stable-i686-gnu
os: windows-latest
rust: stable-i686-pc-windows-gnu
target: i686-pc-windows-gnu
features: "--features blocking,gzip,brotli,json"
features: "--features blocking,gzip,brotli,json,multipart"

- name: "feat.: default-tls disabled"
features: "--no-default-features"
Expand All @@ -120,6 +121,8 @@ jobs:
features: "--features brotli"
- name: "feat.: json"
features: "--features json"
- name: "feat.: multipart"
features: "--features multipart"
- name: "feat.: stream"
features: "--features stream"
- name: "feat.: socks/default-tls"
Expand Down
14 changes: 13 additions & 1 deletion Cargo.toml
Expand Up @@ -21,6 +21,7 @@ features = [
"blocking",
"cookies",
"json",
"multipart",
]

[features]
Expand Down Expand Up @@ -49,6 +50,8 @@ brotli = ["async-compression", "async-compression/brotli", "tokio-util"]

json = ["serde_json"]

multipart = ["mime_guess"]

trust-dns = ["trust-dns-resolver"]

stream = []
Expand All @@ -74,9 +77,13 @@ url = "2.2"
bytes = "1.0"
serde = "1.0"
serde_urlencoded = "0.7"
mime_guess = "2.0"

# Optional deps...

## json
serde_json = { version = "1.0", optional = true }
## multipart
mime_guess = { version = "2.0", default-features = false, optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
base64 = "0.13"
Expand Down Expand Up @@ -206,3 +213,8 @@ required-features = ["gzip"]
name = "brotli"
path = "tests/brotli.rs"
required-features = ["brotli"]

[[test]]
name = "multipart"
path = "tests/multipart.rs"
required-features = ["multipart"]
1 change: 1 addition & 0 deletions src/async_impl/body.rs
Expand Up @@ -152,6 +152,7 @@ impl Body {
ImplStream(self)
}

#[cfg(feature = "multipart")]
pub(crate) fn content_length(&self) -> Option<u64> {
match self.inner {
Inner::Reusable(ref bytes) => Some(bytes.len() as u64),
Expand Down
1 change: 1 addition & 0 deletions src/async_impl/mod.rs
Expand Up @@ -9,6 +9,7 @@ pub(crate) use self::decoder::Decoder;
pub mod body;
pub mod client;
pub mod decoder;
#[cfg(feature = "multipart")]
pub mod multipart;
pub(crate) mod request;
mod response;
6 changes: 5 additions & 1 deletion src/async_impl/request.rs
Expand Up @@ -11,9 +11,12 @@ use serde_json;

use super::body::Body;
use super::client::{Client, Pending};
#[cfg(feature = "multipart")]
use super::multipart;
use super::response::Response;
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_LENGTH, CONTENT_TYPE};
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
#[cfg(feature = "multipart")]
use crate::header::CONTENT_LENGTH;
use crate::{Method, Url};
use http::{Request as HttpRequest, request::Parts};

Expand Down Expand Up @@ -260,6 +263,7 @@ impl RequestBuilder {
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "multipart")]
pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder {
let mut builder = self.header(
CONTENT_TYPE,
Expand Down
8 changes: 7 additions & 1 deletion src/blocking/body.rs
@@ -1,7 +1,9 @@
use std::fmt;
use std::fs::File;
use std::future::Future;
use std::io::{self, Cursor, Read};
use std::io::{self, Read};
#[cfg(feature = "multipart")]
use std::io::Cursor;
use std::mem;
use std::ptr;

Expand Down Expand Up @@ -113,13 +115,15 @@ impl Body {
}
}

#[cfg(feature = "multipart")]
pub(crate) fn len(&self) -> Option<u64> {
match self.kind {
Kind::Reader(_, len) => len,
Kind::Bytes(ref bytes) => Some(bytes.len() as u64),
}
}

#[cfg(feature = "multipart")]
pub(crate) fn into_reader(self) -> Reader {
match self.kind {
Kind::Reader(r, _) => Reader::Reader(r),
Expand Down Expand Up @@ -236,11 +240,13 @@ impl<'a> fmt::Debug for DebugLength<'a> {
}
}

#[cfg(feature = "multipart")]
pub(crate) enum Reader {
Reader(Box<dyn Read + Send>),
Bytes(Cursor<Bytes>),
}

#[cfg(feature = "multipart")]
impl Read for Reader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match *self {
Expand Down
1 change: 1 addition & 0 deletions src/blocking/mod.rs
Expand Up @@ -59,6 +59,7 @@

mod body;
mod client;
#[cfg(feature = "multipart")]
pub mod multipart;
mod request;
mod response;
Expand Down
2 changes: 2 additions & 0 deletions src/blocking/request.rs
Expand Up @@ -10,6 +10,7 @@ use serde_json;
use serde_urlencoded;

use super::body::{self, Body};
#[cfg(feature = "multipart")]
use super::multipart;
use super::Client;
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
Expand Down Expand Up @@ -508,6 +509,7 @@ impl RequestBuilder {
/// ```
///
/// See [`multipart`](multipart/) for more examples.
#[cfg(feature = "multipart")]
pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder {
let mut builder = self.header(
CONTENT_TYPE,
Expand Down
9 changes: 7 additions & 2 deletions src/lib.rs
Expand Up @@ -182,6 +182,7 @@
//! - **gzip**: Provides response body gzip decompression.
//! - **brotli**: Provides response body brotli decompression.
//! - **json**: Provides serialization and deserialization for JSON bodies.
//! - **multipart**: Provides functionality for multipart forms.
//! - **stream**: Adds support for `futures::Stream`.
//! - **socks**: Provides SOCKS5 proxy support.
//! - **trust-dns**: Enables a trust-dns async resolver instead of default
Expand Down Expand Up @@ -290,11 +291,13 @@ if_hyper! {
doctest!("../README.md");

pub use self::async_impl::{
multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response, ResponseBuilderExt,
Body, Client, ClientBuilder, Request, RequestBuilder, Response, ResponseBuilderExt,
};
pub use self::proxy::Proxy;
#[cfg(feature = "__tls")]
pub use self::tls::{Certificate, Identity};
#[cfg(feature = "multipart")]
pub use self::async_impl::multipart;


mod async_impl;
Expand All @@ -316,5 +319,7 @@ if_wasm! {
mod wasm;
mod util;

pub use self::wasm::{multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response};
pub use self::wasm::{Body, Client, ClientBuilder, Request, RequestBuilder, Response};
#[cfg(feature = "multipart")]
pub use self::wasm::multipart;
}
5 changes: 5 additions & 0 deletions src/wasm/body.rs
@@ -1,3 +1,4 @@
#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
Expand All @@ -18,6 +19,7 @@ pub struct Body {

enum Inner {
Bytes(Bytes),
#[cfg(feature = "multipart")]
Multipart(Form),
}

Expand All @@ -30,6 +32,7 @@ impl Body {
let js_value: &JsValue = body_array.as_ref();
Ok(js_value.to_owned())
}
#[cfg(feature = "multipart")]
Inner::Multipart(form) => {
let form_data = form.to_form_data()?;
let js_value: &JsValue = form_data.as_ref();
Expand All @@ -39,6 +42,7 @@ impl Body {
}

#[inline]
#[cfg(feature = "multipart")]
pub(crate) fn from_form(f: Form) -> Body {
Self {
inner: Inner::Multipart(f),
Expand All @@ -48,6 +52,7 @@ impl Body {
pub(crate) fn is_empty(&self) -> bool {
match &self.inner {
Inner::Bytes(bytes) => bytes.is_empty(),
#[cfg(feature = "multipart")]
Inner::Multipart(form) => form.is_empty(),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/wasm/mod.rs
Expand Up @@ -5,6 +5,7 @@ mod client;
mod request;
mod response;
/// TODO
#[cfg(feature = "multipart")]
pub mod multipart;

pub use self::body::Body;
Expand Down
1 change: 1 addition & 0 deletions src/wasm/request.rs
Expand Up @@ -191,6 +191,7 @@ impl RequestBuilder {
}

/// TODO
#[cfg(feature = "multipart")]
pub fn multipart(mut self, multipart: super::multipart::Form) -> RequestBuilder {
if let Ok(ref mut req) = self.request {
*req.body_mut() = Some(Body::from_form(multipart))
Expand Down