Replies: 1 comment 2 replies
-
Rocket is purposefully making it very hard for you to do this. You should never read the entire response body data. It is not only inefficient but also logically incorrect as the data is potentially infinite. This makes it a trivially exploitable DoS attack vector. Even if the data isn't infinite, it could still be problematic. For example, if a large file is being returned, your implementation will read the entire file into memory. This is not only another example of a DoS vector, but also very slow. I would suggest a more Rockety / Rusty approach. Here you're taking any response type T and attempting to hash it to generate an ETag. A better strategy would be to parameterize the generic on a trait that provides the hash. That is: enum Tag {
Weak(..),
Strong(..),
}
trait Taggable {
async fn tag(&self) -> Tag;
}
impl<T: Taggable> ETag<T> {
async fn new(item: T) -> Self {
let tag = item.tag().await;
ETag(tag, item)
}
} A good implementation for File (and NamedFile) would be to use the hash of the modification time and/or other metadata. This gives you a hard hash. For strings, you could decide to use a weak hash of its length or actually hash the string - but at least the string is already in memory and you don't create a second copy of it to do so. With specialization, you could also make this work efficiently for a lot of types with very little effort. |
Beta Was this translation helpful? Give feedback.
-
^ this compiles because I use pollster to block on the future, which is less than ideal obviously.
not sure how else to build this? I was trying to reuse rocket's serialization of the responder, to avoid serializing twice.
i see in the docs that an async constructor is recommended, but i don't think this can apply since i need access to the serialized response in order to create an etag (which is the entire point)
Beta Was this translation helpful? Give feedback.
All reactions