2019-03-10 18:53:56 +01:00
|
|
|
//! Payload/Bytes/String extractors
|
2019-11-20 18:33:22 +01:00
|
|
|
use std::future::Future;
|
|
|
|
use std::pin::Pin;
|
2019-03-10 18:53:56 +01:00
|
|
|
use std::str;
|
2019-11-20 18:33:22 +01:00
|
|
|
use std::task::{Context, Poll};
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
use actix_http::error::{Error, ErrorBadRequest, PayloadError};
|
|
|
|
use actix_http::HttpMessage;
|
2019-03-17 08:48:40 +01:00
|
|
|
use bytes::{Bytes, BytesMut};
|
2019-06-18 08:43:25 +02:00
|
|
|
use encoding_rs::UTF_8;
|
2019-11-20 18:33:22 +01:00
|
|
|
use futures::future::{err, ok, Either, FutureExt, LocalBoxFuture, Ready};
|
|
|
|
use futures::{Stream, StreamExt};
|
2019-03-10 18:53:56 +01:00
|
|
|
use mime::Mime;
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
use crate::dev;
|
2019-03-10 18:53:56 +01:00
|
|
|
use crate::extract::FromRequest;
|
2019-03-17 08:48:40 +01:00
|
|
|
use crate::http::header;
|
2019-04-07 23:43:07 +02:00
|
|
|
use crate::request::HttpRequest;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
/// Payload extractor returns request 's payload stream.
|
|
|
|
///
|
|
|
|
/// ## Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2019-11-20 18:33:22 +01:00
|
|
|
/// use futures::{Future, Stream, StreamExt};
|
2019-03-10 18:53:56 +01:00
|
|
|
/// use actix_web::{web, error, App, Error, HttpResponse};
|
|
|
|
///
|
|
|
|
/// /// extract binary data from request
|
2019-11-20 18:33:22 +01:00
|
|
|
/// async fn index(mut body: web::Payload) -> Result<HttpResponse, Error>
|
2019-03-10 18:53:56 +01:00
|
|
|
/// {
|
2019-11-20 18:33:22 +01:00
|
|
|
/// let mut bytes = web::BytesMut::new();
|
|
|
|
/// while let Some(item) = body.next().await {
|
|
|
|
/// bytes.extend_from_slice(&item?);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// format!("Body {:?}!", bytes);
|
|
|
|
/// Ok(HttpResponse::Ok().finish())
|
2019-03-10 18:53:56 +01:00
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn main() {
|
|
|
|
/// let app = App::new().service(
|
|
|
|
/// web::resource("/index.html").route(
|
2019-11-21 16:34:04 +01:00
|
|
|
/// web::get().to(index))
|
2019-03-10 18:53:56 +01:00
|
|
|
/// );
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-10-01 10:05:38 +02:00
|
|
|
pub struct Payload(pub crate::dev::Payload);
|
|
|
|
|
|
|
|
impl Payload {
|
|
|
|
/// Deconstruct to a inner value
|
|
|
|
pub fn into_inner(self) -> crate::dev::Payload {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
2019-03-10 18:53:56 +01:00
|
|
|
|
2019-03-25 01:00:59 +01:00
|
|
|
impl Stream for Payload {
|
2019-11-20 18:33:22 +01:00
|
|
|
type Item = Result<Bytes, PayloadError>;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
#[inline]
|
2019-11-20 18:33:22 +01:00
|
|
|
fn poll_next(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context,
|
|
|
|
) -> Poll<Option<Self::Item>> {
|
|
|
|
Pin::new(&mut self.0).poll_next(cx)
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get request's payload stream
|
|
|
|
///
|
|
|
|
/// ## Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2019-11-20 18:33:22 +01:00
|
|
|
/// use futures::{Future, Stream, StreamExt};
|
2019-03-10 18:53:56 +01:00
|
|
|
/// use actix_web::{web, error, App, Error, HttpResponse};
|
|
|
|
///
|
|
|
|
/// /// extract binary data from request
|
2019-11-20 18:33:22 +01:00
|
|
|
/// async fn index(mut body: web::Payload) -> Result<HttpResponse, Error>
|
2019-03-10 18:53:56 +01:00
|
|
|
/// {
|
2019-11-20 18:33:22 +01:00
|
|
|
/// let mut bytes = web::BytesMut::new();
|
|
|
|
/// while let Some(item) = body.next().await {
|
|
|
|
/// bytes.extend_from_slice(&item?);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// format!("Body {:?}!", bytes);
|
|
|
|
/// Ok(HttpResponse::Ok().finish())
|
2019-03-10 18:53:56 +01:00
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn main() {
|
|
|
|
/// let app = App::new().service(
|
|
|
|
/// web::resource("/index.html").route(
|
2019-11-21 16:34:04 +01:00
|
|
|
/// web::get().to(index))
|
2019-03-10 18:53:56 +01:00
|
|
|
/// );
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-04-13 23:50:54 +02:00
|
|
|
impl FromRequest for Payload {
|
2019-04-14 01:35:25 +02:00
|
|
|
type Config = PayloadConfig;
|
2019-03-10 18:53:56 +01:00
|
|
|
type Error = Error;
|
2019-11-20 18:33:22 +01:00
|
|
|
type Future = Ready<Result<Payload, Error>>;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
#[inline]
|
2019-04-13 23:50:54 +02:00
|
|
|
fn from_request(_: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
|
2019-11-20 18:33:22 +01:00
|
|
|
ok(Payload(payload.take()))
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Request binary data from a request's payload.
|
|
|
|
///
|
|
|
|
/// Loads request's payload and construct Bytes instance.
|
|
|
|
///
|
|
|
|
/// [**PayloadConfig**](struct.PayloadConfig.html) allows to configure
|
|
|
|
/// extraction process.
|
|
|
|
///
|
|
|
|
/// ## Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use bytes::Bytes;
|
|
|
|
/// use actix_web::{web, App};
|
|
|
|
///
|
|
|
|
/// /// extract binary data from request
|
2019-11-21 16:34:04 +01:00
|
|
|
/// async fn index(body: Bytes) -> String {
|
2019-03-10 18:53:56 +01:00
|
|
|
/// format!("Body {:?}!", body)
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn main() {
|
|
|
|
/// let app = App::new().service(
|
|
|
|
/// web::resource("/index.html").route(
|
|
|
|
/// web::get().to(index))
|
|
|
|
/// );
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-04-13 23:50:54 +02:00
|
|
|
impl FromRequest for Bytes {
|
2019-04-14 01:35:25 +02:00
|
|
|
type Config = PayloadConfig;
|
2019-03-10 18:53:56 +01:00
|
|
|
type Error = Error;
|
2019-11-20 18:33:22 +01:00
|
|
|
type Future = Either<
|
|
|
|
LocalBoxFuture<'static, Result<Bytes, Error>>,
|
|
|
|
Ready<Result<Bytes, Error>>,
|
|
|
|
>;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
#[inline]
|
2019-04-13 23:50:54 +02:00
|
|
|
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
|
2019-07-17 11:48:37 +02:00
|
|
|
let tmp;
|
2019-05-05 04:43:49 +02:00
|
|
|
let cfg = if let Some(cfg) = req.app_data::<PayloadConfig>() {
|
2019-03-10 18:53:56 +01:00
|
|
|
cfg
|
|
|
|
} else {
|
|
|
|
tmp = PayloadConfig::default();
|
|
|
|
&tmp
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Err(e) = cfg.check_mimetype(req) {
|
2019-11-20 18:33:22 +01:00
|
|
|
return Either::Right(err(e));
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
let limit = cfg.limit;
|
2019-11-20 18:33:22 +01:00
|
|
|
let fut = HttpMessageBody::new(req, payload).limit(limit);
|
|
|
|
Either::Left(async move { Ok(fut.await?) }.boxed_local())
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Extract text information from a request's body.
|
|
|
|
///
|
|
|
|
/// Text extractor automatically decode body according to the request's charset.
|
|
|
|
///
|
|
|
|
/// [**PayloadConfig**](struct.PayloadConfig.html) allows to configure
|
|
|
|
/// extraction process.
|
|
|
|
///
|
|
|
|
/// ## Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2019-04-14 01:35:25 +02:00
|
|
|
/// use actix_web::{web, App, FromRequest};
|
2019-03-10 18:53:56 +01:00
|
|
|
///
|
|
|
|
/// /// extract text data from request
|
2019-11-21 16:34:04 +01:00
|
|
|
/// async fn index(text: String) -> String {
|
2019-03-10 18:53:56 +01:00
|
|
|
/// format!("Body {}!", text)
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn main() {
|
|
|
|
/// let app = App::new().service(
|
2019-05-05 04:43:49 +02:00
|
|
|
/// web::resource("/index.html")
|
|
|
|
/// .data(String::configure(|cfg| { // <- limit size of the payload
|
|
|
|
/// cfg.limit(4096)
|
|
|
|
/// }))
|
|
|
|
/// .route(web::get().to(index)) // <- register handler with extractor params
|
2019-03-10 18:53:56 +01:00
|
|
|
/// );
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-04-13 23:50:54 +02:00
|
|
|
impl FromRequest for String {
|
2019-04-14 01:35:25 +02:00
|
|
|
type Config = PayloadConfig;
|
2019-03-10 18:53:56 +01:00
|
|
|
type Error = Error;
|
2019-07-17 07:44:39 +02:00
|
|
|
type Future = Either<
|
2019-11-20 18:33:22 +01:00
|
|
|
LocalBoxFuture<'static, Result<String, Error>>,
|
|
|
|
Ready<Result<String, Error>>,
|
2019-07-17 07:44:39 +02:00
|
|
|
>;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
|
|
|
#[inline]
|
2019-04-13 23:50:54 +02:00
|
|
|
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
|
2019-07-17 11:48:37 +02:00
|
|
|
let tmp;
|
2019-05-05 04:43:49 +02:00
|
|
|
let cfg = if let Some(cfg) = req.app_data::<PayloadConfig>() {
|
2019-03-10 18:53:56 +01:00
|
|
|
cfg
|
|
|
|
} else {
|
|
|
|
tmp = PayloadConfig::default();
|
|
|
|
&tmp
|
|
|
|
};
|
|
|
|
|
|
|
|
// check content-type
|
|
|
|
if let Err(e) = cfg.check_mimetype(req) {
|
2019-11-20 18:33:22 +01:00
|
|
|
return Either::Right(err(e));
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// check charset
|
|
|
|
let encoding = match req.encoding() {
|
|
|
|
Ok(enc) => enc,
|
2019-11-20 18:33:22 +01:00
|
|
|
Err(e) => return Either::Right(err(e.into())),
|
2019-03-10 18:53:56 +01:00
|
|
|
};
|
|
|
|
let limit = cfg.limit;
|
2019-11-20 18:33:22 +01:00
|
|
|
let fut = HttpMessageBody::new(req, payload).limit(limit);
|
2019-03-10 18:53:56 +01:00
|
|
|
|
2019-11-20 18:33:22 +01:00
|
|
|
Either::Left(
|
|
|
|
async move {
|
|
|
|
let body = fut.await?;
|
|
|
|
|
|
|
|
if encoding == UTF_8 {
|
|
|
|
Ok(str::from_utf8(body.as_ref())
|
|
|
|
.map_err(|_| ErrorBadRequest("Can not decode body"))?
|
|
|
|
.to_owned())
|
|
|
|
} else {
|
|
|
|
Ok(encoding
|
|
|
|
.decode_without_bom_handling_and_without_replacement(&body)
|
|
|
|
.map(|s| s.into_owned())
|
|
|
|
.ok_or_else(|| ErrorBadRequest("Can not decode body"))?)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.boxed_local(),
|
|
|
|
)
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Payload configuration for request's payload.
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct PayloadConfig {
|
|
|
|
limit: usize,
|
|
|
|
mimetype: Option<Mime>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PayloadConfig {
|
|
|
|
/// Create `PayloadConfig` instance and set max size of payload.
|
|
|
|
pub fn new(limit: usize) -> Self {
|
2019-04-14 01:35:25 +02:00
|
|
|
let mut cfg = Self::default();
|
|
|
|
cfg.limit = limit;
|
|
|
|
cfg
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Change max size of payload. By default max size is 256Kb
|
|
|
|
pub fn limit(mut self, limit: usize) -> Self {
|
|
|
|
self.limit = limit;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set required mime-type of the request. By default mime type is not
|
|
|
|
/// enforced.
|
|
|
|
pub fn mimetype(mut self, mt: Mime) -> Self {
|
|
|
|
self.mimetype = Some(mt);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
fn check_mimetype(&self, req: &HttpRequest) -> Result<(), Error> {
|
2019-03-10 18:53:56 +01:00
|
|
|
// check content-type
|
|
|
|
if let Some(ref mt) = self.mimetype {
|
|
|
|
match req.mime_type() {
|
|
|
|
Ok(Some(ref req_mt)) => {
|
|
|
|
if mt != req_mt {
|
|
|
|
return Err(ErrorBadRequest("Unexpected Content-Type"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(None) => {
|
|
|
|
return Err(ErrorBadRequest("Content-Type is expected"));
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
return Err(err.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PayloadConfig {
|
|
|
|
fn default() -> Self {
|
|
|
|
PayloadConfig {
|
|
|
|
limit: 262_144,
|
|
|
|
mimetype: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 08:48:40 +01:00
|
|
|
/// Future that resolves to a complete http message body.
|
|
|
|
///
|
|
|
|
/// Load http message body.
|
|
|
|
///
|
|
|
|
/// By default only 256Kb payload reads to a memory, then
|
|
|
|
/// `PayloadError::Overflow` get returned. Use `MessageBody::limit()`
|
|
|
|
/// method to change upper limit.
|
2019-04-13 23:50:54 +02:00
|
|
|
pub struct HttpMessageBody {
|
2019-03-17 08:48:40 +01:00
|
|
|
limit: usize,
|
|
|
|
length: Option<usize>,
|
2019-04-13 23:50:54 +02:00
|
|
|
stream: Option<dev::Decompress<dev::Payload>>,
|
2019-03-17 08:48:40 +01:00
|
|
|
err: Option<PayloadError>,
|
2019-11-20 18:33:22 +01:00
|
|
|
fut: Option<LocalBoxFuture<'static, Result<Bytes, PayloadError>>>,
|
2019-03-17 08:48:40 +01:00
|
|
|
}
|
|
|
|
|
2019-04-13 23:50:54 +02:00
|
|
|
impl HttpMessageBody {
|
2019-03-17 08:48:40 +01:00
|
|
|
/// Create `MessageBody` for request.
|
2019-04-13 23:50:54 +02:00
|
|
|
pub fn new(req: &HttpRequest, payload: &mut dev::Payload) -> HttpMessageBody {
|
2019-03-17 08:48:40 +01:00
|
|
|
let mut len = None;
|
2019-04-07 00:02:02 +02:00
|
|
|
if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) {
|
2019-03-17 08:48:40 +01:00
|
|
|
if let Ok(s) = l.to_str() {
|
|
|
|
if let Ok(l) = s.parse::<usize>() {
|
|
|
|
len = Some(l)
|
|
|
|
} else {
|
|
|
|
return Self::err(PayloadError::UnknownLength);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Self::err(PayloadError::UnknownLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HttpMessageBody {
|
2019-04-13 23:50:54 +02:00
|
|
|
stream: Some(dev::Decompress::from_headers(payload.take(), req.headers())),
|
2019-03-17 08:48:40 +01:00
|
|
|
limit: 262_144,
|
|
|
|
length: len,
|
|
|
|
fut: None,
|
|
|
|
err: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change max size of payload. By default max size is 256Kb
|
|
|
|
pub fn limit(mut self, limit: usize) -> Self {
|
|
|
|
self.limit = limit;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn err(e: PayloadError) -> Self {
|
|
|
|
HttpMessageBody {
|
2019-04-13 23:50:54 +02:00
|
|
|
stream: None,
|
2019-03-17 08:48:40 +01:00
|
|
|
limit: 262_144,
|
|
|
|
fut: None,
|
|
|
|
err: Some(e),
|
|
|
|
length: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-13 23:50:54 +02:00
|
|
|
impl Future for HttpMessageBody {
|
2019-11-20 18:33:22 +01:00
|
|
|
type Output = Result<Bytes, PayloadError>;
|
2019-03-17 08:48:40 +01:00
|
|
|
|
2019-11-20 18:33:22 +01:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
2019-03-17 08:48:40 +01:00
|
|
|
if let Some(ref mut fut) = self.fut {
|
2019-11-20 18:33:22 +01:00
|
|
|
return Pin::new(fut).poll(cx);
|
2019-03-17 08:48:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(err) = self.err.take() {
|
2019-11-20 18:33:22 +01:00
|
|
|
return Poll::Ready(Err(err));
|
2019-03-17 08:48:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(len) = self.length.take() {
|
|
|
|
if len > self.limit {
|
2019-11-20 18:33:22 +01:00
|
|
|
return Poll::Ready(Err(PayloadError::Overflow));
|
2019-03-17 08:48:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// future
|
|
|
|
let limit = self.limit;
|
2019-11-20 18:33:22 +01:00
|
|
|
let mut stream = self.stream.take().unwrap();
|
|
|
|
self.fut = Some(
|
|
|
|
async move {
|
|
|
|
let mut body = BytesMut::with_capacity(8192);
|
|
|
|
|
|
|
|
while let Some(item) = stream.next().await {
|
|
|
|
let chunk = item?;
|
|
|
|
if body.len() + chunk.len() > limit {
|
|
|
|
return Err(PayloadError::Overflow);
|
2019-03-17 08:48:40 +01:00
|
|
|
} else {
|
|
|
|
body.extend_from_slice(&chunk);
|
|
|
|
}
|
2019-11-20 18:33:22 +01:00
|
|
|
}
|
|
|
|
Ok(body.freeze())
|
|
|
|
}
|
|
|
|
.boxed_local(),
|
|
|
|
);
|
|
|
|
self.poll(cx)
|
2019-03-17 08:48:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-10 18:53:56 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2019-03-10 19:04:50 +01:00
|
|
|
use bytes::Bytes;
|
|
|
|
|
2019-03-10 18:53:56 +01:00
|
|
|
use super::*;
|
|
|
|
use crate::http::header;
|
2019-11-26 06:25:50 +01:00
|
|
|
use crate::test::TestRequest;
|
2019-03-10 18:53:56 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_payload_config() {
|
2019-04-07 23:43:07 +02:00
|
|
|
let req = TestRequest::default().to_http_request();
|
2019-03-10 18:53:56 +01:00
|
|
|
let cfg = PayloadConfig::default().mimetype(mime::APPLICATION_JSON);
|
|
|
|
assert!(cfg.check_mimetype(&req).is_err());
|
|
|
|
|
|
|
|
let req = TestRequest::with_header(
|
|
|
|
header::CONTENT_TYPE,
|
|
|
|
"application/x-www-form-urlencoded",
|
|
|
|
)
|
2019-04-07 23:43:07 +02:00
|
|
|
.to_http_request();
|
2019-03-10 18:53:56 +01:00
|
|
|
assert!(cfg.check_mimetype(&req).is_err());
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
let req = TestRequest::with_header(header::CONTENT_TYPE, "application/json")
|
|
|
|
.to_http_request();
|
2019-03-10 18:53:56 +01:00
|
|
|
assert!(cfg.check_mimetype(&req).is_ok());
|
|
|
|
}
|
2019-03-10 19:04:50 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_bytes() {
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
|
2019-03-10 19:04:50 +01:00
|
|
|
.set_payload(Bytes::from_static(b"hello=world"))
|
2019-04-07 23:43:07 +02:00
|
|
|
.to_http_parts();
|
2019-03-10 19:04:50 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
let s = Bytes::from_request(&req, &mut pl).await.unwrap();
|
2019-03-10 19:04:50 +01:00
|
|
|
assert_eq!(s, Bytes::from_static(b"hello=world"));
|
|
|
|
}
|
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_string() {
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
|
2019-03-10 19:04:50 +01:00
|
|
|
.set_payload(Bytes::from_static(b"hello=world"))
|
2019-04-07 23:43:07 +02:00
|
|
|
.to_http_parts();
|
2019-03-10 19:04:50 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
let s = String::from_request(&req, &mut pl).await.unwrap();
|
2019-03-10 19:04:50 +01:00
|
|
|
assert_eq!(s, "hello=world");
|
|
|
|
}
|
2019-03-17 08:48:40 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_message_body() {
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx")
|
|
|
|
.to_srv_request()
|
|
|
|
.into_parts();
|
2019-11-26 06:25:50 +01:00
|
|
|
let res = HttpMessageBody::new(&req, &mut pl).await;
|
2019-03-17 08:48:40 +01:00
|
|
|
match res.err().unwrap() {
|
|
|
|
PayloadError::UnknownLength => (),
|
|
|
|
_ => unreachable!("error"),
|
|
|
|
}
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "1000000")
|
|
|
|
.to_srv_request()
|
|
|
|
.into_parts();
|
2019-11-26 06:25:50 +01:00
|
|
|
let res = HttpMessageBody::new(&req, &mut pl).await;
|
2019-03-17 08:48:40 +01:00
|
|
|
match res.err().unwrap() {
|
|
|
|
PayloadError::Overflow => (),
|
|
|
|
_ => unreachable!("error"),
|
|
|
|
}
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::default()
|
2019-03-17 08:48:40 +01:00
|
|
|
.set_payload(Bytes::from_static(b"test"))
|
2019-04-07 23:43:07 +02:00
|
|
|
.to_http_parts();
|
2019-11-26 06:25:50 +01:00
|
|
|
let res = HttpMessageBody::new(&req, &mut pl).await;
|
2019-03-17 08:48:40 +01:00
|
|
|
assert_eq!(res.ok().unwrap(), Bytes::from_static(b"test"));
|
|
|
|
|
2019-04-07 23:43:07 +02:00
|
|
|
let (req, mut pl) = TestRequest::default()
|
2019-03-17 08:48:40 +01:00
|
|
|
.set_payload(Bytes::from_static(b"11111111111111"))
|
2019-04-07 23:43:07 +02:00
|
|
|
.to_http_parts();
|
2019-11-26 06:25:50 +01:00
|
|
|
let res = HttpMessageBody::new(&req, &mut pl).limit(5).await;
|
2019-03-17 08:48:40 +01:00
|
|
|
match res.err().unwrap() {
|
|
|
|
PayloadError::Overflow => (),
|
|
|
|
_ => unreachable!("error"),
|
|
|
|
}
|
|
|
|
}
|
2019-03-10 18:53:56 +01:00
|
|
|
}
|