Apache + Symfony2 + HTTPS + Node.js + Socket.io: socket.emit does not work

I spent hours on hours on this problem, but to no avail.

EDIT: solution found (see my answer)

Project background

I am creating a project in Symfony2 that requires a module to upload large files. I chose Node.js and Socket.IO (I had to learn it from scratch, so I could skip something basic). I combine them with the HTML5 File and FileReader APIs to send the file in slices from client to server. Preliminary tests showed that this approach works fine as a standalone application where everything is processed and maintained by Node.js , but integration with Apache and Symfony2 seems problematic.

The application has an unprotected and protected section. My goal is to use Apache on ports 80 and 443 to serve the main part of the application built into Symfony2 , and Node.js from Socket.IO to port 8080 to download files. The client page connecting to the socket will be served by Apache , but the socket will work through Node.js The download module must work through HTTPS, because the page is in a secure environment with an authenticated user.

The problem is events using socket.emit or socket.send do not seem to work. Client to server or server to client, it does not matter. Nothing happens and there are no errors.

Code

The code shown is a simplified version of my code without messy and confidential data.

Server

 var httpsModule = require('https'), fs = require('fs'), io = require('socket.io'); var httpsOptions = { key: fs.readFileSync('path/to/key'), cert: fs.readFileSync('/path/to/cert'), passphrase: "1234lol" } var httpsServer = httpsModule.createServer(httpsOptions); var ioServer = io.listen(httpsServer); httpsServer.listen(8080); ioServer.sockets.on('connection', function(socket) { // This event gets bound, but never fires socket.on('NewFile', function(data) { // To make sure something is happening console.log(data); // Process the new file... }); // Oddly, this one does fire socket.on('disconnect', function() { console.log("Disconnected"); }); }); 

Client

 // This is a Twig template, so I'll give an excerpt {% block javascripts %} {{ parent() }} <script type="text/javascript" src="https://my.server:8080/socket.io/socket.io.js"></script> <script type="text/javascript"> var socket = io.connect("my.server:8080", { secure: true, port: 8080 }); // Imagine this is the function initiating the file upload // File is an object containing metadata about the file like, filename, size, etc. function uploadNewFile(file) { socket.emit("NewFile", item); } </script> {% endblock %} 

So the problem is that ...

Of course, the application is much more than this, but this is where I am stuck. The page loads without errors, but emission events never fire or never reach the server (except for the disconnect event). I tried with a message event on both the client and the server to check if there was a problem with only custom events, but that didn't work either. I assume that something is blocking client-server interaction (this is not a firewall, I checked).

I am completely at a loss, so please help.

EDIT: solution found (see my answer)

+4
source share
1 answer

After some painstaking debugging, I found out what was wrong with my setup. I can also share my findings, although they (I think) are not related to Node.js, Socket.IO or Apache.

As I mentioned, my question had simplified code to show you my installation without interference. However, I configured the client through the object, using properties to configure the socket connection. For instance:

 var MyProject = {}; MyProject.Uploader = { location: 'my.server:8080', socket: io.connect(location, { secure: true, port: 8080, query: "token=blabla" }), // ...lots of extra properties and methods } 

The problem was using location as the property name. This is a reserved word in Javascript and causes some strange behavior in this case. It was strange to me that the property name of an object cannot be a reserved word, so I decided to check. I also noticed that the property was referenced incorrectly, I forgot to use this.location when connecting to the socket. So I changed it to this as a test.

 var MyProject = {}; MyProject.Uploader = { location: 'my.server:8080', socket: io.connect(this.location, { secure: true, port: 8080, query: "token=blabla" }), // ...lots of extra properties and methods } 

But to no avail. I still have not received socket data. So, the next step seemed logical in my desperate desperate rage. Changing the property name fixed everything!

 var MyProject = {}; MyProject.Uploader = { socketLocation: 'my.server:8080', socket: io.connect(this.socketLocation, { secure: true, port: 8080, query: "token=blabla" }), // ...lots of extra properties and methods } 

This approach worked fine, I got a lot of debugging messages. SUCCESS!! Whether the behavior in Javascript is expected to be reversed (or something there that happens here is β€œmisused”, seems to be the best way to pass it to me right now) of the object's properties, if you use a reserved word, I don't know. I only know that now I get rid of them!

Hope this helps anyone!

+3
source

Source: https://habr.com/ru/post/1480752/


All Articles