in node.js, if using createReadStream() do you still need response.end() - javascript

node.js doc says
response.end([data], [encoding])
This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. The method, response.end(), MUST be called on each response.
but in the many examples given using using createReadStream, eg,
fs.createReadStream(filename,{...}).pipe(response)
I never see response.end() called.
it resonse.end() needed with createReadStream()? and, if so, where does it appear in the program flow - you don't want it called until the pipe is finished, right?

You do response.end() after reading is finished (end event) or you encounter an error (error event).
Check this example: http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/

Related

Trying to continously send async data to the browser: Cannot set headers after they are sent to the client? [duplicate]

I am a beginner to express.js and I am trying to understand the difference between res.send and res.write ?
res.send
res.send is only in Express.js.
Performs many useful tasks for simple non-streaming responses.
Ability to automatically assigns the Content-Length HTTP response header field.
Ability to provides automatic HEAD & HTTP cache freshness support.
Practical explanation
res.send can only be called once, since it is equivalent to res.write + res.end()
Example:
app.get('/user/:id', function (req, res) {
res.send('OK');
});
For more details:
Express.js: Response
res.write
Can be called multiple times to provide successive parts of the body.
Example:
response.write('<html>');
response.write('<body>');
response.write('<h1>Hello, World!</h1>');
response.write('</body>');
response.write('</html>');
response.end();
For more details:
response.write(chunk[, encoding][, callback])
Anatomy of an HTTP Transaction: Sending Response Body
res.send is equivalent to res.write + res.end
So the key difference is res.send can be called only once where as res.write can be called multiple times followed by a res.end.
But apart from that res.send is part of Express. It can automatically detect the length of response header.
But there may be be a chance of memory spike with res.send(), in case of large files, our application hangs in between .
One of the most important differences not indicated in any of the answers are "draining".
The res.write may return true or false. As of the documentation:
Returns true if the entire data was flushed successfully to the kernel
buffer. Returns false if all or part of the data was queued in user
memory. 'drain' will be emitted when the buffer is free again.
So, when doing res.write, the caller should hold off writing until the drain event emits if the res.write returned false.
All these are handled automatically in res.send. The trade off is the buffering you will have to do when using the latter.
I am also a beginner in this. But what I observed is that, if you write only res.write() the page will be loading continuously until you write res.end(). Whereas if you write res.send() there is no need of res.end(). res.send() basically it does both res.write() and res.end().
Suppose you have two line that needs to be shown up and you use res.send as
res.send("shows only First Line")
res.send("won't show second Line")
Then only first line will show up, whereas using res.write you have flexibility to write multiple line such as
res.write("Shows first line")
res.write("Shows second line")
res.send()
res.send() is equivalent to res.write()+ res.end().
basically, res.send is for express and res.write+res.end() is for bare metal node ways to send data.

Non existing property: EventEmitter memory error instead of proper error message

