Connect to socket.io dynamically - node.js

I'm trying to connect the browser to my application via socket.io.
<script type="text/javascript" src="http://localhost:4000/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:4000');
</script>
With this standard method all works fine.
Now I'm trying to transform this connection in "dynamic" based on the IP of the server, something like this:
<html>
<head>
var socket;
function loadFile(filename){
var ip_server = location.host;
var body = document.getElementsByTagName( 'body' )[0],
fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", "http://"+ip_server+"/"+filename);
body.appendChild( fileref );
}
</head>
<body>
<script type="text/javascript">
loadFile("socket.io/socket.io.js");
socket = io.connect('http://'+location.host);
</script>
</body>
</html>
But firebug says ReferenceError: io is not defined on line socket = io.connect('http://'+location.host);.
How can I solve? There's a simple way to do what I'm thinking?
Thanks

Socket.io has "magical" integration with Node.js which means that something much simpler will work automatically:
<script src="/socket.io/socket.io.js"></script>
var socket = io.connect();
This will find the library and the socket with no explicit host or path. It should "just work."

const socket = io.connect(location.href);

Related

Uncaught reference error require is not defined

I'm trying to use an html page in order to test the connection with my server.
I've got no problem with my server.js
var http = require('http');
var url = require("url");
// Chargement de socket.io
var io = require('socket.io').listen(server);
var server = http.createServer(function(req, res) {
var page = url.parse(req.url).pathname;
// Quand un client se connecte, on le note dans la console
});
io.sockets.on('connection', function (socket) {
console.log('Un client est connecté !');
});
server.listen(8080);
My client should is an html page here
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Socket.io</title>
</head>
<body>
<h1>Communication test with socket.io !</h1>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://localhost:8000/server_node/node_modules/socket.io/lib/socket.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
</script>
</body>
</html>
Problem is, when I load the html client, I've got this error
socket.js:6 Uncaught ReferenceError: require is not defined
at socket.js:6
I'm not trying to implement a real client, I just want a simple page in order to do some connection test.
Thanks for your help
EDIT: Problem fixed, it was all because I wasn't loading the html file from the serverlike this fs.readFile('./ClientTest.html', 'utf-8', function(error, content) {
As this is just used to do some test, it's fine if it works this way; the client side will be with an other platform.
Sorry for that useless issue :(
You appear to be importing the server-side library on the client, you want to be importing the client-side one.
As per the docs, this is automatically served when socket.io runs on the server which you can import via
<script src="/socket.io/socket.io.js" />

socket.io node.js server "debug: destroying non-socket.io upgrade" message

I have a node.js socket server using socket.io.
I'm building a firefox addon, where I load a pageworker. The html in the following page is as follows:
<html>
<head>
<script type="text/javascript">
//THIS DOESN'T WORK
var exampleSocket = new WebSocket("ws://someip:port");
exampleSocket.onopen = function (event) {
console.log("socket opened!");
};
//THIS WORKS
var exampleSocketa = new WebSocket("ws://echo.websocket.org");
exampleSocketa.onopen = function (event) {
console.log("socket to echo opened!");
};
</script>
</head>
<body>
</body>
</html>
I can open a websocket to echo.websocket.org, but not my own server. I get a "debug: destroying non-socket.io upgrade" message. I can switch it off with the option: { 'destroy upgrade': false }, but then I see no debug output from server, and no connection is made.
What am I doing wrong? How can I get a socket open to my socket.io server?
So after some more googling, it turns out that I need to require socket.io on the client side. Even though socket.io uses websockets, it prefers talking to itself.

How to share common function between server and client using node.js

Following are the structure of my application
Inside prototype.js file i have following code:
(function(exports) {
exports.foo = function() {
return 'bar';
};
})((typeof process === 'undefined' || !process.versions) ? window.common = window.common || {} : exports);
app.js contains
var express = require('express'),app = express(),server = require('http').createServer(app),io = require('socket.io').listen(server),port = 3000,path = require('path');
var common = require('common/prototype');
console.log(common.foo());
// listening to port...
server.listen(port);
//Object to save clients data
var users = [];
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function (req, res) {
res.sendfile('/public/index.html');
});
index.html contains
<!doctype html>
<html lang="en">
<head>
<title>Socket.io Demo</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script src="/common/prototype.js"></script>
<script>
alert(window.common.foo()); //This line will gives me an error TypeError: window.common is undefined
</script>
</body>
</html>
Now i would like to print
Hello, I am bar from server and client as well.
Now i am able to print from server side using following line
var common = require('common/prototype');
console.log(common.foo());
But could not able to show alert on client side. could you please help me to find the root cause for the issue.
The root cause is that when you do <script src="/common/prototype.js"></script> in your HTML the file won't be fetched because the Express static middleware is only looking for files under your public folder.
A quick way to test this is to copy your prototype.js to your javascript folder inside public. Then update your script tag to reference the file as follows <script src="/javascripts/prototype.js"></script>
The thing to remember is that the JavaScript files that live under node_modules are not automatically available to the browser.

