How to close HTTP connection in node.js using Express - javascript

I use node.js (Express) with server-sent events. I would like to close the event stream by closing the sse HTTP connection. Given the folllwing function:
router.get('/sse', function (req, res) {
});
how can this be achieved?

use this
res.end();
and it will work to close connection

How to hang up in ExpressJS
Ⅰ. End the response, keeping the socket connection alive.
response.end();
Ⅱ. “Could you please hang up first?”
Request the client to initiate the TCP socket connection termination sequence.
response.set("Connection", "close"); // Note: this is an HTTP header.
Ⅲ. Gently close the socket connection.
“Hey, I’ll be hanging up now, ’kay?”
response.connection.end();
socket.end([data[, encoding]][, callback])
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data.
See writable.end() for further details.
Ⅳ. Just hang up on the client aggressively. No FIN packet, even.
response.connection.destroy();
socket.destroy([error])
Ensures that no more I/O activity happens on this socket. Destroys the stream and closes the connection.
See writable.destroy() for further details.

Selected answer is incorrect, res.end() ends the response and writes to the socket. But it doesn't close the TCP connection.
You need to get the underlying connection from the res object and call end on it to close it.
res.connection.end();

Related

Socket state pending forever in Javascript and Node

// client.js
const webSocket = new WebSocket('wss://127.0.0.1:8081');
webSocket.addEventListener('open', (message) => {
alert(message);
})
const text = document.getElementById('text');
const button = document.getElementById('button');
button.onclick = () => {
webSocket.send(text.value);
}
// server.js
import { Server } from 'net';
const server = new Server();
server.on('connection', (socket) => {
console.log(socket);
socket.on('data', (data) => {
})
});
server.listen(8081, '127.0.0.1', () => {
console.log('Server running at port 8081');
});
The problem that I'm facing is:
When I load the page the socket is printed in the console of the server (I can get the remote address and remote port)
No matter what I do, the connection in the client is always pending. I tried Chrome, Brave, Mozilla and Safari and no one seems to work.
What am I missing? I tried to not send the message until the connection is ready, but I never get that state in my PC. The alert in the client never pops, even if I establish the onopen property without an event.
Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
at button.onclick
A webSocket client must connect to a webSocket server. webSocket is a specific connection algorithm (that starts with an http request and then switches to the webSocket protocol) and a specific data format. So, a webSocket client must have a webSocket server to connect to. Your server is a generic TCP server that does not support webSocket connections.
The client will initially establish a TCP socket to your server, then send an http request over that socket, and then it will sit there waiting for an appropriate response to the http request it sent. Since your server never sends that response, it will just sit there waiting until eventually it will timeout and close the socket. This is why you see it stuck in the pending state. It's still waiting for the rest of the webSocket connection sequence to happen and it never does.
If you're curious how the webSocket connection scheme and data format work, you can see a nice description of it here.
Relevant StackOverflow answers:
How does WebSockets server architecture work?
What's the difference between WebSocket and plain socket communication?
Do websocket implementations use http protocol internally?
Overview of webSocket connection scheme
How WebSocket server handles multiple incoming connection requests?

NodeJs multiple reply for requests after connecting to server

when my device is disconnected from server or device don't have internet connection, after emitting multiple socket to server that cause of reply to all sockets after connecting to server
for example:
1- client disconnected from server, i click multiple on button to emit data for example 10 click as request
2- after connecting client to server, server reply on 10 response
how can i manage this process?
problem resolved, Thanks to #farhadamjady
var mySocket = io.connect('http://192.168.1.4:8080/backend_app', {transports: ['websocket'], reconnection: true});
mySocket.on('connect', function () {
mySocket.sendBuffer=[]
console.log('Connected!');
});

What happens to the request stream in node before it is consumed?

I am working on a node application where I pipe a post request's body into a writable stream that saves the data to disk. I realized while building this application that I have no idea what actually happens to the request stream before it is consumed. Say I did something like this:
app.post('/api/data', (req, res) => {
const writableStream = fs.createWriteStream('data.txt');
setTimeout(() => {
req.pipe(writableStream);
}, 3000);
});
What is actually happening to the stream in the 3 seconds between when the request is initially received and when the stream starts being piped? Is it being loaded into memory?
Streams support a buffer for incoming data, but when the buffer fills up, they tell the sender to stop sending more data until they are ready for some more.
Since an incoming request is actually a TCP connection and incoming data is data arriving on the TCP connection, this probably turns into more a question about what happens to incoming TCP data when you aren't reading the data as fast as it wants to arrive. The answer is that TCP supports flow/control where the receiver tells the sender to stop sending data for the moment and then when incoming buffers clear, it tells the sender it can start sending data again.
Here's a quick overview of TCP flow control.
In your specific stream coding example, until you issue the req.pipe(), there are no data listeners on the stream so it has nothing to do with incoming data. Thus, it will fill up its buffers from the incoming TCP stream, stop reading more from the incoming TCP socket (which will trigger TCP flow control). Then, when you run the req.pipe() that automatically registers handlers for data events and the stream will start triggering those events. As data is read out of the stream buffer, it will then be able to accept more incoming data from the TCP socket which will allow TCP to tell the other end of the TCP socket to restart the incoming flow of new data and so on.
There's a lot more here about how readable streams work: http://www.sitepoint.com/basics-node-js-streams/ and how they can be paused or resumed.

