mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-25 22:49:21 +02:00
move multipart support to separate crate
This commit is contained in:
5
actix-multipart/CHANGES.md
Normal file
5
actix-multipart/CHANGES.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Changes
|
||||
|
||||
## [0.1.0-alpha.1] - 2019-04-xx
|
||||
|
||||
* Split multipart support to separate crate
|
34
actix-multipart/Cargo.toml
Normal file
34
actix-multipart/Cargo.toml
Normal file
@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "actix-multipart"
|
||||
version = "0.1.0-alpha.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Multipart support for actix web framework."
|
||||
readme = "README.md"
|
||||
keywords = ["http", "web", "framework", "async", "futures"]
|
||||
homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-web.git"
|
||||
documentation = "https://docs.rs/actix-multipart/"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "actix_multipart"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "1.0.0-alpha.3"
|
||||
actix-service = "0.3.4"
|
||||
bytes = "0.4"
|
||||
derive_more = "0.14"
|
||||
httparse = "1.3"
|
||||
futures = "0.1.25"
|
||||
log = "0.4"
|
||||
mime = "0.3"
|
||||
time = "0.1"
|
||||
twoway = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "0.2.2"
|
||||
actix-http = "0.1.0-alpha.3"
|
1
actix-multipart/README.md
Normal file
1
actix-multipart/README.md
Normal file
@ -0,0 +1 @@
|
||||
# Multipart support for actix web framework [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-session) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
46
actix-multipart/src/error.rs
Normal file
46
actix-multipart/src/error.rs
Normal file
@ -0,0 +1,46 @@
|
||||
//! Error and Result module
|
||||
use actix_web::error::{ParseError, PayloadError};
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{HttpResponse, ResponseError};
|
||||
use derive_more::{Display, From};
|
||||
|
||||
/// A set of errors that can occur during parsing multipart streams
|
||||
#[derive(Debug, Display, From)]
|
||||
pub enum MultipartError {
|
||||
/// Content-Type header is not found
|
||||
#[display(fmt = "No Content-type header found")]
|
||||
NoContentType,
|
||||
/// Can not parse Content-Type header
|
||||
#[display(fmt = "Can not parse Content-Type header")]
|
||||
ParseContentType,
|
||||
/// Multipart boundary is not found
|
||||
#[display(fmt = "Multipart boundary is not found")]
|
||||
Boundary,
|
||||
/// Multipart stream is incomplete
|
||||
#[display(fmt = "Multipart stream is incomplete")]
|
||||
Incomplete,
|
||||
/// Error during field parsing
|
||||
#[display(fmt = "{}", _0)]
|
||||
Parse(ParseError),
|
||||
/// Payload error
|
||||
#[display(fmt = "{}", _0)]
|
||||
Payload(PayloadError),
|
||||
}
|
||||
|
||||
/// Return `BadRequest` for `MultipartError`
|
||||
impl ResponseError for MultipartError {
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
HttpResponse::new(StatusCode::BAD_REQUEST)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_multipart_error() {
|
||||
let resp: HttpResponse = MultipartError::Boundary.error_response();
|
||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
}
|
57
actix-multipart/src/extractor.rs
Normal file
57
actix-multipart/src/extractor.rs
Normal file
@ -0,0 +1,57 @@
|
||||
//! Multipart payload support
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
|
||||
use actix_web::dev::ServiceFromRequest;
|
||||
use actix_web::error::{Error, PayloadError};
|
||||
use actix_web::FromRequest;
|
||||
use actix_web::HttpMessage;
|
||||
|
||||
use crate::server::Multipart;
|
||||
|
||||
/// Get request's payload as multipart stream
|
||||
///
|
||||
/// Content-type: multipart/form-data;
|
||||
///
|
||||
/// ## Server example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use futures::{Future, Stream};
|
||||
/// # use futures::future::{ok, result, Either};
|
||||
/// use actix_web::{web, HttpResponse, Error};
|
||||
/// use actix_multipart as mp;
|
||||
///
|
||||
/// fn index(payload: mp::Multipart) -> impl Future<Item = HttpResponse, Error = Error> {
|
||||
/// payload.from_err() // <- get multipart stream for current request
|
||||
/// .and_then(|item| match item { // <- iterate over multipart items
|
||||
/// mp::Item::Field(field) => {
|
||||
/// // Field in turn is stream of *Bytes* object
|
||||
/// Either::A(field.from_err()
|
||||
/// .fold((), |_, chunk| {
|
||||
/// println!("-- CHUNK: \n{:?}", std::str::from_utf8(&chunk));
|
||||
/// Ok::<_, Error>(())
|
||||
/// }))
|
||||
/// },
|
||||
/// mp::Item::Nested(mp) => {
|
||||
/// // Or item could be nested Multipart stream
|
||||
/// Either::B(ok(()))
|
||||
/// }
|
||||
/// })
|
||||
/// .fold((), |_, _| Ok::<_, Error>(()))
|
||||
/// .map(|_| HttpResponse::Ok().into())
|
||||
/// }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
impl<P> FromRequest<P> for Multipart
|
||||
where
|
||||
P: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
type Error = Error;
|
||||
type Future = Result<Multipart, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||
let pl = req.take_payload();
|
||||
Ok(Multipart::new(req.headers(), pl))
|
||||
}
|
||||
}
|
6
actix-multipart/src/lib.rs
Normal file
6
actix-multipart/src/lib.rs
Normal file
@ -0,0 +1,6 @@
|
||||
mod error;
|
||||
mod extractor;
|
||||
mod server;
|
||||
|
||||
pub use self::error::MultipartError;
|
||||
pub use self::server::{Field, Item, Multipart};
|
1020
actix-multipart/src/server.rs
Normal file
1020
actix-multipart/src/server.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user