2021-06-23 14:56:02 +02:00
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Context, Poll};
|
|
|
|
|
2021-09-08 12:34:56 +02:00
|
|
|
use actix_web::error::PayloadError;
|
2021-06-23 14:56:02 +02:00
|
|
|
use actix_web::{dev, web, FromRequest, HttpRequest};
|
|
|
|
use futures::future::{ready, Ready};
|
|
|
|
use futures::Stream;
|
|
|
|
|
|
|
|
pub struct Payload {
|
|
|
|
payload: dev::Payload,
|
|
|
|
limit: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PayloadConfig {
|
|
|
|
limit: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PayloadConfig {
|
|
|
|
pub fn new(limit: usize) -> Self {
|
|
|
|
Self { limit }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PayloadConfig {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self { limit: 256 * 1024 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromRequest for Payload {
|
|
|
|
type Error = PayloadError;
|
|
|
|
|
|
|
|
type Future = Ready<Result<Payload, Self::Error>>;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
|
|
|
|
let limit = req
|
|
|
|
.app_data::<PayloadConfig>()
|
|
|
|
.map(|c| c.limit)
|
2022-01-21 21:44:17 +01:00
|
|
|
.unwrap_or(PayloadConfig::default().limit);
|
2021-06-23 14:56:02 +02:00
|
|
|
ready(Ok(Payload {
|
|
|
|
payload: payload.take(),
|
|
|
|
limit,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stream for Payload {
|
|
|
|
type Item = Result<web::Bytes, PayloadError>;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
|
|
match Pin::new(&mut self.payload).poll_next(cx) {
|
|
|
|
Poll::Ready(Some(result)) => match result {
|
|
|
|
Ok(bytes) => match self.limit.checked_sub(bytes.len()) {
|
|
|
|
Some(new_limit) => {
|
|
|
|
self.limit = new_limit;
|
|
|
|
Poll::Ready(Some(Ok(bytes)))
|
|
|
|
}
|
|
|
|
None => Poll::Ready(Some(Err(PayloadError::Overflow))),
|
|
|
|
},
|
|
|
|
x => Poll::Ready(Some(x)),
|
|
|
|
},
|
|
|
|
otherwise => otherwise,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|