In a NodeJS 6.10.2/SailsJS 0.12.13 based JavaScript application I experience since several months a strange error behavior.
In a Sails controller, I try to retrieve a property of a literal object:
console.log(someObject.someProperty);
console.log("I am still here!");
However, in my case someObject is undefined. So, I'd expect to get an error like 'Cannot read property someProperty of undefined.' - and then either Node.js to stop completely or the code to go on (with the next console.log).
Instead, the code simply stops executing at that point and I get a strange warning: "(node:4822) Warning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit." It is however, unpredictable how often this error occurs. Somethings only once, somethings about 20 times right after each other.
What I found out so for is that it is somehow connected to the question whether there was already a response or not. Consider the following:
mySailsControllerFunction: function(req, res) {
console.log(someObject.someProperty);
console.log("I am still here!");
res.json({"foo":"dahoo"});
}
This will result in Sending 500 ("Server Error") response: ReferenceError: someObject is not defined - exactly what I expect.
However, now I first send some response and then trying to access my non existing property, turning the code into:
mySailsControllerFunction: function(req, res) {
res.json({"foo":"dahoo"});
setTimeout(function () {
console.log("Yeah!");
console.log(someObject.someProperty);
console.log("I am still here!");
},1000);
}
then I often get simply nothing: 'Yeah!' displayed, but nothing comes afterwards. The event listener error is sometimes there, sometimes not. Very strange.
Additionally, and strange enough, the problem seems to be somehow connected to the time passed since the start of Sails. I put the code you see above inside a Sails controller function which is called immediately after the clients re-connect. I then played around with the timeout values, restarting the Sails server several times. Outcome: If I set the timeout to 1s, in 4 of 5 tests, I will get the correct error behavior. For 10 seconds it is about 50%, for 30s the error will always be ignored without any console output.
However, if I put my test code outside of the Sails controller, I always get the correct error behavior by Node. So, I'm quite sure this is a wrong behavior of Sails, not Node.
Disclaimer: I don't know Sails. So it may or may not be related, but my answer may offer a clue.
From the Sails documentation:
http://sailsjs.com/documentation/reference/response-res/res-json
This method is terminal, meaning it is generally the last line of code
your app should run for a given request (hence the advisory usage of
return throughout these docs).
Thus, when you use res.json({"foo":"dahoo"});, Sails probably sends the response back to the client, closing the call sequence, which, if it uses Promises or some other async mechanism, may kind of "swallow" further code, as also suggested in an above comment. This is probably internal coding in Sails, so it's not immediately obvious from the outside WHY your second code block specifically doesn't work.
So you should stick to the first pattern: access your property first, and put res.json() at the end of the controller function.
For reference: I finally solved that issue.
There were, somehow hidden in the code, process exit handlers defined:
process.on('exit', myErrorFunction.bind());
process.on('SIGINT', myErrorFunction.bind());
process.on('uncaughtException', myErrorFunction.bind());
The problem was: The function in which these lines were in was bound to a cronjob. So, each time the cronjob executed, new handlers were registered. So, my assumption above (before vs. after response) was wrong: In fact everything worked till the cronjob was executed for the first time. From then on, it didn't. And eventually, the warning was fired (correctly!).
I would have never found out without this answer: Make node show stack trace after EventEmitter warning
You have to add one line of code to get the stack trace:
process.on('warning', e => console.warn(e.stack));
Additionally, speaking of stack traces: In the Sails serverError response (api/api/responses/serverError.js), it is convenient to access it like this:
module.exports = function serverError (data, options) {
console.log(data.stack);
/* ... */
};

Wait for an event to trigger inside Node.js process

First of all, I am well aware that Node.js is non-blocking before anything else, but in this very specific case, it must be blocking and waiting here.
I have an authentication process that works that way (using APIs, I didn't design this so I cannot modify the way the auth works):
I send a PUT request to a REST API, I get a HTTPResponse code that determines if the API understood the request.
The server I just requested through its API sends the full response (including error codes, etc) through an XMPP protocol.
This means, when I send the request, I cannot know what happened next, and must wait for the XMPP event to trigger (basically, an on("message", callback) event).
I'd like to know how to work with this with Node.js.
Two more things to know:
1) I'm working on a client/server architecture, and my Node.js server is doing this authentication process, and sending a response through the websocket to the client and waiting for a socket answer is out of the question (not my call, but my boss wants this process to be done in one pass).
2) It must not be done with the client socket and must go through the full Node.js process for various reasons.
Thanks a lot for your help people! \o/
Sorry for not answering previously, we had some severe hardware failure at work.
Anyway, I'm not answering one of your comments directly because I found a solution I prefer, even if I thank you for your help. I've decided to use a promise and to wait for its answer to be sure to get a proper response.
Here is the code:
var answer = await new Promise((accept, reject) => {
// If there are no stanza in 30 seconds, then the process failed or the stanza got missed.
setTimeout(() => {
reject("timed out");
}, (30 * 1000));
// Waiting for the xmpp event to trigger.
xmpp.on("stanza", function(stanza) {
// Processing of the received stanza goes here.
});
});
#gkatzioura solution was interesting, but this looked a little bit heavy on bandwidth and we are working on a large scale applications, or maybe I didn't fully understand it, then it is my mistake.
#pspi solution was also interesting but this would be a problem considering the XMPP event listener is inside the request, and the PUT request needs to send a body on its end() event and here it wouldn't really work for what I want to do. I think that's because the original post I made was somewhat unclear.
Thanks a lot for your help guys! :]
I don't know enough XMPP, but would this just be case of "putting dependent logic inside callback".
request.put(..., function () {
// dependent xmpp logic inside request callback
xmpp.on(..., function () {
// xmpp and put response received, now talk back to socket client
socket.send(...);
});
});
In your case I would proceed with the event emitter (or anything in a publish subscribe fashion).
Fire your http call and inside the handler add an emitter listener with a check if the events is for the corresponding authentication.
Meanwhile your xmpp connection once it receives the authorization it shall emit a message.
The listener will receive the message successfully and will use the callback of the http call.

