nodejs getting raw https request and response - node.js

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

Related

Node.js blockchain bitcoin api

So I want to use this: (taken from their API site -> node.js documentation)
https://github.com/blockchain/api-v1-client-node
Recieving payments:
https://github.com/blockchain/api-v1-client-node/blob/master/docs/Receive.md
var blockchain = require('blockchain.info');
var identifier = 'myidentifier';
var password = 'mypassword';
var myWallet = new blockchain.MyWallet(identifier, password);
var myBTCadress = '14Q3ufL1BUHtWskBKtsshVDATRY65TaJMB';
Ok, so the recieving part:
var receive = new blockchain.Receive( [confirmations: 1], ? ); // What do I need to put here?
Documentation says:
callbackURL: the url to which the callback should be sent (string)
I don't understand what URL it should go to?!
The callback URL should be the one that redirects back to your site. So setup a callback url with blockchain like...
https://www.yoursite.com/callback/blockchain
Assuming you are using something like express in your app make a route like so.
app.get('/callback/blockchain', function (req, res) {
// Stuff here
});
you will prob need to include
var https = require('https');
That way then you can set up your logic inside for example...
// Stuff here
var options = {
host : 'api.blockchain.info',
path : '/some/path/',
port : 443,
method : 'GET'
}
var request = https.request(options, function(response){
var body = ""
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
res.send(JSON.parse(body));
});
});
request.on('error', function(e) {
console.log('Problem with request: ' + e.message);
});
request.end();
That will for example output you request in json on whatever page you have your app.get('whateverurl') set to.

How to modify (or just read) request stream before it is piped?

I have following code:
app.post('/someurl',function(req,res,next){
var request = require('request').post('/otherurl');
var response = '';
request.on('data',function(chunk){
response += chunk;
});
var pipe = req.pipe(parser).pipe(request);
request.on('end',function(){
var res2 = pipe.response;
var obj = JSON.parse(response);
res.json(obj);
});
});
So it just pipes POST request to other url. What I need is to know body of the piped request. So I added this (this code should do nothing):
var Transform = require('stream').Transform;
var parser = new Transform();
parser._transform = function(data, encoding, done) {
this.push(data);
done();
};
and changed req.pipe(request) to req.pipe(parser).pipe(request). The problem is that this does not work - req is not piped to req, but only to parser...
The problem was with Authorization - actually req.pipe(parser).pipe(request) worked but it returned 401 Authorization error. The problem is how I can pass Authorization header to the piped request?

Node.js and the connect module: How do I get the message out of a request object sent to a web server

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.

sending a javascript object through websockets with faye

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" });

request.on("response",[…]) never gets fired

I'm currently messing around with NodeJS and try to use the Twitter-Search API. With curl it works fine - so there's nothing wrong with my firewall or whatever. Yet, I never get a response within NodeJS.
var sys = require("sys"),
http = require("http"),
events = require("events");
sys.puts("Hi there… ");
var client = http.createClient(80, "search.twitter.com"),
body = "",
query = "foobar";
function getResults() {
sys.puts("fetching for "+query);
var request = client.request("GET", "/search.json?q="+query);
request.on("response", function(data){
/* this somehow never gets fired :( */
sys.puts("BODY:"+ data);
});
}
var interval = setInterval(getResults, 5000);
And the URL is also working.
Any hints or solutions are welcome!
Thanks in advance.
You never send the request.
You need to use request.end()
NOTE: the request is not complete. This method only sends the header of the request. One needs to call request.end() to finalize the request and retrieve the response. (This sounds convoluted but it provides a chance for the user to stream a body to the server with request.write().)
Also the response event'S parameter is the response object NOT the body. You need to set the data event on the response object and then listen for the end event to make sure you got all the data.
request.on('response', function (response) {
var body = '';
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
console.log('BODY: ' + body);
});
});
request.end(); // start the request
See: http://nodejs.org/api/http.html#http_class_http_clientrequest
A few more tips
You might want to use querystring.escape to urlencode your search parameter
You also need to set the Host header, otherwise Twitter will return a 404
Fixed code:
var querystring = require('querystring');
...
var request = client.request("GET", "/search.json?q=" + querystring.escape(query), {'Host': 'search.twitter.com'});

Resources