Use a different server on a page Angular - node.js

I am trying to implement a chat to a view on my Angular / NodeJS website.
The website is deployed on a server running on port 4200, the backend runs on 8000 and for now the chat socket.io template runs on 3000.
I have followed the socket.io's official chat tutorial in detail so I have a functionnal chat page that works on port 3000 but how can I implement it to an Angular component?
Here is my code so far:
server.js:
const app = require('express')();
var http = require('http').Server(app);
var http2 = require('http').Server(app);
var io = require('socket.io')(http2);
http.listen(8000, function(){
console.log('listening on *:8000');
});
http2.listen(3000, function(){
console.log('listening on *:3000');
});
const home = require('./home.js');
const chat = require('./chat.js');
// SOCKET.IO for testing purpose, following the tutorial
app.get('/', function(req, res){
res.sendFile(__dirname + '/socket.html');
});
io.on('connection', function(socket){
...
});
chat.component.html:
<!doctype html>
<html>
<body>
...
<div class="bottom">
<form action="">
<input id="m" class="messageInput" autocomplete="off"/>
<button type="button" class="btn btn-primary btn-lg btn-block">SEND</button>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(e){
e.preventDefault(); // prevents page reloading
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</body>
</html>
I can't figure out to make the chat 'module' work on my HTML page without accessing it through a route (app.get('/', function(req, res){ res.sendFile(__dirname + '/socket.html') });
What can I do? Thanks! And sorry for being a noob :p

Socket.io is different for client side, It's called socket.io-client. You need to get it using:
npm install socket.io-client
Well, Martin you don't need to explicitly link script file in the html. You just need to import socket.io-client variable in its typescript file.
import * as io from 'socket.io-client'. //And then connect using
try {
this._socket = io.connect(socket.io_port_you_are_using_in_server.js)
}
catch (e) {
console.log('error')
}
Now you can use this._socket wherever required like you are doing in server.js.
I also created an app like you using MEAN stack 7 months ago, but I preferred using service as I have to use chat feature in more than 3 components. I'm giving you some sample code which might help you.
joinRoom(room: string, handler: string): Observable<any> {
this._socket.emit('join', { 'room': room, 'handler': handler });
setTimeout(()=>{
console.log(this._socket.id)
},10)
let observable = new Observable((observer) => {
this._socket.on('new user', (data) => {
observer.next(data);
})
})
return observable;
}
leaveRoom(room: string) {
this._socket.emit('leave', room);
this._socket.removeAllListeners()
}
getMessages(): Observable<any> {
let observable = new Observable((observer) => {
this._socket.on('get message', (data) => {
observer.next(data);
})
})
return observable;
}
Just subscribe to the service and use binding to display msgs on the template.
//create array of received msgs
received: any[] = [];
//And in ngOnInit lifecycle hook:
this._chatService.getMessages().subscribe((data) => {
this.received.push(data.msg )
Now you can use *ngFor in the template to display msgs.
<p *ngFor="let msg of received">msg</p>
You can customize code as per your requirement.
Good luck dude!

Related

Node.js WebSockets Send Message

I'm trying to come to terms with how WebSockets work in Node.js but I'm having some trouble with sending a message.
I have my WebSocket server configured as follows (index.js)
var ws = require("ws");
var wsserver = new ws.Server ({
server: httpserver,
port: 3030
});
wsserver.on (
"connection", function connection(connection) {
console.log("connection");
}
);
wsserver.on (
"open", function open(open) {
console.log("open");
}
);
wsserver.on (
"message", function message(message) {
console.log("message");
}
);
This seems to be working ok because I can establish the connection using
var wscon = new WebSocket("ws://192.168.20.88:3030");
Which then gives me the connection output on the server. If I try to use send though nothing seems to happen and no error messages
wscon.onopen = function(open) {
wscon.send("test message");
}
I must be missing something but I don't know what
I might have an answer for this but I'm not entirely sure just yet, I'm going to put this here just in case.
I think the problem is that the message listener is added to the wrong object (the server object), I tried to add the message listener to the connection object passed to the server and it seems to be working but I'm not 100% sure why
wsserver.on (
"connection", function connection(connection) {
console.log("connection");
connection.on (
"message", function message(message) {
console.log("message : " + message);
}
);
}
);
Which dependency works for me?
I have been using socketIO for a while now and it works perfectly for Node.JS API's / servers. There are millions of tutorials online for this framework and I'll tell you one them.
How to install?
If you use NPM as your package manager in Node.JS just down it with the following command:
npm install --save socket.io
In case you're using yarn you can install socketIO as following:
yarn add socket.io
Setup the socket server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
// Used for serving the HTML page (if used)
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
// Listen for new connections
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Now in index.html I add the following snippet before the :
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
In your front-end you are able to fire of an event via the socket by calling the following function / code:
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
});
</script>
In our case we emitted an event called chat message. So in order to receive the value send over the socket connection we call the following code in our backend / api:
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
});
and that is basically how you use socket with the library SocketIO. Hope this helped fixing your issue!