Client disconnects immediately after connection to Node js TCP server

This is my first time with node js. I am trying to get the client to connect to the server and maintain the connection without closure.
This is all hosted in an ubuntu server edition hosted in a virtualbox.
I had checked that the server is actually listening to the port 5000 using
netstat -ant
Websockets is also available on my browser.
I get the following output with error
Echo server dot come
192.168.1.107
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: EPIPE, Broken pipe
at Socket._writeImpl (net.js:159:14)
at Socket._writeOut (net.js:450:25)
at Socket.write (net.js:377:17)
at Socket.ondata (stream.js:36:26)
at Socket.emit (events.js:81:20)
at Socket._onReadable (net.js:678:14)
at IOWatcher.onReadable [as callback] (net.js:177:10)
and if i call socket.end() on the server on connection event handler i get a disconnecting client. My question is how to establish a stable connection using this code, what do i have to change or i am doing wrong here? pulling my hair out - thanks in advance!
HTML CODE
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Test RS Server (built over nodejs)</title>
<link rel="stylesheet" href="style.css"></link>
<script src="jquery.min.js" ></script>
<script src="client.js" ></script>
</head>
<body>
<label>Message</label>
<input type="text" id="message_box"></input>
<input type="button" id="submit_btn" value="Send"></input>
<div style="clear:both;"/>
<label>Output</label>
<textarea rows="10" cols="100" id="output_box"></textarea>
</body>
</html>
CLIENT JS
var message_box;
var output_box;
var submit_btn;
var url = "wss://192.168.1.107:5000";
var socket;
function createListeners() {
if ("WebSocket" in window) {
output_box.html("Supports sockets.");
socket= new WebSocket(url);
socket.onopen= function() {
socket.send("con opened");
output_box.html("Connection opened.");
};
socket.onmessage= function(response) {
// alert('got reply '+s);
console.log(response);
output_box.html(response);
};
socket.onclose = function() {
// websocket is closed.
output_box.html("Connection is closed...");
};
submit_btn.click(function(e) {
socket.send(message_box.val());
});
} else {
output_box.html("doesnt support sockets");
};
};
$(document).ready(function() {
message_box = $("#message_box");
output_box = $("#output_box");
submit_btn = $("#submit_btn");
createListeners();
});
SERVER JS CODE
var net = require('net');
var server = net.createServer(function (socket) {
socket.write('server says this\r\n');
socket.pipe(socket);
});
server.on('connection', function(socket) {
socket.write("Echo server dot come\r\n"+socket.address().address);
console.log("Echo server dot come\r\n"+socket.address().address);
// socket.end();
socket.pipe(socket);
});
server.listen(5000);
You are trying to use WebScoket client with simple TCP server. This is a different protocols. You need to setup WebSocket server to make it work. You can use websocket module to do that. Look at the server example code here.

Change Google Analytics code using Plates

Is there a way to change the Google Analytics code included in a template using Plates?
For example, for the below template:
<!DOCTYPE html>
<html>
<head></head>
<body>
<script id="googleAnalytics">
var _gaq=[['_setAccount','GA_ACCOUNT_CODE'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>
I would like to use a different GA_ACCOUNT_CODE depending on the environment the code runs in.
Is this possible with Plates? If not, what is the common way one would solve this issue in NodeJS & Flatiron?
Plates' idea is great but far from complete. Here is a solution.
app.js
var fs = require('fs');
var plates = require('plates');
var flatiron = require('flatiron');
var app = flatiron.app;
app.use(flatiron.plugins.http);
app.router.get('/', function(){
var html = fs.readFileSync('index.html', 'utf-8');
var map = plates.Map();
var data = {"GA_ACCOUNT_CODE": "YOUR_CODE_FROM_CONFIG"}
map.where('data-ga').is('GA_ACCOUNT_CODE').insert('GA_ACCOUNT_CODE');
html = plates.bind(html, data, map);
this.res.html(html);
});
app.start(3000);
index.html
<!DOCTYPE html>
<html>
<head></head>
<body>
<script id="googleAnalytics" data-ga="GA_ACCOUNT_CODE">
var GA_ACCOUNT_CODE = document.getElementById('googleAnalytics').getAttribute('data-ga');
var _gaq=[['_setAccount',GA_ACCOUNT_CODE],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>
Another way would just be string.replace() like this:
var html = fs.readFileSync('index.html', 'utf-8');
html = html.replace('GA_ACCOUNT_CODE', 'YOUR_CODE_FROM_CONFIG');
this.res.html(html);
Have a look at cheerio for support. It's like any other css selector and dom manipulation frontend library, just backends.

Resources