Make multipart an optional feature (default off) (#1128)
This commit is contained in:
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@@ -63,6 +63,7 @@ jobs:
|
||||
- "feat.: gzip"
|
||||
- "feat.: brotli"
|
||||
- "feat.: json"
|
||||
- "feat.: multipart"
|
||||
- "feat.: stream"
|
||||
- "feat.: socks/default-tls"
|
||||
- "feat.: socks/rustls-tls"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -21,6 +21,7 @@ features = [
|
||||
"blocking",
|
||||
"cookies",
|
||||
"json",
|
||||
"multipart",
|
||||
]
|
||||
|
||||
[features]
|
||||
@@ -49,6 +50,8 @@ brotli = ["async-compression", "async-compression/brotli", "tokio-util"]
|
||||
|
||||
json = ["serde_json"]
|
||||
|
||||
multipart = ["mime_guess"]
|
||||
|
||||
trust-dns = ["trust-dns-resolver"]
|
||||
|
||||
stream = []
|
||||
@@ -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"
|
||||
@@ -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"]
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -113,6 +115,7 @@ impl Body {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "multipart")]
|
||||
pub(crate) fn len(&self) -> Option<u64> {
|
||||
match self.kind {
|
||||
Kind::Reader(_, len) => len,
|
||||
@@ -120,6 +123,7 @@ impl Body {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "multipart")]
|
||||
pub(crate) fn into_reader(self) -> Reader {
|
||||
match self.kind {
|
||||
Kind::Reader(r, _) => Reader::Reader(r),
|
||||
@@ -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 {
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
mod body;
|
||||
mod client;
|
||||
#[cfg(feature = "multipart")]
|
||||
pub mod multipart;
|
||||
mod request;
|
||||
mod response;
|
||||
|
||||
@@ -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};
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#[cfg(feature = "multipart")]
|
||||
use super::multipart::Form;
|
||||
/// dox
|
||||
use bytes::Bytes;
|
||||
@@ -18,6 +19,7 @@ pub struct Body {
|
||||
|
||||
enum Inner {
|
||||
Bytes(Bytes),
|
||||
#[cfg(feature = "multipart")]
|
||||
Multipart(Form),
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -39,6 +42,7 @@ impl Body {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "multipart")]
|
||||
pub(crate) fn from_form(f: Form) -> Body {
|
||||
Self {
|
||||
inner: Inner::Multipart(f),
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ mod client;
|
||||
mod request;
|
||||
mod response;
|
||||
/// TODO
|
||||
#[cfg(feature = "multipart")]
|
||||
pub mod multipart;
|
||||
|
||||
pub use self::body::Body;
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user