I am very new to node.js and I want to receive on an HTML5 website JSON from a PostgreSQL database. So, on the server side I use node-postgres module for DB connection and also express module for communication. The PostgreSQL query is returning a JSON object.
Server-side:
var express = require('express');
var app = express();
app.get('/data', function(req, res){
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/spots";
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
res.send('could not connect to postgres');
}
client.query('SELECT * from spots_json where id=3276', function(err, result) {
if(err) {
res.send('error running query');
}
res.send(JSON.stringify(result.rows[0].json));
client.end();
});
});
});
app.listen(3000);
Client-side:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js" ></script>
<script>
$.get('http://localhost:3000/data',{}, function(data){
alert(JSON.parse(data));
},"json");
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
If I navigate to http://localhost:3000/data on the browser I get:
{\"type\":\"Point\",\"coordinates\":[-2.994783,43.389217]}
So I see that the server is sending the stringified JSON properly, but on the client I always get null data. I must have some misconception.
Ok this is how my code is so far, for anyone that could help:
serverside
var express = require('express');
var app = express();
app.get('/data', function(req, res){
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/spots";
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
res.send('could not connect to postgres');
}
client.query('SELECT * from spots_json where id=3276', function(err, result) {
if(err) {
res.send('error running query');
}
res.set("Content-Type", 'text/javascript'); // i added this to avoid the "Resource interpreted as Script but transferred with MIME type text/html" message
res.send(JSON.stringify(result.rows[0].json));
client.end();
});
});
});
app.listen(3000);
clientside
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"></meta>
<meta charset="utf-8"></meta>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js" ></script>
<script>
$.get('http://localhost:3000/data?callback=?',{}, function(data){
alert(data.type);
},"json");
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The client is now executed on http://localhost:8888/prueba/prueba.html
Im getting a js with the following Response:
"{\"type\":\"Point\",\"coordinates\":[-2.994783,43.389217]}"
The Response can be seen in the following screenshot:
https://www.dropbox.com/s/zi4c5pqnbctf548/pantallazo.png
But now the alert isn't even shown...
I think i need some light with this.
The data is already an object when you get it, not a string. So JSON.parse fails because you gave it an object when it was expecting a string. To verify, change
alert(JSON.parse(data));
to
alert(data.type);
and you should get "Point"
The reason you already have an object is because of the "json" parameter you provided to $.get. If you change that to "html" you will get a string back instead which you could then parse out into a JSON object.
I think you should not try to stringify your result when you put it in the response object.
Just put it entirely it will automaticaly that way :
res.set("Content-Type", 'application/json');
res.json(result.rows[0].json);
That is the right way to send information through REST APIs.
Then in your client side code, I don't know how it works but it should accept json natively.
Related
I have two clients which can interchange some data over socket.io. I also have a server. What i need to do is i want to send data from client 1 to client 2 over a socket and i am unable to figure out that how i can achieve it.Please note that client 1 and client 2 are different html pages.
Server.JS
var express = require('express');
var app = express();
var fs = require('fs');
var path = require('path');
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
var ip=process.env.IP||"192.168.1.5";
app.use(express.static(__dirname));
server.listen(port,ip, function () {
console.log('Server listening at port %d ', port);
});
app.get('/index', function(req, res) {
res.sendFile(path.join(__dirname,'/test.html'));
})
app.get('/index1', function(req, res) {
res.sendFile(path.join(__dirname,'/test1.html'));
})
io.on('connection', function (socket) {
socket.on('broadcast', function (message) {
console.log(message);
socket.broadcast.emit('message', message);
});
console.log("connected");
});
Client1.JS
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script >
var socket = io.connect();
socket.emit('broadcast',"Broadcasting Message");
socket.on('message', function (data) {
alert(data)
});
</script>
</body>
Client2.JS
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script >
var socket = io.connect();
socket.on('message', function (data) {
alert(data)
//socket.emit('message',"Hello world");
});
</script>
</body>
Ok, here is what I did on my local and you may change it by your needs.
server.js
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('broadcast', function (message) {
console.log(message);
socket.broadcast.emit('message', message);
});
console.log("connected");
});
client1.js
var socket = io.connect('ws://127.0.0.1');
socket.emit('broadcast',"Broadcasting Message");
socket.on('message', function (data) {
$('#client1').html(data);
});
client2.js
var socket = io.connect('ws://127.0.0.1');
socket.on('message', function (data) {
$('#client2').html(data);
});
index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src='https://code.jquery.com/jquery-1.12.4.min.js'></script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="client1.js"></script>
<script type="text/javascript" src="client2.js"></script>
</head>
<body>
<div> <h1> CLIENT 1 </h1><div id="client1"></div></div>
<div> <h1> CLIENT 2 </h1><div id="client2"></div></div>
</body>
</html>
On a termminal after you run, node server.js and reload your page, you will see client2 will have Broadcasting message html appended
Make sure to pass the URL to the server when instantiating WS on the client side... for example var socket = io.connect('http://localhost');
On the server side, each WS connection with each client is a unique instance. That is to say that for this purpose you must be deliberate about which WS connection you target when emitting events.
The first thing to solve is how to associate WS connection instances with specific clients. The answer to this is to use a map/dictionary/plain ol' javascript object with some sort of unique client identifier as the key and the instance of the WS connection as the value. Pseudo-code:
let connections = { 'client1': WSinstance, 'client2': WSinstance };
You would add to this object every time you create a new WS instance. Assuming you have a way to uniquely identify a client and that is stored in the variable clientId, you could do the following:
io.on('connection', function (socket) {
connections[clientId] = socket;
}
Now if you want to emit a message to just client1 you can use the WS instance associated with them by grabbing it from the object connections.client1 or if you want to target client2 connections.client2
When I execute the following code, I get the error: Reference Error: Watershed is not defined. How can I define it? Do I need a module to be installed for it?
var restify=require('restify');
var ws= new Watershed();
var server=restify.createServer();
server.get('websocket/attach', function upgradeRoute(req, res, next){
if(!res.claimUpgrade){
next(new Error("Connection must be upgraded."));
return;
}
var upgrade=res.claimUpgrade();
var shed=ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function (msg){
console.log("The message is: "+msg);
});
shed.send("hello there");
next(false);
});
server.listen(8081, function(){
console.log('%s listening at %s', server.name, server.url);
});
There is also a section of the restify doc that mentioned how to handle the ability to upgrade sockets. I just struggled with this for an emarrassingly long time and thought I'd share the simple solution. In addtion the #Dibu Raj reply, you also need to create your restify server with the handleUpgrades option set to true. Here is a complete example to make restify work with websocket upgrades and watershed:
'use strict';
var restify = require('restify');
var watershed = require('watershed');
var ws = new watershed.Watershed();
var server = restify.createServer({
handleUpgrades: true
});
server.get('/websocket/attach', function (req, res, next) {
if (!res.claimUpgrade) {
next(new Error('Connection Must Upgrade For WebSockets'));
return;
}
console.log("upgrade claimed");
var upgrade = res.claimUpgrade();
var shed = ws.accept(req, upgrade.socket, upgrade.head);
shed.on('text', function(msg) {
console.log('Received message from websocket client: ' + msg);
});
shed.send('hello there!');
next(false);
});
//For a complete sample, here is an ability to serve up a subfolder:
server.get(/\/test\/?.*/, restify.serveStatic({
directory: './static',
default: 'index.html'
}));
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
For an html page to test your new nodejs websocket server: write this html below into a file at ./static/test/index.html - point your browser to http://localhost:8080/test/index.html - open your browser debug console to see the message exchange.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Socket test area</title>
<meta name="description" content="Web Socket tester">
<meta name="author" content="Tim">
</head>
<body>
Test Text.
<script>
(function() {
console.log("Opening connection");
var exampleSocket = new WebSocket("ws:/localhost:8080/websocket/attach");
exampleSocket.onopen = function (event) {
console.log("Opened socket!");
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
exampleSocket.onmessage = function (event) {
console.log("return:", event.data);
exampleSocket.close();
}
})();
</script>
</body>
</html>
Your browser log will look something like this:
07:05:05.357 index.html:18 Opening connection
07:05:05.480 index.html:22 Opened socket!
07:05:05.481 index.html:26 return: hello there!
And your node log will look like:
restify listening at http://[::]:8080
client connected!
Rest service called started
upgrade claimed
Received message from websocket client: Here's some text that the server is urgently awaiting!
Documentation for this found at:
http://restify.com/#upgrade-requests
You should include the watershed library
var Watershed = require('lib/watershed').Watershed;
I'm begginer in Node.js or websocket. I have problem:
My HTML code:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
"use strict";
var gniazdo = new WebSocket('ws://localhost:3000');
gniazdo.onopen = function(){
console.log('Połączono');
};
gniazdo.onmessage = function(m){
console.log(m.data);
};
</script>
</body>
</html>
My Node.js code:
var io = require('socket.io')(3000);
io.on('connection', function(socket){
console.log('a user connected');
});
I have error in console:
WebSocket connection to 'ws://localhost:3000/' failed: Connection closed before receiving a handshake response
Help plz :)
Your client is using WebSockets, but Socket.IO has its own protocol (that may be transported over WebSockets, but it can also be transported over other protocols). Change your client to use Socket.IO's own client:
<script src="https://cdn.socket.io/socket.io-1.1.0.js"></script>
<script>
'use strict';
var gniazdo = io('ws://localhost:3000');
gniazdo.on('connect', function () {
console.log('Połączono');
gniazdo.on('message', function (m) {
console.log(m.data);
});
});
</script>
i write a node program,and i encounter a big difficult.
the server side code is below:
var express=require("express");
var app=express();
var socketio=require("socket.io");
var server=require("http").Server(app);
var ws=socketio.listen(server);
app.use(express.static('public'));
app.listen(3000);
ws.on('connection',function(socket){
socket.on("message",function(msg){
console.log("got:"+msg);
socket.send('pong');
});
});
the client side code is below:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>websocket echo</title>
</head>
<body>
<h1>websocket echo</h1>
<h2>latency:<span id="latency"></span>ms</h2>
<script>
var lastMessage;
window.onload=function(){
//create socket
var ws=new WebSocket("ws://127.0.0.1:3000");
ws.onopen=function(){
//send first ping
ping();
};
// 监听Socket的关闭
ws.onclose = function(event) {
console.log('Client notified socket has closed',event);
};
ws.onmessage=function(ev){
console.log("got:"+ev.data);
document.getElementById("latency").innerHTML=new Date-lastMessage;
ping();
};
function ping(){
lastMessage= + new Date;
ws.send("ping");
}
}
</script>
</body>
</html>
there is the tip in chrome console:
WebSocket connection to 'ws://127.0.0.1:3000/' failed: Connection closed before receiving a handshake response (index):16
Client notified socket has closed CloseEvent
As mentioned in the comments this happens because socket.io should be connected with it's own client. You should either use websockets or socket.io on both sides.
I want to receive on an HTML5 website JSON from a PostgreSQL database. So, on the server side I use node-postgres module for DB connection and also express module for communication.
The problem is that in the html i am not seeing any alert when getting the data from the server. The alert isn't even thrown.
this is how my code is so far, for anyone that could help:
serverside
var express = require('express');
var app = express();
app.get('/data', function(req, res){
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/spots";
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
res.send('could not connect to postgres');
}
client.query('SELECT * from spots_json where id=3276', function(err, result) {
if(err) {
res.send('error running query');
}
res.set("Content-Type", 'text/javascript'); // i added this to avoid the "Resource interpreted as Script but transferred with MIME type text/html" message
res.send(JSON.stringify(result.rows[0].json));
client.end();
});
});
});
app.listen(3000);
clientside
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"></meta>
<meta charset="utf-8"></meta>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js" ></script>
<script>
$.get('http://localhost:3000/data?callback=?',{}, function(data){
alert(data.type);
},"json");
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The client is now executed on http://localhost:8888/prueba/prueba.html
Im getting a js with the following Response:
"{\"type\":\"Point\",\"coordinates\":[-2.994783,43.389217]}"
The Response can be seen in the following screenshot:
result.rows[0].json is not an object, it is a string. You don't need to stringify it:
res.send(result.rows[0].json);
Edit:
If you use two servers on different ports you will need to use JSONP. jQuery makes this simple on the client side, but you will need to implement it in your server (example):
if(req.query.callback) {
res.send(req.query.callback + '(' + result.rows[0].json + ');');
} else {
res.send(result.rows[0].json);
}
By the way, you need to return if you encounter an error in one of your callbacks to prevent subsequent code from being executed.
if(err) {
res.end('error message');
return;
// Or shorter: return res.end('error message');
}