Express.js send response before end of execution - node.js

In a Express application I would like to do something like this:
app.get('/some/route', someMiddleWare(), function(req, res){
var status = undefined;
if( /*someCondition*/ ) status = 200;
else status = 403
res.status(status).send('');
// do something else
})
In the first part I do something that is needed in order to decode what response to give, in the second (after send()) I do something additional that needs to be done in the same execution (i.e. not asynchronously) but does not really concern the user.
The question is: can I be sure that after send() returns the response is already on its way back to the user? Or is it sent only after the execution of my handler function?
Thanks

Yes. You're code will execute in the function even after you send the data through res.send().
However, after you use res.send() you will no longer be able to send any other data with that same response to that request.

The question is: can I be sure that after send() returns the response
is already on its way back to the user? Or is it sent only after the
execution of my handler function?
Yes, you can be sure the data is on its way. At the point you call res.send(), the data has been written to the underlying TCP infrastructure and it is then up to the TCP stack to send it. Due to TCP Nagle algorithm, there might be a short delay before the data is sent, but it will not be waiting for anything in your Express application. The data will be sent as soon as the TCP stack decides to send it.
It won't matter whether you are doing something else in the request handler after you send the response or not.
If you want to follow the actual source code for this, you first look at res.send(data) in express and that ultimately ends up calling res.end(data) in the http module. And, by looking at the http module, you can see that it is writing the data to the TCP implementation synchronously when it is called. There are no magic delays waiting for other things to happen in Express.

Related

Is there any workaround to send response until a promise is finished and send another response after it is finished in nodejs express

I have a promise call which takes a long time to return. So I need to send some response like "In progress" until the response is returned. Once it is returned , I need to send another response saying "Done".
I want this in Nodejs-Express App
How to do it?
Using SocketIO would be an option as you would maintain a stream of data open while it is required. But you go beyond of a simple http Express server ...

what happens if neither res.send() nor res.end() is called in express.js?

I have a security issue that someone is trying to call random APIs that are not supported on our server but are frequently used for administrators API in general. and I set this code below to handle 404 to not respond to this attack
url-not-found-handler.js
'use strict';
module.exports = function () {
//4XX - URLs not found
return ((req, res, next) => {
});
};
what happens to client is that it waits until the server responds but I want to know if this will affect the performance of my express.js server also what happens behind the scene in the server without res.send() or res.end() ?
According to the documentation of res.end().
Ends the response process. This method actually comes from Node core,
specifically the response.end() method of http.ServerResponse.
And then response.end
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.
If you leave your request hanging, the httpserver will surely keep data about it. Which means that if you let hang many requests, your memory will grow and reduce your server performance.
About the client, he's going to have to wait until he got a request timeout.
The best to do having a bad request is to immediately reject the request, which is freeing the memory allowed for the request.
You cannot prevent bad requests (maybe have a firewall blocking requests from certains IP address?). Best you can do is to handle them as fast as possible.

node, is each request and response unique or cached irrespective of url

In an app that I was working, I encountered "headers sent already error" if I test using concurrency and parallel request methods.
ultimately I resolved the problem using !response.headersSent but my question is why am I forced to use it? is node caching similar requests and reuses them for the next repeated call.
if(request.headers.accept == "application/json") {
if(!response.headersSent) {response.writeHead(200, {'Content-Type': 'application/json'})}
response.end(JSON.stringify({result:{authToken:data.authToken}}));
}
Edit
var express = require('express');
var app = express();
var server = app.listen(process.env.PORT || 3000, function () {
console.log('Example app listening at http://%s:%s', server.address().address, server.address().port);
});
Edit 2:
Another problem is while testing using mocha, super agent and while the tests in progress if I just send another request through postman on the side, one of the tests in mocha end with a timeout error. These steps I'm taking to ensure the code is production ready for simultaneous, parallel requests? please advise on what measures I can take to ensure node/code works under stress.
Edit 3:
app.use(function(request, response, next){
request.id = Math.random();
next();
});
OK, in an attempt to capture what solved this for you via all our conversation in comments, I will attempt to summarize here:
The message "headers sent already error" is nearly always caused by improper async handling which causes the code to call methods on the response object in a wrong sequence. The most common case is non-async code that ends the request and then an async operation that ends some time later that then tries to use the request (but there are other ways to misuse it too).
Each request and response object is uniquely created at the time each individual HTTP request arrives at the node/express server. They are not cached or reused.
Because of asynchronous operations in the processing of a request, there may be more than one request/response object in use at any given time. Code that is processing these must not store these objects in any sort of single global variable because multiple ones can be in the state of processing at once. Because node is single threaded, code will only be running on any given request at any given moment, but as soon as that code hits an async operation (and thus has nothing to do until the async operation is done), another request could start running. So multiple requests can easily be "in flight" at the same time.
If you have a system where you need to keep track of multiple requests at once, you can coin a request id and attach it to each new request. One way to do that is with a few lines of express middleware that is early in the middleware stack that just adds a unique id property to each new request.
One simple way of coining a unique id is to just use a monotonically increasing counter.

express response with a callback

Is it possible to send a response from express, and wait for a return response before continuing?
A typical scenario is something like this
Server A sends a request to server B.
Server B processes the request and sends to back to server A
Server B waits for a response from server A before continuing
Server A does further processing of the response from Server B and sends it back to Server B
Server B then handles the rest of the processing required.
My understanding is that normally this is handled with callbacks. In express I would expect to do something like
res.write('response', callback);
function callback() {
//do stuff
}
I don't see that this is possible with the res.write method though. Is there another method I can use with express to get this functionality? I've never used socket.io before, but this seems like a scenario where websockets would be useful. Am I wrong in this assumption?
res.on('finish', callback);
is sent when the last of the data is given to the OS to deal with.
http://nodejs.org/api/http.html#http_event_finish
If you need to know when the client receives/processes the data, however, the client must send something back to the server, in which case socket.io could help.
I appreciate all the responses and help from everyone, I ended up using sessions to get what I needed.
var session = require('express-session');
Thanks again

Connecting to a Reliable Webservice with Nodejs

My application needs to receive a result from Reliable Webservice. Here is the scenario:-
First I send a CreateSequence request. Then the server replies with a CreateSequenceResponse message. Next I send the actual request to the webservice.
Then the webservice send a response with 202 accept code and sends result in a later message. All these messages contain the header Connection: keep-alive.
I made request with http.ClientRequest. I could capture all responses except the result. http.ClientRequest fires only one response event.
How can I receive the message which contains the result?
Is there any way to listen to socket for remaining data (socket.on('data') did not work). I checked this with ReliableStockQuoteService shipped with Apache Synapse. I appreciate if someone can help me.
When you get the response event, you are given a single argument, which is an http.IncomingMessage, which is a Readable stream. This means that you should bind your application logic on the data event of the response object, not on the request itself.
req.on('response', function (res) {
res.on('data', console.log);
});
Edit: Here is a good article on how to make HTTP requests using Node.

Resources