From b211966c28112f808005ee19a92c94ad650ce86c Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 7 Mar 2019 13:33:40 -0800 Subject: [PATCH] Payload extractor --- actix-web-codegen/src/server.rs | 31 ----------- examples/basic.rs | 4 +- src/extract.rs | 95 ++++++++++++++++++++++++++++++++- src/lib.rs | 29 ++++------ 4 files changed, 107 insertions(+), 52 deletions(-) delete mode 100644 actix-web-codegen/src/server.rs diff --git a/actix-web-codegen/src/server.rs b/actix-web-codegen/src/server.rs deleted file mode 100644 index 43e663f3a..000000000 --- a/actix-web-codegen/src/server.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::collections::HashSet; -use std::env; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; - -use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; -use syn; - -/// Thrift mux server impl -pub struct Server {} - -impl Server { - fn new() -> Server { - Server {} - } - - /// generate servers - pub fn generate(input: TokenStream) { - let mut srv = Server::new(); - let ast: syn::ItemFn = syn::parse2(input).unwrap(); - println!("T: {:?}", ast.ident); - - // quote! { - // #ast - - // #(#servers)* - // } - } -} diff --git a/examples/basic.rs b/examples/basic.rs index 3f832780a..f8b816480 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,6 +1,8 @@ use futures::IntoFuture; -use actix_web::macros::get; +#[macro_use] +extern crate actix_web; + use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer}; #[get("/resource1/{name}/index.html")] diff --git a/src/extract.rs b/src/extract.rs index 6c838901f..ac04f1c4e 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -409,7 +409,7 @@ impl DerefMut for Form { impl FromRequest

for Form where T: DeserializeOwned + 'static, - P: Stream + 'static, + P: Stream + 'static, { type Error = Error; type Future = Box>; @@ -653,7 +653,7 @@ impl Responder for Json { impl FromRequest

for Json where T: DeserializeOwned + 'static, - P: Stream + 'static, + P: Stream + 'static, { type Error = Error; type Future = Box>; @@ -739,6 +739,97 @@ impl Default for JsonConfig { } } +/// Payload extractor returns request 's payload stream. +/// +/// ## Example +/// +/// ```rust +/// use futures::{Future, Stream}; +/// use actix_web::{web, error, App, Error, HttpResponse}; +/// +/// /// extract binary data from request +/// fn index

(body: web::Payload

) -> impl Future +/// where +/// P: Stream +/// { +/// body.map_err(Error::from) +/// .fold(web::BytesMut::new(), move |mut body, chunk| { +/// body.extend_from_slice(&chunk); +/// Ok::<_, Error>(body) +/// }) +/// .and_then(|body| { +/// format!("Body {:?}!", body); +/// Ok(HttpResponse::Ok().finish()) +/// }) +/// } +/// +/// fn main() { +/// let app = App::new().service( +/// web::resource("/index.html").route( +/// web::get().to_async(index)) +/// ); +/// } +/// ``` +pub struct Payload(crate::dev::Payload); + +impl Stream for Payload +where + T: Stream, +{ + type Item = Bytes; + type Error = PayloadError; + + #[inline] + fn poll(&mut self) -> Poll, PayloadError> { + self.0.poll() + } +} + +/// Get request's payload stream +/// +/// ## Example +/// +/// ```rust +/// use futures::{Future, Stream}; +/// use actix_web::{web, error, App, Error, HttpResponse}; +/// +/// /// extract binary data from request +/// fn index

(body: web::Payload

) -> impl Future +/// where +/// P: Stream +/// { +/// body.map_err(Error::from) +/// .fold(web::BytesMut::new(), move |mut body, chunk| { +/// body.extend_from_slice(&chunk); +/// Ok::<_, Error>(body) +/// }) +/// .and_then(|body| { +/// format!("Body {:?}!", body); +/// Ok(HttpResponse::Ok().finish()) +/// }) +/// } +/// +/// fn main() { +/// let app = App::new().service( +/// web::resource("/index.html").route( +/// web::get().to_async(index)) +/// ); +/// } +/// ``` +impl

FromRequest

for Payload

+where + P: Stream, +{ + type Error = Error; + type Future = Result, Error>; + type Config = (); + + #[inline] + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { + Ok(Payload(req.take_payload())) + } +} + /// Request binary data from a request's payload. /// /// Loads request's payload and construct Bytes instance. diff --git a/src/lib.rs b/src/lib.rs index 35a88b981..ad4a2a866 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,23 +18,12 @@ mod service; mod state; pub mod test; -/// Attribute macros for route registration -/// -/// ```rust -/// use actix_web::{macros, App, HttpResponse}; -/// -/// #[macros::get("/index.html")] -/// fn index() -> HttpResponse { -/// HttpResponse::Ok().finish() -/// } -/// -/// fn main() { -/// let app = App::new().service(index); -/// } -/// ``` -pub mod macros { - pub use actix_web_codegen::{get, post, put}; -} +#[allow(unused_imports)] +#[macro_use] +extern crate actix_web_codegen; + +#[doc(hidden)] +pub use actix_web_codegen::*; // re-export for convenience pub use actix_http::Response as HttpResponse; @@ -85,6 +74,9 @@ pub mod web { use actix_http::{http::Method, Error, Response}; use futures::IntoFuture; + pub use actix_http::Response as HttpResponse; + pub use bytes::{Bytes, BytesMut}; + use crate::extract::FromRequest; use crate::handler::{AsyncFactory, Factory}; use crate::resource::Resource; @@ -92,7 +84,8 @@ pub mod web { use crate::route::Route; use crate::scope::Scope; - pub use crate::extract::{Json, Path, Query}; + pub use crate::extract::{Json, Path, Payload, Query}; + pub use crate::request::HttpRequest; pub use crate::state::State; /// Create resource for a specific path.