JS change socket namespace from client when click on button

I'm developping simple app with nodejs and socket.io.
I created two channels and I want my client connect one of channels when click on button. The problem is I don't get response from server
This is my code :
// SERVER side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendfile('MDC.html');
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
// CLIENT SIDE
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
console.log("setDay");
socket = io.connect('/day');
console.log(socket)
}
socket.on('hiDay',function(data){
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
function setWeek(){
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
}
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
});
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
In my client, I created two button and when I click on one I want change socket namespace
When you call setDay() or setWeek(), you are creating a whole new socket.io connection and thus overwriting your previous socket variable. The socket.on(hiDay, ...) and socket.on('hiWeek', ...) handlers you have are ONLY on the first socket you created, not on the newly created sockets, thus you never see the messages on those.
To fix, add those message handlers only to the right socket after you've connected to that namespace.
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
console.log(data)
});
}
Then, do the same thing for the setDay() function.
And, as shown here you probably want to disconnect the previous connection when changing namespaces too so you don't necessarily leave connections that you aren't using any more.
FYI, you also had a typo where this:
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
should have been this:
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
Final, tested and working code is this:
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
socket.close();
console.log("setDay");
socket = io.connect('/day');
socket.on('hiDay',function(data){
console.log("hiDay")
document.getElementById('message-container').innerHTML = 'Update day';
console.log(data);
});
}
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek");
document.getElementById('message-container').innerHTML = 'Update Week';
console.log(data);
});
}
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
And server code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var path = require('path');
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'socket-io-namespace.html'));
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
If you create a connect(ns) function you can reconstruct the socket event listener when the namespace changes. The following should work:
<script>
var connect = function (ns) {
return io.connect(ns, {
query: 'ns=' + ns,
resource: "socket.io"
}).on('hiWeek', function (data) {
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
}).on('hiDay', function (data) {
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
}
var socket = io();
function setDay() {
console.log("setDay");
socket = connect('/day');
console.log(socket);
}
function setWeek() {
console.log("setWeek");
socket = connect('/week');
console.log(socket);
}
</script>

Openshift Nodejs Socket.io issue, But 200 Ok response

I have deployed below code in OpenShift Cloud platform by Red-hat for NodeJs chat application, I am not getting any error in Console(F12) and response code as Ok 200..but the application is not working
Server(you can find complete source at https://github.com/varund29/openshift/blob/master/index.js)
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server, { origins:'http://nodejs-atnodejs.rhcloud.com:8000' });
app.get('/', function (req, res) {
res.sendfile('index.html');
});
io.on('connection', function (socket) {
socket.on('chatmessage', function (msg) {
console.log('index.js(socket.on)==' + msg);
io.emit('chatmessage', msg);
});
});
server.listen(process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP);
Client(you can find complete source at https://github.com/varund29/openshift/blob/master/index.html)
src="http://nodejs-atnodejs.rhcloud.com:8000/socket.io/socket.io.js
src="http://code.jquery.com/jquery-1.11.1.js"
var socket = io.connect('http://nodejs-atnodejs.rhcloud.com:8000');
$('button').click(function (e) {
console.log('index.html($(button).click)=' + $('#m').val());
socket.emit('chatmessage', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chatmessage', function (msg) {
console.log('index.html(socket.on)==' + msg);
$('#messages').append($('<li>').text(msg));
});
Html body is
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" />
<button>Send</button>
</form>
When I ran your code I got the following errors in my log files on my gear on OpenShift Online:
Option log level is not valid. Please refer to the README.
Option polling duration is not valid. Please refer to the README.
So I commented out the following lines in your index.js file:
io.set('log level', 1); // reduce logging
io.set('transports', ['xhr-polling']);
io.set("polling duration", 10);
And it seems to be working fine now. You can test it here: http://nodejs-cdaley.rhcloud.com/
And you can view the code here: https://github.com/developercorey/nodejs

How to use Express post request to emit Socket.io or Sockjs?

I know this question is kind of awkward, but the problem comes from Samsung TV 2010 / 2011 SmartTV (and blue ray player; of course 2012 emulator working fine). I ported the simple chatting examples come from the source and package to SmartTV app. Both of them fall back to JSONP polling, but from SmartTV app only could emit / push to server once. Receiving the message from server could be multiple times without any problem. After looking for the answer in Samsung D forum (of course nothing there), I think the fastest way to work around this issue is to deploy an Express server, taking the post data and JSON.parse, then emit Socket.io / Sockjs internally inside the server itself.
Could anybody show me an easy sample code so I could start from there? Thanks a lot.
I quickly make code, but seems it doesn't work:
lib/server.js
var express = require('express')
, app = express.createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.use(express.bodyParser());
app.get('/', function (req, res) {
res.sendfile('/var/www/mpgs_lite_v3/index.html');
});
app.post('/', function(req, res){
console.log(req.body);
io.sockets.emit('my other event', req.body);
res.redirect('back');
});
io.sockets.on('connection', function (socket) {
//socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
index.html
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
<form method="post" action="/">
<input type="hidden" name="_method" value="put" />
<input type="text" name="user[name]" />
<input type="text" name="user[email]" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
'my other event' seems not receive anything.
UPDATE: I updated the example for you to make it more complete. I didn't have an app.listen before, and here is also a client side script which shows that it, indeed, works fine:
<!doctype html>
<html>
<head>
<script src="//www.google.com/jsapi"></script>
<script src="/socket.io/socket.io.js"></script>
<script>google.load("jquery", "1.7.1")</script>
<script>
var socket = io.connect("localhost", {port: 3000});
socket.on("foo", function(message) { console.log("foo: ", message) });
$(function() {
$("button").click(function() {
$.post("/foo", { message: $("input").val() });
});
});
</script>
</head>
<body>
<input type=text>A message</input>
<button>Click me!</button>
</body>
</html>
And the server, now with an app.listen directive:
var express = require("express"),
app = express.createServer(),
io = require("socket.io").listen(app)
index = require("fs").readFileSync(__dirname + "/index.html", "utf8");
app.use(express.bodyParser());
app.get("/", function(req, res, next) {
res.send(index);
});
app.post("/foo", function(req, res, next) {
io.sockets.emit("foo", req.body);
res.send({});
});
app.listen(3000);
Usage:
node app.js
Navigate to http://localhost:3000/ and click the button. Check your console for output.
Based on SockJS express example server.js could look like:
var express = require('express');
var sockjs = require('sockjs');
// 1. Echo sockjs server
var sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.2.min.js"};
var sockjs_echo = sockjs.createServer(sockjs_opts);
connections = {};
sockjs_echo.on('connection', function(conn) {
console.log(conn.id);
connections[conn.id] = conn
conn.on('close', function() {
delete connections[conn.id];
});
// Echo.
conn.on('data', function(message) {
conn.write(message);
});
});
// 2. Express server
var app = express.createServer();
sockjs_echo.installHandlers(app, {prefix:'/echo'});
console.log(' [*] Listening on 0.0.0.0:9999' );
app.listen(9999, '0.0.0.0');
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.post("/send", function(req, res, next) {
for(var id in connections) {
connections[id].write('received POST');
}
res.send({});
});
To test open browser at localhost:9999 and run:
curl localhost:9999/send -X POST
just remove this comment
//socket.emit('news', { hello: 'world' });
to
socket.emit('news', { hello: 'world' });
it will work because its emiting data through news and you are listening using my other event instead of 'news' or you can do just listen using 'my other event'
I don't know if this would help, but you can make an emit abstraction on the client based on your browser and then make a separate get function on the server that will handle the request the same way as the socket.on callback. In order to know where to send the information I suggest you use some key that you can store in a hash table in the server and local storage on the client.
For the client:
var emit = function(event, options) {
if ("WebSocket" in window) {
socket.emit(event, options);
console.log("emited via WebSocket");
} else {
$.post("http://localhost/emit/" + event, options);
console.log("emited via AJAX");
}
}
emit("echo", {
key: localStorage.getItem("key"),
data: {
hello: "world"
}
});
socket.on("response", function(data) {
console.log(data.hello); //will print "world"
});
For the server:
var sockets = {};
var echo_handler = function(a) {
var socket = sockets[a.key];
var data = a.data;
socket.emit("response", data);
}
app.post("/emit/:event", function(req, res) {
var event = req.params.event;
switch (event) {
case "echo":
var a = {
key: req.param("key"),
data: req.param("data")
}
echo_handler(a);
break;
}
});
io.sockets.on("connection", function(socket) {
socket.on("connect", function(data) {
sockets[data.key] = socket;
});
socket.on("echo", echo_handler);
});
Another way to do this will be to switch to Sockjs and use their patch.
If someone have better solution for Socket.IO it will be appreciated, because I'm already deep into the project and it's too late to switch Socket.IO for Sockjs, and this solution is not to my liking :( .

node.js socket.io simple chat

I'm starting playing with node.js and as everybody, I want do a chat.
My idea is run node.js with socket.io in the port 9090, for example, and my client html in the port 8080. My html client will be served independent.
My server:
var sys = require('sys');
var express = require('express');
var io = require('socket.io');
var app = express.createServer();
app.listen(8080);
var socket = io.listen(app);
socket.on('connection', function (client) {
client.on('message', function (msg) {
socket.broadcast(msg);
});
client.on('disconnect', function () {
});
});
My client:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src="http://cdn.socket.io/stable/socket.io.js"></script>
<script>
$(document).ready(function () {
var socket = new io.Socket("localhost", {port: 8080});
socket.on('connect', function () {
socket.send('A client connected.');
});
socket.on('message', function (message) {
$('div#messages').append($('<p>'), message);
});
socket.on('disconnect', function () {
console.log('disconnected');
});
socket.connect();
$('input').keydown(function (event) {
if(event.keyCode === 13) {
socket.send($('input').val());
$('input').val('');
}
});
});
</script>
</head>
<body>
<input type="text" style="width: 300px;" />
<div id="messages" style="border:solid 1px #000;"> </div>
</body>
</html>
I'm running in ubuntu 11.04 with node.js v0.4.10.
The server works fine, but the client can't do connection, in the console.log on google Chrome I received this message:
XMLHttpRequest cannot load http://localhost:8080/socket.io/xhr-polling//1311465961485. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
The server.js is in a folder in /var/www/cliente/chat/public.
What's the problem?
Your client code is not actually being served from port 8080 as you want.
var sys = require('sys');
var express = require('express');
var io = require('socket.io');
var app = express.createServer();
app.listen(8080);
app.use(express.static(__dirname));
app.get('/', function(req, res){
res.render('index.html', { title: 'Chat' });
});
var socket = io.listen(app);
socket.on('connection', function (client) {
client.on('message', function (msg) {
socket.broadcast(msg);
});
client.on('disconnect', function () {
});
});
This should fix your Access-Control-Allow-Origin errors. Execute node server.js and connect to http://localhost:8080. A couple additional notes:
Make sure you have installed socket.io 0.6.x since that's what you are including in your html file. 0.7.x is backwards incompatible.
With this configuration you'll be running socket.io on the same port you are serving your page from (as opposed to 9090).
When I updated my client to:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
<script>
var socket = io.connect("http://localhost", {port: 8080});
socket.on('connect', function () {
socket.send('A client connected.');
});
socket.on('message', function (msg) {
$('div#messages').append($('<p>'), msg);
});
socket.on('disconnect', function () {
console.log('disconnected');
});
$(document).ready(function(){
$('#btn_send').click(function (event) {
socket.send($('#txt_msg').val());
$('#txt_msg').val('');
});
});
</script>
</head>
<body>
<input type="text" id="txt_msg" style="width: 300px;" /><input type="button" id="btn_send" value="send" />
<div id="messages" style="border:solid 1px #000;"> </div>
</body>
</html>
Everything worked.
I was using a version 0.7 of the socket.io that was the problem: https://github.com/LearnBoost/Socket.IO/wiki/Migrating-0.6-to-0.7
You cannot make AJAX requests to URLs that are not on the same hostname and port as the current page. It's a security restriction in all web browsers.

Resources