Comments (11)
Streaming without the total source size has been added in 5.1.1. It uses the write() method effectively using chunked transfer method to serve data. The only downside to this is that no content-length is specified and the write() method does not handle backpressure so there is no way to guarantee that all sent data was received. You still have the option to use handled transfer by specifying a total size.
from hyper-express.
Interesting, will push this fix in an update soon and still keep tryEnd as an option so users who want the content-length header for whatever reason can specify a total_size.
from hyper-express.
The stream method was implemented based on the official streaming example from uWebsockets.js repository (See https://github.com/uNetworking/uWebSockets.js/blob/master/examples/VideoStreamer.js).
Under the hood, the Response.stream() method uses uWS.Response.tryEnd(chunk, totalSize) method which requires a totalSize parameter (I am assuming this has to do with how uWebsockets serves chunks and responds to backpressure under the hood).
The only somewhat hacky way I can think of implementing streaming with uWebsockets.js without knowing the total size would be to provide an artificially high totalSize to the tryEnd method until the Readable.on('end') event is fired upon which we serve an empty chunk and the totalSize is specified as the total amount of bytes sent which can be tracked using a private variable. Will look into implementing this now and see if its viable.
from hyper-express.
Nodejs streams will handle backpressure too (https://nodejs.org/en/docs/guides/backpressuring-in-streams/), so using the write method instead of tryEnd of the uws response wrapped as a Writable would probably be sufficient for most use cases. At worst the pressurized? data will get cached and use up memory on the machine, which is likely still better than having the entire response in memory. It's possible that the write method of the uWS response does backpressure handling too, honestly I don't know.
I believe that totalSize is used to set the content-length header, which would get written on the first write, meaning the client would likely fail because the response was the wrong size.
But I see that the write method on the hyper-express response does write the headers correctly as of 5.1, so I can wrap it in a writable myself as a work around. It would be nice if this framework supported it natively though.
Btw my use case is streaming large amounts of data out of a database, so I can't possibly know the size of it without caching the entire thing in memory or causing an extra load on the database to calculate the size.
from hyper-express.
No, so the way Node.js handles backpressure is based on when you trigger the callback from the write handler. The thing is the uWS.write() method does not return a Boolean value to signify backpressure which means we have no choice but to call the callback from the write handler after making the uWS.write() call. With this we will write all chunks every time even if some chunks failed with backpressure. This is precisely the reason why the example from uWebsockets.js repository uses tryEnd for streaming the video file. I am actually not sure what the purpose of the write method it writes body chunks without returning any signal to handle backpressure.
Code Example:
const stream = new Writable({
write: (chunk, encoding, callback) => {
response.write(chunk); // This method does not return a Boolean to tell us whether this chunk was sent or not
callback(); // We have no choice but to call the callback thus Node will continue streaming even though we may not be sending any chunks
}
})
from hyper-express.
No, so the way Node.js handles backpressure is based on when you trigger the callback from the write handler. The thing is the uWS.write() method does not return a Boolean value to signify backpressure which means we have no choice but to call the callback from the write handler after making the uWS.write() call. With this we will write all chunks every time even if some chunks failed with backpressure. This is precisely the reason why the example from uWebsockets.js repository uses tryEnd for streaming the video file. I am actually not sure what the purpose of the write method it writes body chunks without returning any signal to handle backpressure.
Code Example:
const stream = new Writable({ write: (chunk, encoding, callback) => { response.write(chunk); // This method does not return a Boolean to tell us whether this chunk was sent or not callback(); // We have no choice but to call the callback thus Node will continue streaming even though we may not be sending any chunks } })
Ah, good point. Perhaps uWS will just not return from the write method if it's experiencing too much backpressure... Thanks for the super quick updates :D
from hyper-express.
Actually, it looks like write does return a boolean. I'm super noob at c++ so I might be reading this wrong...
template <bool SSL>
static void res_write(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
auto *res = getHttpResponse<SSL>(args);
if (res) {
NativeString data(args.GetIsolate(), args[0]);
if (data.isInvalid(args)) {
return;
}
bool ok = res->write(data.getString());
args.GetReturnValue().Set(Boolean::New(isolate, ok));
}
}
That isolate thing handles js context if I'm understanding correctly, and the GetReturnValue gets passed the ok boolean from write.
from hyper-express.
The docs disagree though... Weird....
https://unetworking.github.io/uWebSockets.js/generated/interfaces/HttpResponse.html#write
from hyper-express.
Opened an issue with uWebSockets.js uNetworking/uWebSockets.js#638
from hyper-express.
Heh, it does return a boolean. uNetworking/uWebSockets.js#638 (comment)
from hyper-express.
https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
A sender MUST NOT send a Content-Length header field in any message
that contains a Transfer-Encoding header field.
The only downside to this is that no content-length is specified
Seems like this is not an issue.
from hyper-express.
Related Issues (20)
- `res.cookie` is incompatible with express HOT 1
- A build error appeared with version 6.14.2 with TypeScript types definition HOT 1
- How to use `compression`? HOT 6
- Can't handle error in global error handler
- Default Encoding problems with accents HOT 1
- HI kartik, I'm sorry for the stupid question, but I need to learn how to work with this by example, can you show me?) HOT 3
- Handling multiple multipart HOT 7
- Question: Is there support for HTTP3 / QUIC ? HOT 1
- Feature request: swagger HOT 1
- No error thrown if invalid json is sent as body HOT 4
- From version 6.0.0, the response component doesn´t call a close or abort event when the SSE client is closed HOT 1
- Nest-hyper-express-adapter middleware tests failing HOT 4
- Nest-hyper-express instance and local-pipes tests each fail one test HOT 3
- Outdated example of static serving / LiveDirectory HOT 1
- Error: uWS.HttpResponse must not be accessed after uWS.HttpResponse.onAborted callback HOT 1
- Graceful shutdown HOT 4
- Static serving HOT 1
- No error on binding to the same port HOT 1
- No Socket Received From uWebsockets.js likely due to an invalid host or busy port. HOT 2
- Optional Parameter Route HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hyper-express.