Hi all I'm trying to send a javascript object through websockets:
the faye-websockets documentation says:
send(message) accepts either a String or a Buffer and sends a text or binary message over the connection to the other peer.
server side I'm using node and faye.
var WebSocket = require('faye-websocket');
var http = require('http');
var server = http.createServer();
server.addListener('upgrade', function(request, socket, head) {
var ws = new WebSocket(request, socket, head);
ws.send({topic:'handshake', data:'sdf487rgiuh7'});
});
server.listen(8000);
client side:
<script>
var ws = new WebSocket('ws://localhost:8000');
ws.onmessage = function(e) {
console.log(e.data); //prints [Object object] string and not the object
};
</script>
what is my error? Thanks
WebSockets support sending and receiving: strings, typed arrays (ArrayBuffer) and Blobs. Javascript objects must be serialized to one of the above types before sending.
To send an object as a string you can use the builtin JSON support:
ws.send(JSON.stringify(object));
To send an object as a typed array you can use a javascript BSON library such as this one:
ws.send(BSON.serialize(object));
When you receive a WebSocket message you will need to deserialize it.
To deserialize a JSON string from a WebSocket message:
ws.onmessage = function (e) {
var object = JSON.parse(e.data);
...
};
If you are using binary messages over WebSocket, then first you should set the binaryType attribute in order to receive all binary messages as typed arrays:
ws.binaryType = "arraybuffer";
Then the deserialization will look like this:
ws.onmessage = function (e) {
var object = BSON.deserialize(e.data);
...
};
Here is a blog post about using BSON in Javascript;
I'm basically working with Socket.IO, but it looks like you need to stringify your data in the server and parse it in the client like so:
in the server:
ws.send(JSON.stringify({topic:'handshake', data:'sdf487rgiuh7'}));
in the client:
console.log(JSON.parse(e.data));
Client:
const bson = new BSON();
ws.binaryType = 'arraybuffer';
ws.onmessage = function(event) {
console.log(bson.deserialize(Buffer.from(event.data)));
}
Server:
const data = bson.serialize({ ... });
ws.send(data);
add a function called json to the websocket object that transform in json and send the object passed by parameter
ws.json = (obj) => ws.send(JSON.stringify(obj));
ws.json({ message: "hello" });
Related
I am currently developing a NodeJS project with strong-soap library to receive and transmit SOAP requests and responses. Before asking question, i want to present code sample to ask my question efficiently.
server.js
//Address of this project is http://localhost:8080
const soap = require('strong-soap');
const http = require('http');
const fs = require('fs');
let myService = { //My SOAP server's service (group of methods)
Method:
function(data) //My question literally and directly related with data
{
//... Function content.
}
};
let xmlFile = fs.readFileSync('sample.wsdl');
let path = '/wsdl';
http.createServer(function (req, res) {
let soapServer = soap.listen(server, '/wsdl', myService, xmlFile);
}).listen(8080);
Assume that i have a server with codebase which is is seen above. And assume that have another Node.js project (or another .js file) which send request and transmit response from this server.
client.js
const soap = require('strong-soap');
soap.createClient('http://localhost:8080/wsdl', {forceSoap12Headers: true}, function(error, client){
if(error)
{
reject(error);
//res.sendStatus(404);
//console.log(error);
}
else{
client.Method(requestArgs, function(err, result, envelope) {
//I want to be able to sent an XML data as requestArgs
// Result in SOAP envelope body which is the wrapper element.
// In this case, result object corresponds to GetCityForecastByZIPResponse.
console.log(JSON.stringify(result));
}, null, customRequestHeader);
}
});
My question is: how i can send an XML in client.js? Or how i can receive requests in XML format without any problem in server.js? Most probably, i will deal with raw XML requests, and i want to deal with both XML and JSON requests? Help me developers!
i was in the process of answering this question
Retrieving the http.ServerResponse body
im trying to capture the raw string of an https request and response, for http it works fine
var http = require('http');
var util = require('util');
var req,res;
var server = http.createServer(onrequest);
server.listen(81);
server.on('connection',socket=>{
console.log('*** connection ***');
req = '';
res = '';
socket.on('data',data=>{
req += data.toString();
});
var write = socket.write
socket.write=function(data,encoding,callback){
res += data.toString();
write.apply(socket,arguments);
}//write
});
function onrequest(request,response){
console.log('*** request : '+request.url+' ***');
response.on('finish',()=>{
console.log('--- request ---');
console.log('['+req+']');
console.log();
console.log('--- response ---');
console.log('['+res+']');
});
request.on('data',data=>{});
request.on('end',()=>response.end('Hi. This is my http response.'));
}//onresquest
simplifying things using a single curl request
curl http://localhost:81/
gives the required data, congrats i thought onto my project and .. nope
when using https with the following code
var key; // = .....
var cert; // = ....
var server = https.createServer({key,cert},onrequest);
and again using curl
curl -k https://localhost:81/
no data is logged, the problem is this
on the connection event the socket passed is of type "socket" presumably a net.socket
the socket that is passed to the onrequest function is of type "tlssocket"
so i thought maybe i could use the underlying "duplex" which they do both share, however when i try to add the on data event to the duplex, with either
//on connection
var duplex = socket.__proto__;
duplex.on('data',data=>{
or
duplex.on.call(duplex,'data',data=>
it fails at Node.js JavaScript runtime
does anybody know how to get further than this?
related questions :
Get raw HTTP response in NodeJS
How can I get the raw HTTP message body using the request library in Node.js?
okey dokey
the solution is to use the "secureConnection" event, like so :
var https = require('https');
var req,res;
var key; // = ...
var cert; // = ...
var server = https.createServer({key,cert},onrequest);
server.listen(81);
server.on('secureConnection',socket=>{
console.log('*** connection ***');
req = '';
res = '';
socket.on('data',data=>{
req += data.toString();
});
var write = socket.write
socket.write=function(data,encoding,callback){
res += data.toString();
write.apply(socket,arguments);
}//write
});
function onrequest(request,response){
console.log('*** request : '+request.url+' ***');
response.on('finish',()=>{
console.log('--- request ---');
console.log('['+req+']');
console.log();
console.log('--- response ---');
console.log('['+res+']');
});
request.on('data',data=>{});
request.on('end',()=>response.end('Hi. This is my http response.'));
}//onresquest
this can be seen implemented
github: simple-server - no dependencies
Is there a way to view the complete raw HTTP request and response to make debugging easier?
Here is the node module ( https://www.npmjs.com/package/node-rest-client ) and an example.
var Client = require('node-rest-client').Client;
client = new Client();
args = {
path:{"p1":"1234", "p2":"abcd"}
headers:{"Authorization":"01234567890"}
}
client.get("http://example.com/${p1}/${p2}", args, function(data, response){
// parsed response body as js object
console.log(data);
// raw response
console.log(response);
}).on('error',function(err){
console.log('something went wrong on the request', err.request.options);
});
according to source code, the Client.get() function returns a regular ol' request object created (eventually, under the hood) by node's http or https module. So try examining the return value of client.get() and seeing what's inside.
I want to send ZMQ message inside app.get but when running I throw error:
events.js:72
throw er; // Unhandled 'error' event
^
ReferenceError: res is not defined
My running code:
var zmq = require('zmq'),
zreq = zmq.socket('req'),
app = express();
zreq.connect('tcp://localhost:5559');
zreq.on('message', function (msg) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.send(msg);
});
app.get('/words', function (req, res) {
zreq.send('nodejs');
//I think it should have something like zreqCallback(req)?
});
The problem is, as the error indicates, that you don't have access to the res object from the message event handler on your req socket. What you need is a way to link the message in that event handler to your res object. You're not going to be able to do that (easily) without support from the other end of that socket.
The basic idea is to associate a unique id with each message you send over zmq and include it in the message sent through the req socket and the reply that comes back from the rep socket. Then also associate the res object with the same message id.
I usually use node-uuid for unique id generation. You'll also need a way to easily encode / decode your messages (it looks like you're just sending straight strings at the moment). The built in JSON parser works fine for that, or you could use something more compact like bencode or protobuf. Be sure to pick something that both ends of the socket can work with.
You're code would look something like this:
Note: I'm assuming we're using node-uuid and JSON. Also, I'm not putting any error handling or sanity checks in here; don't forget that stuff.
var zmq = require('zmq'),
uuid = require('node-uuid'),
zreq = zmq.socket('req'),
app = express();
var responses = {};
zreq.connect('tcp://localhost:5559');
zreq.on('message', function (data) {
data = JSON.parse(data);
var msgId = data.id;
var res = responses[msgId];
res.writeHead(200, { 'Content-Type': 'application/json' });
res.send(data.message);
responses[msgId] = null;
});
app.get('/words', function (req, res) {
var msgId = uuid.v4();
var data = { id: msgId, message: 'nodejs' };
responses[msgId] = res;
zreq.send(JSON.stringify(data));
});
On the other end (I'll just assume it's also written in node for the purpose of this example):
var zmq = require('zmq');
zrep = zmq.socket('rep');
zrep.bind('tcp://localhost:5559');
zrep.on('message', function(data) {
data = JSON.parse(data);
var msgId = data.id;
var msg = data.message;
// Do whatever you were doing before to process the message
// We'll say it ends up in a "results" variable
var response = { id: msgId, message: results };
zrep.send(JSON.stringify(response));
});
I'm using Node.js and connect to create a simple web server. I have something similar to the following code and I can't figure out how to access the actual request message body from the request object. I'm new to this so bear with me. I'm also taking out some of the stuff that's not necessary for the example.
function startServer(dir) {
var port = 8888,
svr = connect().use(connect.static(dir, {"maxAge" : 86400000}))
.use(connect.directory(dir))
/*
* Here, I call a custom function for when
* connect.static can't find the file.
*/
.use(custom);
http.createServer(svr).listen(port);
}
function custom(req, res) {
var message = /* the message body in the req object */;
// Do some stuff with message...
}
startServer('dirName');
Make sense? I've tried logging that object to the console and it is full of TONS of stuff. I can easily see headers in there plus the request URL and method. I just can't seem to isolate the actual message body.
You should include the connect.bodyParser middleware as well:
svr = connect().use(connect.static(dir, {"maxAge" : 86400000}))
.use(connect.directory(dir))
.use(connect.bodyParser())
.use(custom);
That will provide the parsed message body as req.body to your handler.
If you want the raw message body, you shouldn't use it but instead read the req stream yourself:
function custom(req, res) {
var chunks = [];
req.on('data', function(chunk) {
chunks.push(chunk);
});
req.on('end', function() {
var rawbody = Buffer.concat(chunks);
...do stuff...
// end the request properly
res.end();
});
}
if(req.method == "POST"){
var body = '';
req.on('data', function(data){
body += data;
});
}
Then body should contain your message if you posted correctly.
A better idea would be to use Express, then use the bodyparser middleware - which will give you this functionality out of the box without worrying about somebody hammering your server. The code above has NO functionality to worry about attacks - but it will get you started.