Keep Node JS connection opened and write (GET Request)

I was trying to implement a NODE JS get method where I could encode in the url parameters and send back responses like in Server Sent Events.
For example, when I used:
curl -D- 'http://localhost:8030/update'
The server would return a message, and then keep the connection opened to return more messages (like Push).
I was using require('connect'), I tried with require('express') but can't get it working.
Here's part of my code:
var http = require('http');
var connect = require('express');
var app = connect();
app.use(bodyParser.urlencoded({ extended: false }))
.use(bodyParser.json()) // JSON
.use(cors(corsOpts))
.get('/update', updateMiddleware);
var server = http.createServer(app);
server.listen("twserver.alunos.dcc.fc.up.pt", 8030);
function updateMiddleware(req, res) {
res.setHeader('Connection', 'keep-alive');
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.writeHead(200);
setTimeout(function() {
res.write("this is an event");
res.flushHeaders();
}, 1000);
setTimeout(function() {
res.write("this is another event");
}, 2000);
// should print without ending
}
EDIT: I found it was working, but only in chrome. In terminal, I only receive it after waiting a long time, and messages come like in chunks.
You can't use a single HTTP request to listen for multiple event data. If you are really stuck with HTTP (i.e. WebSocket or WebRTC is not an option) then the technique you are looking for is called long polling. This basically works this way:
Client sends request to server
Server waits until an event happens (or until a specific but not too long timeout, so the client application does not throw a timeout error for the request)
Server responses with a complete http response, containing the details of the event
Client receives the event details and immediately sends another request to listen to further events.
This method really takes advantage of HTTP Keep-Alive
EDIT:
For me it looks like your code does not follow the protocol of server sent events. Here is a tutorial: Server-Sent Events in nodejs.
Following another tutorial on MDN about Server-Sent Events, the structure of the messages should be the following:
: this is a test stream
data: some text
data: another message
data: with two lines
Note that the data to be sent must be followed by a double new-line \n\n.
In general, http endpoints in Express aren't supposed to do things like that. If you want live event data, the best way is to use a web socket.
That being said, this thread has an example on how to force Express to do this.
socket.io or Webrtc is the best choice

socket.io server-side timeout for inactive client connection?

I know that the socket.io client library will close the current socket.io connection (and then attempt to reconnect) if it is not regularly receiving a response to the ping packets that it sends to the server (under the assumption that the connection has died for some reason). And, there are client options for controlling this reconnect behavior.
But, what happens server-side if a client goes inactive and stops sending ping messages (say because the client went to sleep)? I can't find any info in the socket.io server-side doc that explains that situation or allows for configuration of it. Will the server close an inactive client socket.io connection (one that it is not receiving ping messages from)? If so, how long will the server wait and is that behavior configurable?
As per the socket.io 2.20 readme (the latest version as of Jan 2020):
"A heartbeat mechanism is implemented at the Engine.IO level, allowing both the server and the client to know when the other one is not responding anymore.
That functionality is achieved with timers set on both the server and the client, with timeout values (the pingInterval and pingTimeout parameters) shared during the connection handshake."
So, you can configure both the server and client side timeout settings by setting the following timeout properties on the engine.io component inside of socket.io.
Using socket.io version 2.20:
const io = ...; // initialize socket.io how you wish
io.eio.pingTimeout = 120000; // 2 minutes
io.eio.pingInterval = 5000; // 5 seconds
The same thing using older versions of socket.io:
const io = ...; // initialize socket.io how you wish
io.set('heartbeat timeout', 1200000);
io.set('heartbeat interval', 5000);
Disconnection detection
The Engine.IO connection is considered as closed when:
one HTTP request (either GET or POST) fails (for example, when the server is shutdown)
the WebSocket connection is closed (for example, when the user closes the tab in its browser)
socket.disconnect() is called on the server-side or on the client-side
There is also a heartbeat mechanism which checks that the connection between the server and the client is still up and running:
At a given interval (the pingInterval value sent in the handshake) the server sends a PING packet and the client has a few seconds (the pingTimeout value) to send a PONG packet back. If the server does not receive a PONG packet back, it will consider that the connection is closed. Conversely, if the client does not receive a PING packet within pingInterval + pingTimeout, it will consider that the connection is closed.
The disconnection reasons are listed here (server-side) and here (client-side).
pingTimeout (Number): how many ms without a pong packet to consider the connection closed (60000)
pingInterval (Number): how many ms before sending a new ping packet (25000)
https://socket.io/docs/v4/server-api/
https://github.com/socketio/engine.io#methods-1
On socket.io 2.20. This can be set when, initializing socket.io
const io = require("socket.io")({pingTimeout: 10000, pingInterval: 30000});
See all options and their defaults here

Categories