-
How can I handle how long the body can be to prevent a DoS attack on uploading of a document such as a pdf or form data. For example, I want to handle uploading a PDF but the PDF must not be more than 30MiB. how do I add this to trillium so that on streaming the data from the client, trillium immediately returns an error when an upload data exceeds 30MiB. The ideal scenario would be that it must not hold all the form data in memory first before it calculates its size (so as not to result in huge memory allocation), but instead it must calculate the size as the data is streaming in and circuit break immediately the data size exceeds the set threshold. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
This is a great question, and not one with a preexisting solution. I'm not at all sure if this is something trillium-http should handle internally, as it can potentially be handled in user code. In order to recommend a specific solution: How are you consuming the request body? Are you streaming it to disk or reading into memory? Here's one possible solution for handling this outside of trillium: |
Beta Was this translation helpful? Give feedback.
-
I am looking for a solution for both in-memory and streaming to disk. An example for in-memory would be like a form that would support uploading an essay with words not maximum of 1MiB when converted to bytes (like 500 words), here an adversary would do a DoS if they upload say 1GiB worth of words especially on multiple connections. Here for the gist you shared I thought it would have a cleaner API than this: pub struct Limit<T> {
reader: T,
length: usize,
max: usize,
}
impl<T> Limit<T> {
pub fn new(reader: T, max: usize) -> Self {
Self {
reader,
length: 0,
max,
}
}
}
impl<T> AsyncRead for Limit<T>
where
T: AsyncRead + Unpin,
{
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<usize>> {
let new_bytes = ready!(Pin::new(&mut self.reader).poll_read(cx, buf))?;
self.length += new_bytes;
if self.length >= self.max {
Poll::Ready(Err(Error::new(
ErrorKind::InvalidData, // or if on nightly, ErrorKind::FileTooLarge
"max length exceeded",
)))
} else {
Poll::Ready(Ok(new_bytes))
}
}
} I have used rocket.rs before and this was so easy. Pardon me, trillium probably might not have the same goals but to provide some context, here is rate limiting documentation provided by rocket |
Beta Was this translation helpful? Give feedback.
This is a great question, and not one with a preexisting solution. I'm not at all sure if this is something trillium-http should handle internally, as it can potentially be handled in user code. In order to recommend a specific solution: How are you consuming the request body? Are you streaming it to disk or reading into memory?
Here's one possible solution for handling this outside of trillium:
https://gist.github.com/jbr/d92f3a4b139f64a2bac3903bdea54247