Support for http and https in the same app?
I have an Express app that handles both http and https requests. The Express 3.0 examples suggest using explicit http and https server objects to accomplish this, rather than using app.listen(). Express.io doesn't seem to support that, so when I attempted to integrate express.io, I tried out the following code:
var app = require('express.io')(),
fs = require('fs')
httpsOptions = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
app.http().io();
app.https(httpsOptions).io();
app.listen(process.env.PORT || 80, function(){});
app.listen(443, function(){});
My app now responds to http requests, but with https it returns Error 102 (net::ERR_CONNECTION_REFUSED): The server refused the connection. Thanks for any help!
@amitkumar I'm working on a better syntax for this. And i'm open to any suggestions. But here is how you can get your code to work:
var express = require('express.io'),
fs = require('fs');
var app = express();
httpsOptions = {
key: fs.readFileSync('./server.key'),
cert: fs.readFileSync('./server.crt')
};
app.http().io();
httpsServer = require('https').createServer(httpsOptions, app);
app.listen(process.env.PORT || 80, function(){});
express.io.listen(httpsServer);
httpsServer.listen(443, function(){});
I always thought it was kind of strange to run http and https for the same app, what is your use case? I usually just setup a redirect from http to https.
Cheers!
@techpines 2 reasons: One, I'm developing a Heroku app. When it's on Heroku, the app only listens on http since Heroku's proxy hides the https handling. My redirection handler has a special case when deployed to Heroku to check x-forwarded-proto rather than req.secure. When I'm developing locally however, my app uses https.
The other reason is I have Arduino-based devices that need to talk to my API, and Arduinos aren't really able to handle the load of https encryption. So I have them using HMAC-based auth over regular http instead.
Thanks for the help! I actually went ahead and implemented regular socket.io in my app, but I'll try this out soon.
@amitkumar Cool, thanks for the update.
If you think about your code that you posted earlier, it is somewhat ambigiuous as to which port a particular server would bind to on listen.
I was thinking that maybe a better solution would be something like this:
app.http({
io: true, // enable websockets, probably defaults true
port: 80 // specify the port here instead
});
app.https({
io: true,
port: [443, 449] // support for multiple ports.
key: 'some-key',
cert: 'some-cert'
});
app.listen(function(error, port) {
// This would get called multiple times for each port.
});
I think a clean syntax is possible. But this would be breaking with my current implentation, so I would probably need to do a major version bump.
If anyone else has an opinion on this, please drop a note on this thread.
@techpines I like the proposed new syntax. I think it makes things much clearer as to what's going on. You might also consider a very minor variation like:
app.setup({
http: {
io: true,
port: 80
},
https: {
...
}
)
app.listen(...)
which would provide a single interface for setting up both http and https.
Another interesting way would be to pass an object to the listen function, since this is where the port is currently specified anyway. You could get rid of app.http() or app.https().
var express = require('express.io'),
app = express().io(); // no http() or https()
app.get('/', ... );
app.io.route( ... );
app.listen({
http: {
io : true,
por t: 80
},
https: {
...
}
})
I'd also love to see an easy way enable both HTTP and HTTPS. This is a really cool project, btw. Thanks!
I'm in favor of @maxkueng's method. This separates the application from the connection protocol. Additionally, I think it would be helpful to use the app.listen(options) to specify a socket.io port if desired, as well as any other options that could be passed to http[s].server.listen().
var express = require('express.io'),
app = express().io();
app.get( ... );
app.io.route( ... );
app.listen({
http: {
port: 80,
io: 8080,
hostname: [hostname],
callback: function(){}
},
https: {
key: fs.readFileSync('./key'),
cert: fs.readFileSync('./cert'),
...
}
})
Any progress with this issue?
Are any of the suggested better ways of handling http and https going to be implemented?
Also I found that if I setup the server with express on http and created the https server later I ran into issues with the client-side of socket.io not properly emitting messages to the server even after connection (it dropped to XHR polling and things like that, but messages weren't getting through). To fix this I made it so that the server is created as https and then later creates a mirroring http server. The equivalent of the first suggested code being like this:
var express = require('express.io'),
fs = require('fs');
var app = express();
httpsOptions = {
key: fs.readFileSync('./server.key'),
cert: fs.readFileSync('./server.crt')
};
app.https(httpsOptions).io();
httpServer = require('http').createServer(app);
app.listen(443);
express.io.listen(httpServer);
httpServer.listen(process.env.PORT || 80, function(){}, function(){});