read stream from event twice
I'm trying to find a way to read a stream (from an h3 event ) twice. Once to chez its size and once to actually use it.
I tried this: but .values doesn't exist on req
I tried creating a readableStream, but then I can't find how to actually read it.
I tried to create a new h3event with createEvent, but I can't figure out how to do it properly.
So, is there a way to read the stream twice ?
Is there a way to read a readableStream ?
What should I do ?
I want to measure the incoming stream to prevent gigantic files from getting uploaded
From what I've found, just checking the .size value might not be completely safe.
By reading it chunk by chunk, we can stop the stream if the limit is reached, and the server wont have to store 100gb in case of an attack.
Does that make sense ? is it stupid ?
9 Replies
Hi @Eric. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Your question is about handling streams in the context of Nuxt and H3, which is relevant to my expertise. Let me address your concerns based on the provided knowledge sources.
Your approach of trying to read the stream twice to check its size and then use it is on the right track, but there are some issues with the implementation. Let's break down the problem and provide a solution.
1. Reading the stream twice:
Unfortunately, streams are typically consumed only once. Once you've read from a stream, you can't rewind it. This is why your attempt to read it twice doesn't work as expected.
2. Checking the size:
Your reasoning for wanting to check the size chunk by chunk is correct. It's a good practice to prevent potential attacks or unintended large file uploads.
3. Implementation:
Instead of trying to read the stream twice, you can use the
readRawBody
utility from H3, which allows you to read the body of the request as a stream. Here's how you can implement this:
This implementation uses the readRawBody
utility from H3, which is documented in the H3 Body utils section. The readRawBody
function allows you to provide a callback that is called for each chunk of the body as it's being read. This enables you to check the size as the stream is being consumed.
Your approach of checking the size chunk by chunk is indeed a good practice. It allows you to stop processing as soon as the limit is reached, without having to store the entire payload in memory. This is particularly useful for preventing potential attacks or unintended large file uploads, as you mentioned.
To answer your specific questions:
1. Is there a way to read the stream twice?
Generally, no. Streams are typically consumed once. Instead, you should process the stream as you read it, as shown in the example above.
2. Is there a way to read a ReadableStream?
Yes, you can use the readRawBody
utility from H3 to read a ReadableStream.
3. What should you do?
Use the readRawBody
utility as shown in the example above. This allows you to check the size as you read the stream and process it in one go.
4. Does your approach make sense? Is it stupid?
Your approach is not stupid at all. In fact, it's a good practice for handling potentially large uploads securely. Checking the size as you read the stream is more efficient and secure than reading the entire stream into memory before checking its size.
Remember to handle errors appropriately and send proper responses to the client when limits are exceeded or other errors occur.
H3 Body utils
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@776374982275497985> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Hello
What do you mean by use it ?
Can you just start stacking it into a Buffer and stop if it becomes too large ?
Sometimes the source includes a Content-Length, did you check just in case of ?
HI ! thanks for you help ! Yes I tried a loop that reads the stream chunk by chunk, store everything in a variable, adds up the total size and stop if the size reaches the max size.
But i couldn't figure out what to do with it after.
I was thinking of adding a check to Content-Length too, but it's bot perfectly safe because it is set client side. A malicious usr could temper with it. this reads, measure and stores the data. But what do I do with chunks after ?
I was thinking of adding a check to Content-Length too, but it's bot perfectly safe because it is set client side. A malicious usr could temper with it. this reads, measure and stores the data. But what do I do with chunks after ?
Well it depends, what is the blob/file about ? What do you want to do with it ?
For exemple if it's an image you want to store on a S3, you could :
- Use somthing like putstream to put it chunk by chunk (and cancel it if too large or something)
- concat the chunks and upload it in one go with a basic put
the incoming data is a formData that needs to be sent to a Directus server. It contains data ile id, userid, etc.. and an image. I need to parse it to make two different requests to Directus. Before trying to add the size check , I read it to obtain an array aof values , filter it to create the two request.
once chunks is concatenated , it is still not readable, right ? do you know how I can read it to turn it into an array of usable data objects ?
sorry I use adonis as a backend, I do use the chunks on the file part but it treats the data for me on the parameters part ^^"
To handle the chunks after reading them, you need to concatenate them into a single Buffer and then parse the data. Since the incoming data is formData, you can use a library like formidable or busboy to parse the multipart form data. Here's how you can do it:
With bussboy
Multipart Form Data with Nitro and h3
Thanks guys for your help. I had to go to another project , so I couldn't set this up, but I'll come back to it in 2 weeks.
Thanks again!!