Reputation: 25641
I'm studying for the first time socket.io. I'd like to start a simple socket server. I see every example I found in the internet made like this:
var http = require('http');
var fs = require('fs');
// Loading the index file . html displayed to the client
var server = http.createServer(function(req, res) {
fs.readFile('./index.html', 'utf-8', function(error, content) {
res.writeHead(200, {"Content-Type": "text/html"});
res.end(content);
});
});
// Loading socket.io
var io = require('socket.io').listen(server);
// When a client connects, we note it in the console
io.sockets.on('connection', function (socket) {
console.log('A client is connected!');
});
server.listen(8080);
The core of my question is simple: in all examples like this, I see io to listen attached to an existing http server.
Is this a requirement? If yes, why? Is websocket protocol transported via http?
My use case is a bit strange probably: I've a vue dev server that must be kept running because it's offering live reload, etc.. It's listening on port 8080 and it's offered by vue-cli-service so I cannot alter it to attach something.
Also, I've a 'hand-made' and experimental smtp server, made in node.js and running on port 25
I want to use websocket to allow my smtp server to 'post' and my Vue.js webapp to 'listen' .
Final goal: creating a standalone smtp-catch-all system with a simple webgui, so every mail sent via my smtp is 'pushed' into my webapp and never stored (and never really sent !)
Given this, I'd like to create a 'standalone' socket.io server. If it simply needs an http server, I create a second one on a specific port to allow http->websocket upgrade; then my web app will simply comunicate with the socket server on this secondary server.
I prefer in this way, because, using pm2, I can run each service without touch the other
Upvotes: 0
Views: 928
Reputation: 25641
I add a proof-of-concept about an smtp server that simply catch all received mail but do not send to real target.
Also, it emits events on a socket.io connection.
All without using an http server.
const SMTPServer = require("smtp-server").SMTPServer;
const io = require('socket.io')(2626);
const server = new SMTPServer({
logger: true,
debug: true,
allowInsecureAuth: true,
onAuth(auth, session, callback) {
console.log("onAuth, user", auth.username, "password", auth.password);
if (auth.username !== "abc" || auth.password !== "def") {
return callback(new Error("Invalid username or password"));
}
io.emit("smtpAuth", auth);
callback(null, { user: 123 }); // where 123 is the user id or similar property
},
onConnect(session, callback) {
console.log("onConnect, from ip ", session.remoteAddress);
io.emit("smtpConnect", session);
return callback(); // Accept the connection
},
onMailFrom(address, session, callback) {
console.log("onMailFrom", address.address);
io.emit("smtpMailFrom", address);
return callback(); // Accept the address
},
onRcptTo(address, session, callback) {
console.log("onRcptTo", address.address);
io.emit("smtpRcptTo", address);
return callback(); // Accept the address
},
onData(stream, session, callback) {
var email_content = "";
// stream.pipe(email_content); // print message to console
stream.on('data', (chunk) => { email_content += chunk });
stream.on("end", function() {
// Stream ended
console.log (email_content);
io.emit("smtpData", email_content);
callback();
});
}
});
server.on("error", err => {
console.log("Error %s", err.message);
});
server.listen(25);
This component is automatically informed by socket.io server if something new is happening. In this case, it can log all events but also save entire email (raw) data.
<template>
<div class="hello">
<h1>Le email che abbiamo ricevuto per te</h1>
<pre
v-for="(message, index) in messages"
:key="index"
>{{
message
}}</pre>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
messages: [],
}
},
sockets: {
connect() {
console.log('socket connected')
},
smtpAuth(val) {
console.log('SMTP AUTH', val);
},
smtpConnect(val) {
console.log('SMTP CONNECT', val);
},
smtpMailFrom(val) {
console.log('SMTP MAIL FROM', val);
},
smtpRcptTo(val) {
console.log('SMTP RCPT TO', val);
},
smtpData(val) {
console.log('SMYP DATA', val);
this.messages.push(val);
}
},
};
</script>
Call this ecosystem.config.js
module.exports = {
apps: [
{
name: "WEB",
script: "./node_modules/@vue/cli-service/bin/vue-cli-service.js",
args: "serve"
},
{
watch: true,
name: "SMTP",
script: "./server/index.js"
}
]
};
Run it as pm2 run ecosystem.config.js
Upvotes: 0
Reputation: 56467
The WebSocket protocol is a separate protocol, it is not built on top of HTTP. However there's an upgrade mechanism (i.e. the WebSocket handshake) in the HTTP protocol itself, that turns a simple HTTP connection into a WebSocket connection. And since browsers use that then it is impossible to establish a WebSocket connection from a browser without HTTP.
Side note: socket.io does utilize other protocols as well. It falls back to them if WebSocket protocol is not available.
Now the following is (obviously) an opinion: there is no need to attach one server to another. In fact this is an anti pattern. You generally want components to be as independent as possible so that changes to one don't affect the other. Moreover: even if both were to run over HTTP there still is no reason to do that. I find those tutorials at least misleading.
Upvotes: 1