Custom error with Parse.com Cloud Code (server) and iOS (client)

I have a Parse Cloud Code written in JavaScript, I have an code-based system so I have 3 different modes:
Code is found and have't been used before - SUCCESS
Code is found and have been used before - ERROR
Code isn't found - ERROR
Now, when the client (iOS) gets the success - everything works fine and the code is OK. But I want to determinate between the 2 errors I have and tell the user what's wrong (your code isn't available anymore/code not found), but the error code Parse sends is always 141, so I don't know which message should I print to the user.
How can I change the error code of the error/another way to detect what error is it on client/server side?
Thank you!
From https://parseplatform.github.io/docs/js/guide/#error-codes:
ScriptFailed 141 Cloud Code script failed. Usually points to a JavaScript error. Check error message for more details.
FunctionNotFound 141 Cloud function not found. Check that the specified Cloud function is present in your Cloud Code script and has been deployed.
JobNotFound 141 Background job not found. Check that the specified job is present in your Cloud Code script and has been deployed.
SuccessErrorNotCalled 141 success/error was not called. A cloud function will return once response.success() or response.error() is called. A background job will similarly finish execution once status.success() or status.error() is called. If a function or job never reaches either of the success/error methods, this error will be returned. This may happen when a function does not handle an error response correctly, preventing code execution from reaching the success() method call.
MultupleSuccessErrorCalls 141 Can’t call success/error multiple times. A cloud function will return once response.success() or response.error() is called. A background job will similarly finish execution once status.success() or status.error() is called. If a function or job calls success() and/or error() more than once in a single execution path, this error will be returned.
So looking above, you could have a Javascript error occurring during the function's run. You could be spelling the function name wrong when calling. You could forget to call response.success() to properly close the function. Or you could be calling response.success() / response.error() too many times, make sure that as you follow your code's logic, you only hit one of these for every path.
If you could post the code for your Cloud Code, we might be able to further help you.

NodeJS http module: what is requestListener?

I'm new to JS and more specifically Node. Even after reading the api docs, I'm confused about what 'requestListener' is in the following method.
http.createServer([requestListener]);
Searching google revealed that 'requestListener' is a(n) (anonymous) function with the following signature:
function (request, response) { };
I suppose I'm reading the docs incorrectly, hopefully someone can point me in the right direction.
The docs say that the method call takes a function which will be called when a new request is received by your application. This function, as you correctly stated in your question, takes two arguments - a request and response objects.
You should inspect the contents of these objects to learn what information is available to you. Also, take a look at the API docs for request and response.
The function is optional; you could also attach the request handler in the following way:
var server = http.createServer()
server.on('request', function (req, res) {
// Process the request here
})
In practice, this function is called when someone opens up your website in their browser (i.e. issues a GET http request). The purpose of that function is to provide a HTTP response body back to the client, i.e. render a web page or perform any business logic as necessary.
To directly answer your question: it's a function that gets called when a request is received by the server and is given those two parameters.
At the very least you can experiment with doing a console.log(request, response) inside the function and see what is spit out in your terminal.
But that's only the beginning of the rabbit hole. You should read up on "callback functions", as they are integral to how Node (and quite a bit of client-side javascript) operates (asynchronously).
The http.createServer method creates a server object.
The server object has a listen method. If you invoke the listen method, for example:
createServer(requestListener).listen({ port:80 });
the server object will be listening on port 80, and when a Http request is received on that port, the server object will invoke the function requestListener, passing it two objects, of type request and response. So you can write your requestListener like, for example:
function requestListener(req, res) {
res.write("Hello world");
res.end();
}
and it will push out the string Hello world to every url that is hitting your this simple web server.
write is one of the many methods of the response object.
You can run the above few lines of code on your PC, and point your browser to http://localhost.
If you have other applications listening on port 80, then use a different port number in your listen method.
Using an anonymous function for requestListener is merely a different coding pattern, for better or for worse. My code above can be re-written as:
createServer((req, res) => {
res.write("Hello world");
res.end();
}).listen({ port:80 });
The above code is very rudimentary and will send the same response to every Http request that hits it. The code does not differentiate between localhost/page1 or localhost/page2, etc. So to do anything more, the requestListener have to be expanded significantly to parse different paths in the url and to decide on what content to send for each. But to do anything useful as a real web server without writing too much code, you will need a package. Express is an excellent one that drives many real life web servers.

Categories

Resources