So I have an event stream in my express js node application. Here's an overview:
app.get('/eventstream', function(req, res){
req.socket.setTimeout(Infinity);
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
res.write('/n');
req.on('close', function(){
console.log('connection closed');
});
}
On my local dev box, running from the command line with
node app.js
it works fine, and prints out 'connection closed' when i close my tab in my browser.
However, when running on my server, under Apache with Passenger, it doesn't print out any message - the server seems to not fire the 'close' event. I'm using this event to remove from my count of active users. Any ideas?
Cheers,
Dan
Phusion Passenger author here. The short answer is: technically, the connection hasn't closed yet.
Here's the long answer. If the client connects directly to your Node.js process, then yes, the connection is closed. But with Phusion Passenger there's a proxy in between the client and Node.js. The thing about sockets is that there are two ways to find out whether a socket has been closed: either 1) by reading end-of-file from it, or 2) by writing to it and getting an error. Phusion Passenger stops reading from the client as soon as it has determined that the request body has ended. And in case of GET requests, that is immediately after header. Thus, the only way Phusion Passenger can notice that the client has closed to the connection, is by sending data to it. But your application never sends any data after that newline, and so Phusion Passenger doesn't do that either and never notices that the connection is closed.
This issue is not limited to Phusion Passenger. If you put your Node.js app behind a load balancer or any other kind of reverse proxy, then you could also run into the same issue.
The standard solution is to regularly send "ping" messages, with the purpose of checking whether the connection is alive.
A similar issue also applies to WebSockets. It is the reason why the WebSocket supports ping frames.
UPDATE February 28, 2016:
We have found a solution, and Passenger 5.0.26 and later supports forwarding half-close events which fixes the problem described by #coffeedougnuts. Just use 5.0.26 and later and it'll work as expected.
Related
Java server, javascript client, no special libraries, plain text HTTP/1.1 and websocket connections.
Server side written (in Eclipse) using JDK 16 and a websocket jar found in Tomcat, version 10.0.2. (Many permutations of other JDKs and websocket jars have also been tried.)
Two web applications. Tomcat 10.0.2 on PC, 10.0.7 on server. Both apps run on Windows 10. Deployed to a Ubuntu 20.04 server. Both programs display the initial HTTP data. One program gets a websocket connection and works, the other fails to get the websocket connection. Both use the same code to calculate the target URL for the websocket connection:
window.onload = function() {
var target = "ws://" + location.host + "/[context]/[endpoint]";
console.log("target: " + target);
try {
if ('WebSocket' in window) {
socket = new WebSocket(target);
} else if ('MozWebSocket' in window) {
socket = new MozWebSocket(target);
} else {
alert('WebSocket is not supported by this browser.');
return;
}
} catch (e) {
console.log("websocket connection exception: " + e.description);
}
...
Where only [context] and [endpoint] differ. Recall that these URLs work on a PC. I believe they are “well-formed”/valid.
Results for the web app that fails:
Firefox:
uncaught exception: Could not establish connection. Receiving end does not exist.
GET ws://35.xxx.xx.xx:8080/Memory/MemoryEndpoint[HTTP/1.1 404 70ms]
Firefox can’t establish a connection to the server at ws://35.xxx.xx.xx:8080/Memory/MemoryEndpoint.
Chrome:
Error handling response: TypeError: Cannot read property 'encrypt' of undefined
at Object.13 (chrome-extension://bkdgflcldnnnapblkhphbgpggdiikppg/public/js/content-scripts/autofill.js:1427:33)
. . .
game.js:31 WebSocket connection to 'ws://xxx.xx.xx.xx:8080/Memory/MemoryEndpoint' failed:
Chrome continues for many lines regarding the 'encrypt' undefined issue. I have no idea what that is about but it might be very relevant. The last line above implies that some reason for the failure might be given on the next line, but it is empty.
Neither browser logs the expected exception text beginning with: "websocket connection exception:".
Tomcat log files are all clean except for some curious entries in localhost__access_log such as:
209.90.225.218 - - [11/Jul/2021:00:43:33 +0000] "HEAD /robots.txt HTTP/1.0" 404 -
And others mentioning /invoker/readonly, /login, /jenkins/login, /nifi/.
The fact that both programs do return results from the Tomcat server tells me that permissions on ports etc are all sufficient. I've also dug into netstat results and the like, reviewed firewall settings, read many many articles and requests for help. (Probably irrelevant because Tomcat does return expected HTTP/1.1 data.) No luck.
I need this program to work. I would pay a cash reward for a solution to this by 07-16-2021, though I don't know how to discretely negotiate that. :-(
Problem resolved, though I don't understand the cause. Recall: the web application ran fine on development PC deployed to Tomcat version 10.0.2, for various JDKs, websocket libraries (including one found in the Tomcat 10.0.7 that had been installed on the VM). The app failed on the Ubuntu VM. A friend installed Tomcat 10.0.8 in the VM. Presto! websockets work.
i just started learning deno and tried to send mails with it.
import { SmtpClient } from "./deps.js";
await client.connectTLS({
host: "smtp.163.com",
port: 465,
username: "my email",
password: "my password",
});
await client.send({
from: "mailaddress#163.com",
to: "t32n5nr#prowerl.com",
subject: "Mail Title",
content: "Mail Content,maybe HTML",
});
I did everything as said in SmtpClient docs
But i get an error
error: Uncaught ConnectionRefused: No connection could be made because the target machine actively refused it. (os error 10061)
at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)
at async Object.connectTls ($deno$/tls.ts:20:15)
at async SmtpClient.connectTLS (https://deno.land/x/smtp/smtp.ts:36:18)
at async file:///C:/.../controller.js:28:1
The "connection refused" message almost always resolve to one these two possibilities:
1. The server or service is unstable or unavailable.
In this situation there might be a few things going on the server:
Options 1.1 - Incorrect port / listener is down
The port you are using is correct but the listener (process on the servers) is down, meaning that you are connecting to the correct port, but there's no process to listen for your requests.
Possible solution is to try running telnet <address> <port> and check if the service is up. Example: telnet google.com 443.
Option 1.2 - Threshold limit
The port and the service are up, but you've reached the threshold that limits the configured TCP connectivity.
That might occur due to high traffic (peaks) to the endpoint. That is not something you can solve yourself. TCP listeners might reject the caller connection if the traffic is too high.
One way of testing these is to implement a load testing script that tests the connectivity over time. If you prove that the server is limiting the requests you can then report and ask them to increase the load capabilities (allow for a higher capacity for simultaneous requests).
2. The client cannot communicate with the server
Option 2.1 - Proxy
If you are connection from an enterprise network and there is a proxy in between, that might be why you are having such difficulties.
Solution: run your code from home or an external network to prove that you are able to connect from outside the corporate network.
Option 2.2 - Firewall
Just like the proxy, you're running your code behind a firewall that is either blocking or interfering with your communication with the external network.
I was able to run your code and connect to Google using my personal credentials. I had to perform a slight change due to a problem to the Deno library due to type definitions but it worked fine.
I strongly suspect that your problem is related to the infrastructure (local or remote), not to the Deno runtime or library.
import { SmtpClient } from "https://deno.land/x/smtp/mod.ts";
import { ConnectConfigWithAuthentication } from "https://raw.githubusercontent.com/manyuanrong/deno-smtp/master/config.ts";
const client = new SmtpClient();
const params = <ConnectConfigWithAuthentication>{
hostname: "smtp.google.com",
port: 465,
username: "<google mail>",
password: "<password>"
}
await client.connectTLS(params);
await client.send({
from: "<from_email>", // Your Email address
to: "<to_email>", // Email address of the destination
subject: "Mail Title",
content: "Mail Content,maybe HTML",
});
await client.close();
I tried to create a user on the smtp.163.com website but I couldn't understand the language, if you give me test credentials I try myself.
I am running a barebones Nodejs server only using the HTTP module. I've created an HTTP server and am listening on socket connections and on requests. I noticed that when I use chrome and go to localhost, three sockets connect, and two requests are made to "/". I know that, using some other webservers, I've seen Chrome request the same thing multiple times if it does not receive a quick response (about 5 seconds), but I am sending a response right away and still Chrome is connecting/requesting multiple times.
Is this expected, and if it is, should I be expected to handle duplicate requests?
My relevant code
let server = http.createServer();
server.listen({
host: host,
port: port
});
server.on('connection', function(socket){
// gets printed 3 times
console.log('connection')
});
server.on('request', function(request, response){
// gets printed two times
console.log('hi')
// yet chrome only receives one response (seemingly)
response.end('hi')
});
Edit: Half solved. Now I am printing request.url and I see
/
and
favicon.ico
So there are 2 requests, but still 3 socket connections. I guess every single request is on a new socket?
All individual images, css and javascript will definitely make http requests. No doubt about it.
I'm using Node.js' Soap Client (https://github.com/vpulim/node-soap) for some extensive integration with other service. However, this is not the only integration running on my server, and I would like to make my calls from another network interface (i.e. "external IP")
My software layer is pretty much complete, but this is something that I've not predicted. Can I possibly do this with some setting, or maybe some Node.js' launch argument?
I was thinking about a locally running proxy server (even in the same thread as the app), but - if possible - I'd welcome some more elegant option.
OK, i've managed to achieve this by using request module (https://github.com/request/request) and simply changing one line of code:
soap.createClientAsync('https://example.com/service.php?wsdl', {
'request': request.defaults({
localAddress: 'xxx.xxx.xxx.xxx',
connection: 'keep-alive'
})
})
My Sails version is 0.11.2 and running with port 1337
In assets/js/dependencies/sails.io.js, i can see version as 0.11.0
Below is the client side script.
<script src="http://localhost/project/assets/js/dependencies/sails.io.js"></script>
<script type="text/javascript">
// `io` is available as a global.
// `io.socket` will connect automatically, but at this point in the DOM, it is not ready yet
// (think of $(document).ready() from jQuery)
//
// Fortunately, this library provides an abstraction to avoid this issue.
// Requests you make before `io` is ready will be queued and replayed automatically when the socket connects.
// To disable this behavior or configure other things, you can set properties on `io.sails`.
// You have one cycle of the event loop to set `io.sails.autoConnect` to false before the auto-connection
// behavior starts.
io.socket.get('/hello', function serverResponded (body, JWR) {
// JWR ==> "JSON WebSocket Response"
console.log('Sails responded with: ', body);
console.log('with headers: ', JWR.headers);
console.log('and with status code: ', JWR.statusCode);
// first argument `body` === `JWR.body`
// (just for convenience, and to maintain familiar usage, a la `JQuery.get()`)
});
I am getting the error like
Socket is trying to reconnect to Sails...
When i checked some other posts, there saying something related with sails version.
I tried to change the sails.io.js version to 0.11.2, but still same error.
Is this error have any connection with port ?
Because the response from below request is 404
http://localhost/socket.io/?__sails_io_sdk_version=0.11.2&__sails_io_sdk_platform=browser&__sails_io_sdk_language=javascript&EIO=3&transport=polling&t=1444654910110-52
Response
<p>The requested URL /socket.io/ was not found on this server.</p>
<address>Apache/2.2.22 (Ubuntu) Server at localhost Port 80</address>
Any help what is wrong ?
You're running the Sails app on port 1337, but loading the sails.io.js file from port 80 (because you don't specify another port):
<script src="http://localhost/project/assets/js/dependencies/sails.io.js">
I guess you have an Apache server running on port 80, so it's finding the sails.io.js file and returning it, but then the socket client assumes that it should be connecting on port 80 as well.
Either update your script tag with a port:
<script src="http://localhost:1337/js/dependencies/sails.io.js">
or specify an alternate URL for the socket to connect to, using the following code before the io.socket.get:
io.sails.url = "http://localhost:1337";
The 404 is coming from a client-side socket attempting to connect to the server, which is not accepting socket connections.
if you are not using a socket in your application you need to delete the sails.io.js script.
and below both options didn't work for me but this worked. I deleted the sails.io.js file.